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
openSUSE Build Service is sponsored by