File strongswan-ikev2-cavs.patch of Package strongswan.1492
diff -Nurp strongswan-5.1.3-orig/configure.ac strongswan-5.1.3/configure.ac
--- strongswan-5.1.3-orig/configure.ac 2014-04-14 14:20:17.000000000 +0200
+++ strongswan-5.1.3/configure.ac 2015-02-17 19:52:25.254719000 +0100
@@ -274,6 +274,7 @@ ARG_ENABL_SET([integrity-test], [enable
ARG_DISBL_SET([load-warning], [disable the charon plugin load option warning in starter.])
ARG_ENABL_SET([mediation], [enable IKEv2 Mediation Extension.])
ARG_ENABL_SET([unwind-backtraces],[use libunwind to create backtraces for memory leaks and segfaults.])
+ARG_ENABL_SET([cavs], [enable CAVS test helper binary.])
# compile options
ARG_ENABL_SET([coverage], [enable lcov coverage report generation.])
ARG_ENABL_SET([leak-detective], [enable malloc hooks to find memory leaks.])
@@ -1383,6 +1384,7 @@ AM_CONDITIONAL(USE_SILENT_RULES, test x$
AM_CONDITIONAL(COVERAGE, test x$coverage = xtrue)
AM_CONDITIONAL(USE_TKM, test x$tkm = xtrue)
AM_CONDITIONAL(USE_CMD, test x$cmd = xtrue)
+AM_CONDITIONAL(USE_CAVS, test x$cavs = xtrue)
# ========================
# set global definitions
@@ -1436,6 +1438,7 @@ AC_CONFIG_FILES([
src/Makefile
src/include/Makefile
src/libstrongswan/Makefile
+ src/libstrongswan/cavs/Makefile
src/libstrongswan/plugins/aes/Makefile
src/libstrongswan/plugins/cmac/Makefile
src/libstrongswan/plugins/des/Makefile
diff -Nurp strongswan-5.1.3-orig/src/libstrongswan/cavs/Makefile.am strongswan-5.1.3/src/libstrongswan/cavs/Makefile.am
--- strongswan-5.1.3-orig/src/libstrongswan/cavs/Makefile.am 1970-01-01 01:00:00.000000000 +0100
+++ strongswan-5.1.3/src/libstrongswan/cavs/Makefile.am 2015-02-17 19:53:35.449035000 +0100
@@ -0,0 +1,7 @@
+AM_CPPFLAGS = \
+ -I$(top_srcdir)/src/libstrongswan
+
+ipsec_PROGRAMS = strongswan_ikev2_cavs
+strongswan_ikev2_cavs_SOURCE = strongswan_ikev2_cavs.c
+
+strongswan_ikev2_cavs_LDFLAGS = -lstrongswan -L../.libs
diff -Nurp strongswan-5.1.3-orig/src/libstrongswan/cavs/strongswan_ikev2_cavs.c strongswan-5.1.3/src/libstrongswan/cavs/strongswan_ikev2_cavs.c
--- strongswan-5.1.3-orig/src/libstrongswan/cavs/strongswan_ikev2_cavs.c 1970-01-01 01:00:00.000000000 +0100
+++ strongswan-5.1.3/src/libstrongswan/cavs/strongswan_ikev2_cavs.c 2015-02-17 19:53:35.455047000 +0100
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2015, Stephan Mueller <smueller@chronox.de>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, and the entire permission notice in its entirety,
+ * including the disclaimer of warranties.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior
+ * written permission.
+ *
+ * ALTERNATIVELY, this product may be distributed under the terms of
+ * the GNU General Public License, in which case the provisions of the GPL2
+ * are required INSTEAD OF the above restrictions. (This clause is
+ * necessary due to a potential bad interaction between the GPL and
+ * the restrictions contained in a BSD-style copyright.)
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
+ * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <string.h>
+#include <getopt.h>
+
+#include "../../config.h"
+#include "utils/chunk.h"
+#include "crypto/prf_plus.h"
+
+static int bin_char(unsigned char hex)
+{
+ if (48 <= hex && 57 >= hex)
+ return (hex - 48);
+ if (65 <= hex && 70 >= hex)
+ return (hex - 55);
+ if (97 <= hex && 102 >= hex)
+ return (hex - 87);
+ return 0;
+}
+
+/*
+ * Convert hex representation into binary string
+ * @hex input buffer with hex representation
+ * @hexlen length of hex
+ * @bin output buffer with binary data
+ * @binlen length of already allocated bin buffer (should be at least
+ * half of hexlen -- if not, only a fraction of hexlen is converted)
+ */
+static void hex2bin(const char *hex, size_t hexlen,
+ unsigned char *bin, size_t binlen)
+{
+ size_t i = 0;
+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
+
+ for (i = 0; i < chars; i++) {
+ bin[i] = bin_char(hex[(i*2)]) << 4;
+ bin[i] |= bin_char(hex[((i*2)+1)]);
+ }
+}
+
+/*
+ * Allocate sufficient space for binary representation of hex
+ * and convert hex into bin
+ *
+ * Caller must free bin
+ * @hex input buffer with hex representation
+ * @hexlen length of hex
+ * @bin return value holding the pointer to the newly allocated buffer
+ * @binlen return value holding the allocated size of bin
+ *
+ * return: 0 on success, !0 otherwise
+ */
+static int hex2bin_alloc(const char *hex, size_t hexlen,
+ unsigned char **bin, size_t *binlen)
+{
+ unsigned char *out = NULL;
+ size_t outlen = 0;
+
+ if (!hexlen)
+ return -EINVAL;
+
+ outlen = (hexlen + 1) / 2;
+
+ out = calloc(1, outlen);
+ if (!out)
+ return -errno;
+
+ hex2bin(hex, hexlen, out, outlen);
+ *bin = out;
+ *binlen = outlen;
+ return 0;
+}
+
+static char hex_char_map_l[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
+static char hex_char_map_u[] = { '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
+static char hex_char(unsigned int bin, int u)
+{
+ if (bin < sizeof(hex_char_map_l))
+ return (u) ? hex_char_map_u[bin] : hex_char_map_l[bin];
+ return 'X';
+}
+
+/*
+ * Convert binary string into hex representation
+ * @bin input buffer with binary data
+ * @binlen length of bin
+ * @hex output buffer to store hex data
+ * @hexlen length of already allocated hex buffer (should be at least
+ * twice binlen -- if not, only a fraction of binlen is converted)
+ * @u case of hex characters (0=>lower case, 1=>upper case)
+ */
+static void bin2hex(const unsigned char *bin, size_t binlen,
+ char *hex, size_t hexlen, int u)
+{
+ size_t i = 0;
+ size_t chars = (binlen > (hexlen / 2)) ? (hexlen / 2) : binlen;
+
+ for (i = 0; i < chars; i++) {
+ hex[(i*2)] = hex_char((bin[i] >> 4), u);
+ hex[((i*2)+1)] = hex_char((bin[i] & 0x0f), u);
+ }
+}
+
+struct kdf_cavs {
+ unsigned char *gir;
+ size_t girlen;
+ unsigned char *girnew;
+ size_t girnewlen;
+ unsigned char *Ni;
+ size_t Nilen;
+ unsigned char *Nr;
+ size_t Nrlen;
+ unsigned char *SPIi;
+ size_t SPIilen;
+ unsigned char *SPIr;
+ size_t SPIrlen;
+ /*
+ * according to src/libstrongswan/crypto/prfs/prf.h:
+ * PRF_HMAC_SHA1 2
+ * PRF_HMAC_SHA2_256 -> 5
+ * PRF_HMAC_SHA2_384 -> 6
+ * PRF_HMAC_SHA2_512 -> 7
+ */
+ unsigned int hash_algo;
+
+ size_t dkmlen;
+};
+
+/** plugins to load */
+#undef PLUGINS
+#define PLUGINS "openssl"
+
+static int ikev2kdf_cavs(struct kdf_cavs *test)
+{
+ int ret = -1;
+ chunk_t skeyseed;
+ chunk_t dkm;
+ chunk_t child_dkm;
+ chunk_t nonce_r = chunk_create(test->Nr, test->Nrlen);
+ chunk_t nonce_i = chunk_create(test->Ni, test->Nilen);
+ chunk_t fixed_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ chunk_t full_nonce = chunk_cat("cc", nonce_i, nonce_r);
+ chunk_t spi_i = chunk_create(test->SPIi, test->SPIilen);
+ chunk_t spi_r = chunk_create(test->SPIr, test->SPIrlen);
+ chunk_t prf_plus_seed = chunk_cat("ccc", full_nonce, spi_i, spi_r);
+ chunk_t secret = chunk_create(test->gir, test->girlen);
+ chunk_t child_seed = chunk_cat("ccc", secret, nonce_i, nonce_r);
+
+ /* rekey */
+ chunk_t girnew = chunk_create(test->girnew, test->girnewlen);
+ chunk_t secret_new = chunk_cat("cc", girnew, full_nonce);
+ pseudo_random_function_t prf_alg = test->hash_algo;
+ prf_t *prf = NULL;
+ prf_plus_t *prf_plus = NULL;
+
+ chunk_t skd;
+
+#define HEXLEN 2048
+ char hex[HEXLEN];
+
+ /* initialize library */
+ if (!library_init(NULL, "cavs"))
+ {
+ library_deinit();
+ goto out;
+ }
+ atexit(library_deinit);
+ lib->plugins->load(lib->plugins, PLUGINS);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+
+ if (!prf) {
+ printf("PRF not found\n");
+ goto out;
+ }
+
+ /****** from derive_ike_keys *****/
+ /* RFC 4306 section 2.14 */
+ /* SKEYSEED = prf(Ni | Nr, g^ir) */
+
+ if (!prf->set_key(prf, fixed_nonce))
+ goto out;
+ if (!prf->allocate_bytes(prf, secret, &skeyseed))
+ goto out;
+
+ /* {SK_d | SK_ai | SK_ar | SK_ei | SK_er | SK_pi | SK_pr } = prf+
+ (SKEYSEED, Ni | Nr | SPIi | SPIr ) */
+ if (!prf->set_key(prf, skeyseed))
+ goto out;
+ prf_plus = prf_plus_create(prf, TRUE, prf_plus_seed);
+
+ if (!prf_plus)
+ goto out;
+ /* PRF+ */
+ if (!prf_plus->allocate_bytes(prf_plus, test->dkmlen, &dkm))
+ goto out;
+ /* SK_d for child SA */
+ skd.ptr = dkm.ptr;
+ skd.len = prf->get_key_size(prf);
+
+ memset(hex, 0, HEXLEN);
+ bin2hex(skeyseed.ptr, skeyseed.len, hex, HEXLEN, 0);
+ printf("SKEYSEED = %s\n", hex);
+ memset(hex, 0, HEXLEN);
+ bin2hex(dkm.ptr, dkm.len, hex, HEXLEN, 0);
+ printf("DKM = %s\n", hex);
+
+
+ /******* from derive_child_keys *******/
+ /* RFC 4306 section 2.17 option 1 */
+ /* KEYMAT = prf+(SK_d, Ni | Nr) */
+ DESTROY_IF(prf_plus);
+ if (!prf->set_key(prf, skd)) {
+ printf("setkey for child failed\n");
+ goto out;
+ }
+ prf_plus = prf_plus_create(prf, TRUE, fixed_nonce);
+ if (!prf_plus->allocate_bytes(prf_plus, test->dkmlen, &child_dkm))
+ goto out;
+ memset(hex, 0, HEXLEN);
+ bin2hex(child_dkm.ptr, child_dkm.len, hex, HEXLEN, 0);
+ printf("DKM(Child SA) = %s\n", hex);
+
+ /******* from derive child keys ******/
+ /* RFC 4306 section 2.17 option 2 */
+ /* KEYMAT = prf+(SK_d, g^ir (new) | Ni | Nr ) */
+ DESTROY_IF(prf_plus);
+ chunk_free(&child_dkm);
+
+ if (!prf->set_key(prf, skd)) {
+ printf("setkey for child failed\n");
+ goto out;
+ }
+ prf_plus = prf_plus_create(prf, TRUE, secret_new);
+ if (!prf_plus->allocate_bytes(prf_plus, test->dkmlen, &child_dkm))
+ goto out;
+ memset(hex, 0, HEXLEN);
+ bin2hex(child_dkm.ptr, child_dkm.len, hex, HEXLEN, 0);
+ printf("DKM(Child SA D-H) = %s\n", hex);
+
+ /********* rekey derive_ike_keys *********/
+ /* RFC 4306 section 2.18 */
+ /* SKEYSEED = prf(SK_d (old), [g^ir (new)] | Ni | Nr) */
+ chunk_free(&skeyseed);
+ prf = lib->crypto->create_prf(lib->crypto, prf_alg);
+ if (!prf->set_key(prf, skd))
+ goto out;
+ if (!prf->allocate_bytes(prf, secret_new, &skeyseed))
+ goto out;
+ memset(hex, 0, HEXLEN);
+ bin2hex(skeyseed.ptr, skeyseed.len, hex, HEXLEN, 0);
+ printf("SKEYSEED(Rekey) = %s\n", hex);
+
+
+ chunk_free(&skeyseed);
+ chunk_free(&dkm);
+ chunk_free(&child_dkm);
+ DESTROY_IF(prf_plus);
+ chunk_free(&fixed_nonce);
+ chunk_free(&full_nonce);
+ chunk_free(&prf_plus_seed);
+ chunk_free(&child_seed);
+out: /* there is no proper deallocation in error case -- we do not care */
+ return ret;
+}
+
+static void usage(void)
+{
+ fprintf(stderr, "\nStrongswan KDF CAVS Test\n\n");
+ fprintf(stderr, "Usage:\n");
+ fprintf(stderr, "\t-g --gir\tDiffie-Hellman shared secret\n");
+ fprintf(stderr, "\t-n --girnew\tDiffie-Hellman shared secret (rekey)\n");
+ fprintf(stderr, "\t-a --ni\t\tNi value\n");
+ fprintf(stderr, "\t-b --nr\t\tNr value\n");
+ fprintf(stderr, "\t-c --spii\tSPIi value\n");
+ fprintf(stderr, "\t-d --spir\tSPIr value\n");
+ fprintf(stderr, "\t-l --dkmlen\tLength of DKM\n");
+ fprintf(stderr, "\t-h --hash\tHash algorithm:\n");
+ fprintf(stderr, "\t\t\t2 -> SHA-1\n");
+ fprintf(stderr, "\t\t\t5 -> SHA-256\n");
+ fprintf(stderr, "\t\t\t6 -> SHA-384\n");
+ fprintf(stderr, "\t\t\t7 -> SHA-512\n");
+}
+
+/*
+ * LD_LIBRARY_PATH="/usr/lib64/strongswan" ./strongswan-ikev2-cavs -g 4b2c1f971981a8ad8d0abeafabf38cf75fc8349c148142465ed9c8b516b8be52 -n 863f3c9d06efd39d2b907b97f8699e5dd5251ef64a2a176f36ee40c87d4f9330 -a 32b50d5f4a3763f3 -b 9206a04b26564cb1 -c 34c9e7c188868785 -d 3ff77d760d2b2199 -l 132 -h 2
+ *
+ * SKEYSEED = a9a7b222b59f8f48645f28a1db5b5f5d7479cba7
+DKM = a14293677cc80ff8f9cc0eee30d895da9d8f405666e30ef0dfcb63c634a46002a2a63080e514a062768b76606f9fa5e992204fc5a670bde3f10d6b027113936a5c55b648a194ae587b0088d52204b702c979fa280870d2ed41efa9c549fd11198af1670b143d384bd275c5f594cf266b05ebadca855e4249520a441a81157435a7a56cc4
+DKM(Child SA) = 8059e3ee8810e6c3a91bc8bcd2a7a41151b8d0e6ae239c7b38093ad85ef4c5811a8e7b5d1cdabd9560b2d5e092d1f24e2d4b85eccdf0ad0dc9abd94b51ee71814ca6dbc8bb51b6309f5b9545c7eb35cf5580b1e521a8fe20754a2d883ba0c2cf285f524aea6545b33106bc03e614296d319d41d4b50b3f510b1c0a22f3e664994d234cb4
+DKM(Child SA D-H) = bb43244c1860ad65ee1e211ffe8bb3661750c8f89cb9f547df7f4fa61d37301628190e38c66232eab4b3ab14c400a5197dd3730ed4820a8a10394d51e1c0400052f63ebd36b0e7ef53aaed31eba4a5080d7d4b5666023a8bbb5ffb7857240f9a05884d1b7d2f933708450b7b3288f1fc863ab49fa901227cffc06e27899c7054d56fd74c
+SKEYSEED(Rekey) = 63e81194946ebd05df7df5ebf5d8750056bf1f1d
+ */
+
+int main(int argc, char *argv[])
+{
+ struct kdf_cavs test;
+ int ret = 1;
+ int c = 0;
+
+ memset(&test, 0, sizeof(struct kdf_cavs));
+ while(1)
+ {
+ int opt_index = 0;
+ static struct option opts[] =
+ {
+ {"gir", 1, 0, 'g'},
+ {"girnew", 1, 0, 'n'},
+ {"ni", 1, 0, 'a'},
+ {"nr", 1, 0, 'b'},
+ {"spii", 1, 0, 'c'},
+ {"spir", 1, 0, 'd'},
+ {"dkmlen", 1, 0, 'l'},
+ {"hash", 1, 0, 'h'},
+ {0, 0, 0, 0}
+ };
+ c = getopt_long(argc, argv, "g:n:a:b:c:d:l:h:", opts, &opt_index);
+ if(-1 == c)
+ break;
+ switch(c)
+ {
+ case 'g':
+ ret = hex2bin_alloc(optarg, strlen(optarg),
+ &test.gir, &test.girlen);
+ if (ret)
+ goto out;
+ break;
+ case 'n':
+ ret = hex2bin_alloc(optarg, strlen(optarg),
+ &test.girnew,
+ &test.girnewlen);
+ if (ret)
+ goto out;
+ break;
+ case 'a':
+ ret = hex2bin_alloc(optarg, strlen(optarg),
+ &test.Ni,
+ &test.Nilen);
+ if (ret)
+ goto out;
+ break;
+ case 'b':
+ ret = hex2bin_alloc(optarg, strlen(optarg),
+ &test.Nr,
+ &test.Nrlen);
+ if (ret)
+ goto out;
+ break;
+ case 'c':
+ ret = hex2bin_alloc(optarg, strlen(optarg),
+ &test.SPIi,
+ &test.SPIilen);
+ if (ret)
+ goto out;
+ break;
+ case 'd':
+ ret = hex2bin_alloc(optarg, strlen(optarg),
+ &test.SPIr,
+ &test.SPIrlen);
+ if (ret)
+ goto out;
+ break;
+ case 'l':
+ test.dkmlen = strtoul(optarg, NULL, 10);
+ break;
+ case 'h':
+ test.hash_algo = atoi(optarg);
+ switch (test.hash_algo) {
+ case 2:
+ case 5:
+ case 6:
+ case 7:
+ continue;
+ }
+ /* fall through */
+ default:
+ usage();
+ goto out;
+ }
+ }
+
+ ret = ikev2kdf_cavs(&test);
+
+out:
+ if (test.gir)
+ free(test.gir);
+ if (test.girnew)
+ free(test.girnew);
+ if (test.Ni)
+ free(test.Ni);
+ if (test.Nr)
+ free(test.Nr);
+ if (test.SPIi)
+ free(test.SPIi);
+ if (test.SPIr)
+ free(test.SPIr);
+ return ret;
+}
diff -Nurp strongswan-5.1.3-orig/src/libstrongswan/Makefile.am strongswan-5.1.3/src/libstrongswan/Makefile.am
--- strongswan-5.1.3-orig/src/libstrongswan/Makefile.am 2014-03-31 13:02:50.000000000 +0200
+++ strongswan-5.1.3/src/libstrongswan/Makefile.am 2015-02-17 19:53:09.420546000 +0100
@@ -506,4 +506,9 @@ endif
if MONOLITHIC
SUBDIRS += .
endif
+
+if USE_CAVS
+ SUBDIRS += cavs
+endif
+
SUBDIRS += tests