From: Andreas Steffen Date: Wed, 25 Feb 2015 20:12:30 +0000 (+0100) Subject: Allow SHA256 and SHA384 data hash for BLISS signatures. X-Git-Tag: 5.3.0dr1~62 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=27bd0fed93ef2e2e59895efecf5c039f373ea278;p=thirdparty%2Fstrongswan.git Allow SHA256 and SHA384 data hash for BLISS signatures. The default is SHA512 since this hash function is also used for the c_indices random oracle. --- diff --git a/NEWS b/NEWS index e43159f5d5..eb9cba569b 100644 --- a/NEWS +++ b/NEWS @@ -19,6 +19,10 @@ Windows 7 IKEv2 clients, which announces its services over the tunnel if the negotiated IPsec policy allows it. +- Upgrade of the BLISS post-quantum signature algorithm to the improved BLISS-B + variant. Can be used in conjunction with the SHA256, SHA384 and SHA512 hash + algorithms with SHA512 being the default. + strongswan-5.2.2 ---------------- diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt index bf392dad28..5e49074784 100644 --- a/src/libstrongswan/asn1/oid.txt +++ b/src/libstrongswan/asn1/oid.txt @@ -224,6 +224,8 @@ 0x08 "BLISS-B_IV" OID_BLISS_B_IV 0x03 "blissSigType" 0x01 "BLISS-with-SHA512" OID_BLISS_WITH_SHA512 + 0x02 "BLISS-with-SHA384" OID_BLISS_WITH_SHA384 + 0x03 "BLISS-with-SHA256" OID_BLISS_WITH_SHA256 0x89 "" 0x31 "" 0x01 "" diff --git a/src/libstrongswan/credentials/keys/public_key.c b/src/libstrongswan/credentials/keys/public_key.c index 40d96100e5..c342ac128a 100644 --- a/src/libstrongswan/credentials/keys/public_key.c +++ b/src/libstrongswan/credentials/keys/public_key.c @@ -43,6 +43,8 @@ ENUM(signature_scheme_names, SIGN_UNKNOWN, SIGN_BLISS_WITH_SHA512, "ECDSA-256", "ECDSA-384", "ECDSA-521", + "BLISS_WITH_SHA256", + "BLISS_WITH_SHA384", "BLISS_WITH_SHA512", ); @@ -136,6 +138,10 @@ signature_scheme_t signature_scheme_from_oid(int oid) case OID_BLISS_PUBLICKEY: case OID_BLISS_WITH_SHA512: return SIGN_BLISS_WITH_SHA512; + case OID_BLISS_WITH_SHA256: + return SIGN_BLISS_WITH_SHA256; + case OID_BLISS_WITH_SHA384: + return SIGN_BLISS_WITH_SHA384; default: return SIGN_UNKNOWN; } diff --git a/src/libstrongswan/credentials/keys/public_key.h b/src/libstrongswan/credentials/keys/public_key.h index ef681c9708..9cdcc8e6c9 100644 --- a/src/libstrongswan/credentials/keys/public_key.h +++ b/src/libstrongswan/credentials/keys/public_key.h @@ -93,6 +93,10 @@ enum signature_scheme_t { SIGN_ECDSA_384, /** ECDSA on the P-521 curve with SHA-512 as in RFC 4754 */ SIGN_ECDSA_521, + /** BLISS with SHA-256 */ + SIGN_BLISS_WITH_SHA256, + /** BLISS with SHA-384 */ + SIGN_BLISS_WITH_SHA384, /** BLISS with SHA-512 */ SIGN_BLISS_WITH_SHA512, }; diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c index b5e1134ba2..a56930325f 100644 --- a/src/libstrongswan/crypto/hashers/hasher.c +++ b/src/libstrongswan/crypto/hashers/hasher.c @@ -326,6 +326,10 @@ int hasher_signature_algorithm_to_oid(hash_algorithm_t alg, key_type_t key) case KEY_BLISS: switch (alg) { + case HASH_SHA256: + return OID_BLISS_WITH_SHA256; + case HASH_SHA384: + return OID_BLISS_WITH_SHA384; case HASH_SHA512: return OID_BLISS_WITH_SHA512; default: diff --git a/src/libstrongswan/plugins/bliss/bliss_plugin.c b/src/libstrongswan/plugins/bliss/bliss_plugin.c index 2021885b3a..07597c3183 100644 --- a/src/libstrongswan/plugins/bliss/bliss_plugin.c +++ b/src/libstrongswan/plugins/bliss/bliss_plugin.c @@ -55,9 +55,17 @@ METHOD(plugin_t, get_features, int, PLUGIN_REGISTER(PUBKEY, bliss_public_key_load, TRUE), PLUGIN_PROVIDE(PUBKEY, KEY_ANY), /* signature schemes, private */ + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_BLISS_WITH_SHA256), + PLUGIN_DEPENDS(HASHER, HASH_SHA256), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_BLISS_WITH_SHA384), + PLUGIN_DEPENDS(HASHER, HASH_SHA384), PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_BLISS_WITH_SHA512), PLUGIN_DEPENDS(HASHER, HASH_SHA512), /* signature verification schemes */ + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_BLISS_WITH_SHA256), + PLUGIN_DEPENDS(HASHER, HASH_SHA256), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_BLISS_WITH_SHA384), + PLUGIN_DEPENDS(HASHER, HASH_SHA384), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_BLISS_WITH_SHA512), PLUGIN_DEPENDS(HASHER, HASH_SHA512), }; diff --git a/src/libstrongswan/plugins/bliss/bliss_private_key.c b/src/libstrongswan/plugins/bliss/bliss_private_key.c index 0f89bed106..74c6cfe0b8 100644 --- a/src/libstrongswan/plugins/bliss/bliss_private_key.c +++ b/src/libstrongswan/plugins/bliss/bliss_private_key.c @@ -158,18 +158,20 @@ static void greedy_sc(int8_t *s1, int8_t *s2, int n, uint16_t *c_indices, } /** - * Compute a BLISS signature based on a SHA-512 hash + * Compute a BLISS signature */ -static bool sign_bliss_with_sha512(private_bliss_private_key_t *this, - chunk_t data, chunk_t *signature) +static bool sign_bliss(private_bliss_private_key_t *this, hash_algorithm_t alg, + chunk_t data, chunk_t *signature) { - rng_t *rng; - hash_algorithm_t alg; - hasher_t *hasher; bliss_fft_t *fft; bliss_signature_t *sig; bliss_sampler_t *sampler = NULL; - uint8_t seed_buf[32], data_hash_buf[HASH_SIZE_SHA512]; + rng_t *rng; + hasher_t *hasher; + hash_algorithm_t mgf1_alg; + size_t mgf1_seed_len; + uint8_t mgf1_seed_buf[HASH_SIZE_SHA512], data_hash_buf[HASH_SIZE_SHA512]; + chunk_t mgf1_seed, data_hash; uint16_t q, q2, p, p2, *c_indices, tests = 0; uint32_t *ay; int32_t *y1, *y2, *z1, *z2, *u, *s1c, *s2c; @@ -177,39 +179,46 @@ static bool sign_bliss_with_sha512(private_bliss_private_key_t *this, int32_t scalar, norm, ui; int16_t *ud, *uz2d, *z2d, value; int i, n; - size_t seed_len; double mean1 = 0, mean2 = 0, sigma1 = 0, sigma2 = 0; - chunk_t seed; - chunk_t data_hash = { data_hash_buf, sizeof(data_hash_buf) }; bool accepted, positive, success = FALSE, use_bliss_b; /* Initialize signature */ *signature = chunk_empty; /* Create data hash */ - hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); + hasher = lib->crypto->create_hasher(lib->crypto, alg); if (!hasher) { return FALSE; } + data_hash = chunk_create(data_hash_buf, hasher->get_hash_size(hasher)); + if (!hasher->get_hash(hasher, data, data_hash_buf)) { hasher->destroy(hasher); return FALSE; } + hasher->destroy(hasher); + + /* Create SHA512 hasher for c_indices oracle */ + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); + if (!hasher) + { + return FALSE; + } /* Set MGF1 hash algorithm and seed length based on security strength */ if (this->set->strength > 160) { - alg = HASH_SHA256; - seed_len = HASH_SIZE_SHA256; + mgf1_alg = HASH_SHA256; + mgf1_seed_len = HASH_SIZE_SHA256; } else { - alg = HASH_SHA1; - seed_len = HASH_SIZE_SHA1; + mgf1_alg = HASH_SHA1; + mgf1_seed_len = HASH_SIZE_SHA1; } - seed = chunk_create(seed_buf, seed_len); + mgf1_seed = chunk_create(mgf1_seed_buf, mgf1_seed_len); rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); if (!rng) @@ -260,13 +269,13 @@ static bool sign_bliss_with_sha512(private_bliss_private_key_t *this, { tests++; - if (!rng->get_bytes(rng, seed_len, seed_buf)) + if (!rng->get_bytes(rng, mgf1_seed_len, mgf1_seed_buf)) { goto end; } DESTROY_IF(sampler); - sampler = bliss_sampler_create(alg, seed, this->set); + sampler = bliss_sampler_create(mgf1_alg, mgf1_seed, this->set); if (!sampler) { goto end; @@ -507,8 +516,12 @@ METHOD(private_key_t, sign, bool, { switch (scheme) { + case SIGN_BLISS_WITH_SHA256: + return sign_bliss(this, HASH_SHA256, data, signature); + case SIGN_BLISS_WITH_SHA384: + return sign_bliss(this, HASH_SHA384, data, signature); case SIGN_BLISS_WITH_SHA512: - return sign_bliss_with_sha512(this, data, signature); + return sign_bliss(this, HASH_SHA512, data, signature); default: DBG1(DBG_LIB, "signature scheme %N not supported with BLISS", signature_scheme_names, scheme); diff --git a/src/libstrongswan/plugins/bliss/bliss_public_key.c b/src/libstrongswan/plugins/bliss/bliss_public_key.c index 4564d7c751..0175b0f8e9 100644 --- a/src/libstrongswan/plugins/bliss/bliss_public_key.c +++ b/src/libstrongswan/plugins/bliss/bliss_public_key.c @@ -59,8 +59,8 @@ METHOD(public_key_t, get_type, key_type_t, /** * Verify a BLISS signature based on a SHA-512 hash */ -static bool verify_bliss_with_sha512(private_bliss_public_key_t *this, - chunk_t data, chunk_t signature) +static bool verify_bliss(private_bliss_public_key_t *this, hash_algorithm_t alg, + chunk_t data, chunk_t signature) { int i, n; int32_t *z1, *u; @@ -68,23 +68,33 @@ static bool verify_bliss_with_sha512(private_bliss_public_key_t *this, uint16_t q, q2, p, *c_indices, *indices; uint32_t *az; uint8_t data_hash_buf[HASH_SIZE_SHA512]; - chunk_t data_hash = { data_hash_buf, sizeof(data_hash_buf) }; + chunk_t data_hash; hasher_t *hasher; bliss_fft_t *fft; bliss_signature_t *sig; bool success = FALSE; /* Create data hash */ - hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); + hasher = lib->crypto->create_hasher(lib->crypto, alg); if (!hasher ) { return FALSE; } + data_hash = chunk_create(data_hash_buf, hasher->get_hash_size(hasher)); + if (!hasher->get_hash(hasher, data, data_hash_buf)) { hasher->destroy(hasher); return FALSE; } + hasher->destroy(hasher); + + /* Create SHA512 hasher for c_indices oracle */ + hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA512); + if (!hasher) + { + return FALSE; + } sig = bliss_signature_create_from_data(this->set, signature); if (!sig) @@ -190,8 +200,12 @@ METHOD(public_key_t, verify, bool, { switch (scheme) { + case SIGN_BLISS_WITH_SHA256: + return verify_bliss(this, HASH_SHA256, data, signature); + case SIGN_BLISS_WITH_SHA384: + return verify_bliss(this, HASH_SHA384, data, signature); case SIGN_BLISS_WITH_SHA512: - return verify_bliss_with_sha512(this, data, signature); + return verify_bliss(this, HASH_SHA512, data, signature); default: DBG1(DBG_LIB, "signature scheme %N not supported by BLISS", signature_scheme_names, scheme); diff --git a/src/libstrongswan/plugins/bliss/tests/suites/test_bliss_sign.c b/src/libstrongswan/plugins/bliss/tests/suites/test_bliss_sign.c index 04147988f3..8b4e9cbf06 100644 --- a/src/libstrongswan/plugins/bliss/tests/suites/test_bliss_sign.c +++ b/src/libstrongswan/plugins/bliss/tests/suites/test_bliss_sign.c @@ -23,6 +23,7 @@ static u_int key_strength[] = { 128, 160, 192 }; START_TEST(test_bliss_sign_all) { + signature_scheme_t signature_scheme; private_key_t *privkey, *privkey1; public_key_t *pubkey, *pubkey1; chunk_t msg, signature, privkey_blob, pubkey_blob, pubkey_fp, privkey_fp; @@ -32,6 +33,18 @@ START_TEST(test_bliss_sign_all) { int verify_count = 1000; + switch (k) + { + case 1: + signature_scheme = SIGN_BLISS_WITH_SHA256; + break; + case 2: + signature_scheme = SIGN_BLISS_WITH_SHA384; + break; + default: + signature_scheme = SIGN_BLISS_WITH_SHA512; + } + /* enforce BLISS-B key for k = 2, 3 */ lib->settings->set_bool(lib->settings, "%s.plugins.bliss.use_bliss_b", k >= 2, lib->ns); @@ -105,9 +118,9 @@ START_TEST(test_bliss_sign_all) /* generate and verify 1000 BLISS signatures */ while (verify_count--) { - ck_assert(privkey->sign(privkey, SIGN_BLISS_WITH_SHA512, msg, + ck_assert(privkey->sign(privkey, signature_scheme, msg, &signature)); - ck_assert(pubkey->verify(pubkey, SIGN_BLISS_WITH_SHA512, msg, + ck_assert(pubkey->verify(pubkey, signature_scheme, msg, signature)); free(signature.ptr); } diff --git a/src/libstrongswan/tests/suites/test_hasher.c b/src/libstrongswan/tests/suites/test_hasher.c index 41a9d64efe..14cc321223 100644 --- a/src/libstrongswan/tests/suites/test_hasher.c +++ b/src/libstrongswan/tests/suites/test_hasher.c @@ -48,6 +48,9 @@ static hasher_oid_t oids[] = { { OID_ECDSA_WITH_SHA256, HASH_SHA256, KEY_ECDSA }, { OID_ECDSA_WITH_SHA384, HASH_SHA384, KEY_ECDSA }, { OID_ECDSA_WITH_SHA512, HASH_SHA512, KEY_ECDSA }, + { OID_BLISS_WITH_SHA256, HASH_SHA256, KEY_BLISS }, + { OID_BLISS_WITH_SHA384, HASH_SHA384, KEY_BLISS }, + { OID_BLISS_WITH_SHA512, HASH_SHA512, KEY_BLISS }, { OID_UNKNOWN, HASH_UNKNOWN, KEY_ECDSA } }; diff --git a/src/pki/commands/acert.c b/src/pki/commands/acert.c index 03d90a103f..e571318180 100644 --- a/src/pki/commands/acert.c +++ b/src/pki/commands/acert.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -168,8 +169,11 @@ static int acert() } if (private->get_type(private) == KEY_BLISS) { - /* currently only SHA-512 is supported */ - digest = HASH_SHA512; + /* the default hash function is SHA512. SHA1 is not supported */ + if (digest == HASH_SHA1) + { + digest = HASH_SHA512; + } } if (hex) diff --git a/src/pki/commands/gen.c b/src/pki/commands/gen.c index c39644e309..8b11854ad8 100644 --- a/src/pki/commands/gen.c +++ b/src/pki/commands/gen.c @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 Martin Willi - * Copyright (C) 2014 Andreas Steffen + * Copyright (C) 2014-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index c1d4cf8f2c..fba0238aee 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -365,8 +366,11 @@ static int issue() if (private->get_type(private) == KEY_BLISS) { - /* currently only SHA-512 is supported */ - digest = HASH_SHA512; + /* the default hash function is SHA512. SHA1 is not supported */ + if (digest == HASH_SHA1) + { + digest = HASH_SHA512; + } } if (hex) { diff --git a/src/pki/commands/pub.c b/src/pki/commands/pub.c index 843b784b48..ccc3c42517 100644 --- a/src/pki/commands/pub.c +++ b/src/pki/commands/pub.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the diff --git a/src/pki/commands/req.c b/src/pki/commands/req.c index fbe47ecc8a..39d71626da 100644 --- a/src/pki/commands/req.c +++ b/src/pki/commands/req.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 Martin Willi - * Copyright (C) 2009 Andreas Steffen + * Copyright (C) 2009-2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * HSR Hochschule fuer Technik Rapperswil * @@ -104,8 +105,11 @@ static int req() if (type == KEY_BLISS) { - /* currently only SHA-512 is supported */ - digest = HASH_SHA512; + /* the default hash function is SHA512. SHA1 is not supported */ + if (digest == HASH_SHA1) + { + digest = HASH_SHA512; + } } if (!dn) { diff --git a/src/pki/commands/self.c b/src/pki/commands/self.c index a67115d9bf..8dcb046de8 100644 --- a/src/pki/commands/self.c +++ b/src/pki/commands/self.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2015 Andreas Steffen + * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -264,8 +265,11 @@ static int self() if (type == KEY_BLISS) { - /* currently only SHA-512 is supported */ - digest = HASH_SHA512; + /* the default hash function is SHA512. SHA1 is not supported */ + if (digest == HASH_SHA1) + { + digest = HASH_SHA512; + } } if (!dn) { diff --git a/src/pki/commands/signcrl.c b/src/pki/commands/signcrl.c index 212e1a820a..4b81c775c9 100644 --- a/src/pki/commands/signcrl.c +++ b/src/pki/commands/signcrl.c @@ -337,8 +337,11 @@ static int sign_crl() } if (private->get_type(private) == KEY_BLISS) { - /* currently only SHA-512 is supported */ - digest = HASH_SHA512; + /* the default hash function is SHA512. SHA1 is not supported */ + if (digest == HASH_SHA1) + { + digest = HASH_SHA512; + } } if (basecrl)