diff options
Diffstat (limited to 'src/libstrongswan/plugins')
111 files changed, 1936 insertions, 531 deletions
diff --git a/src/libstrongswan/plugins/acert/Makefile.in b/src/libstrongswan/plugins/acert/Makefile.in index 10e6fa460..36067a3ff 100644 --- a/src/libstrongswan/plugins/acert/Makefile.in +++ b/src/libstrongswan/plugins/acert/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/aes/Makefile.in b/src/libstrongswan/plugins/aes/Makefile.in index 08f965596..d3817e12a 100644 --- a/src/libstrongswan/plugins/aes/Makefile.in +++ b/src/libstrongswan/plugins/aes/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/aesni/Makefile.in b/src/libstrongswan/plugins/aesni/Makefile.in index fbc7d9230..fdcfc099e 100644 --- a/src/libstrongswan/plugins/aesni/Makefile.in +++ b/src/libstrongswan/plugins/aesni/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/af_alg/Makefile.in b/src/libstrongswan/plugins/af_alg/Makefile.in index 2c45ce5ba..6b4a7fe5f 100644 --- a/src/libstrongswan/plugins/af_alg/Makefile.in +++ b/src/libstrongswan/plugins/af_alg/Makefile.in @@ -248,9 +248,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/agent/Makefile.in b/src/libstrongswan/plugins/agent/Makefile.in index 8183de939..12a44870c 100644 --- a/src/libstrongswan/plugins/agent/Makefile.in +++ b/src/libstrongswan/plugins/agent/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/agent/agent_private_key.c b/src/libstrongswan/plugins/agent/agent_private_key.c index bb55c45c0..cf2c5ea85 100644 --- a/src/libstrongswan/plugins/agent/agent_private_key.c +++ b/src/libstrongswan/plugins/agent/agent_private_key.c @@ -233,7 +233,7 @@ static bool scheme_supported(private_agent_private_key_t *this, } METHOD(private_key_t, sign, bool, - private_agent_private_key_t *this, signature_scheme_t scheme, + private_agent_private_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t *signature) { uint32_t len, flags; diff --git a/src/libstrongswan/plugins/bliss/Makefile.in b/src/libstrongswan/plugins/bliss/Makefile.in index eb8eaecb0..b98d367f1 100644 --- a/src/libstrongswan/plugins/bliss/Makefile.in +++ b/src/libstrongswan/plugins/bliss/Makefile.in @@ -269,9 +269,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/bliss/bliss_private_key.c b/src/libstrongswan/plugins/bliss/bliss_private_key.c index 25253ed37..964edcd93 100644 --- a/src/libstrongswan/plugins/bliss/bliss_private_key.c +++ b/src/libstrongswan/plugins/bliss/bliss_private_key.c @@ -512,7 +512,7 @@ end: } METHOD(private_key_t, sign, bool, - private_bliss_private_key_t *this, signature_scheme_t scheme, + private_bliss_private_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t *signature) { switch (scheme) diff --git a/src/libstrongswan/plugins/bliss/bliss_public_key.c b/src/libstrongswan/plugins/bliss/bliss_public_key.c index f7ddbbfd2..945840cdc 100644 --- a/src/libstrongswan/plugins/bliss/bliss_public_key.c +++ b/src/libstrongswan/plugins/bliss/bliss_public_key.c @@ -194,7 +194,7 @@ end: } METHOD(public_key_t, verify, bool, - private_bliss_public_key_t *this, signature_scheme_t scheme, + private_bliss_public_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t signature) { switch (scheme) diff --git a/src/libstrongswan/plugins/bliss/tests/Makefile.in b/src/libstrongswan/plugins/bliss/tests/Makefile.in index a2d56cdd1..015f40a00 100644 --- a/src/libstrongswan/plugins/bliss/tests/Makefile.in +++ b/src/libstrongswan/plugins/bliss/tests/Makefile.in @@ -248,9 +248,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ 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 a3e4420a9..908ea910d 100644 --- a/src/libstrongswan/plugins/bliss/tests/suites/test_bliss_sign.c +++ b/src/libstrongswan/plugins/bliss/tests/suites/test_bliss_sign.c @@ -118,9 +118,9 @@ START_TEST(test_bliss_sign_all) /* generate and verify 1000 BLISS signatures */ while (verify_count--) { - ck_assert(privkey->sign(privkey, signature_scheme, msg, + ck_assert(privkey->sign(privkey, signature_scheme, NULL, msg, &signature)); - ck_assert(pubkey->verify(pubkey, signature_scheme, msg, + ck_assert(pubkey->verify(pubkey, signature_scheme, NULL, msg, signature)); free(signature.ptr); } @@ -134,7 +134,7 @@ START_TEST(test_bliss_sign_fail) { private_key_t *privkey; public_key_t *pubkey; - chunk_t msg, signature, encoding, fp; + chunk_t msg = chunk_empty, signature, encoding, fp; /* generate non-supported BLISS-II private key */ privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_BLISS, @@ -172,18 +172,18 @@ START_TEST(test_bliss_sign_fail) ck_assert(!privkey->decrypt(privkey, ENCRYPT_UNKNOWN, chunk_empty, NULL)); /* sign with invalid signature scheme */ - ck_assert(!privkey->sign(privkey, SIGN_UNKNOWN, msg, &signature)); + ck_assert(!privkey->sign(privkey, SIGN_UNKNOWN, NULL, msg, &signature)); /* generate valid signature */ msg = chunk_from_str("Hello Dolly!"); - ck_assert(privkey->sign(privkey, SIGN_BLISS_WITH_SHA2_512, msg, &signature)); + ck_assert(privkey->sign(privkey, SIGN_BLISS_WITH_SHA2_512, NULL, msg, &signature)); /* verify with invalid signature scheme */ - ck_assert(!pubkey->verify(pubkey, SIGN_UNKNOWN, msg, signature)); + ck_assert(!pubkey->verify(pubkey, SIGN_UNKNOWN, NULL, msg, signature)); /* corrupt signature */ signature.ptr[signature.len - 1] ^= 0x80; - ck_assert(!pubkey->verify(pubkey, SIGN_BLISS_WITH_SHA2_512, msg, signature)); + ck_assert(!pubkey->verify(pubkey, SIGN_BLISS_WITH_SHA2_512, NULL, msg, signature)); free(signature.ptr); privkey->destroy(privkey); diff --git a/src/libstrongswan/plugins/blowfish/Makefile.in b/src/libstrongswan/plugins/blowfish/Makefile.in index 0d091d196..2f122b5a8 100644 --- a/src/libstrongswan/plugins/blowfish/Makefile.in +++ b/src/libstrongswan/plugins/blowfish/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/ccm/Makefile.in b/src/libstrongswan/plugins/ccm/Makefile.in index 008407097..07eb457d5 100644 --- a/src/libstrongswan/plugins/ccm/Makefile.in +++ b/src/libstrongswan/plugins/ccm/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/chapoly/Makefile.in b/src/libstrongswan/plugins/chapoly/Makefile.in index 0b2998c95..09cbddee7 100644 --- a/src/libstrongswan/plugins/chapoly/Makefile.in +++ b/src/libstrongswan/plugins/chapoly/Makefile.in @@ -259,9 +259,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/cmac/Makefile.in b/src/libstrongswan/plugins/cmac/Makefile.in index 2586d77c4..234a54cc2 100644 --- a/src/libstrongswan/plugins/cmac/Makefile.in +++ b/src/libstrongswan/plugins/cmac/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/constraints/Makefile.in b/src/libstrongswan/plugins/constraints/Makefile.in index 25632d745..82f82ca2d 100644 --- a/src/libstrongswan/plugins/constraints/Makefile.in +++ b/src/libstrongswan/plugins/constraints/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/ctr/Makefile.in b/src/libstrongswan/plugins/ctr/Makefile.in index 275a76273..7c3012301 100644 --- a/src/libstrongswan/plugins/ctr/Makefile.in +++ b/src/libstrongswan/plugins/ctr/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/curl/Makefile.in b/src/libstrongswan/plugins/curl/Makefile.in index 0dbcca895..0928dee1c 100644 --- a/src/libstrongswan/plugins/curl/Makefile.in +++ b/src/libstrongswan/plugins/curl/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/curve25519/Makefile.in b/src/libstrongswan/plugins/curve25519/Makefile.in index 21b0e75f7..cb8bb3405 100644 --- a/src/libstrongswan/plugins/curve25519/Makefile.in +++ b/src/libstrongswan/plugins/curve25519/Makefile.in @@ -251,9 +251,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/curve25519/curve25519_private_key.c b/src/libstrongswan/plugins/curve25519/curve25519_private_key.c index 2a7303c4b..878be4ca5 100644 --- a/src/libstrongswan/plugins/curve25519/curve25519_private_key.c +++ b/src/libstrongswan/plugins/curve25519/curve25519_private_key.c @@ -63,7 +63,7 @@ METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, sign, bool, private_curve25519_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) + void *params, chunk_t data, chunk_t *signature) { uint8_t r[HASH_SIZE_SHA512], k[HASH_SIZE_SHA512], sig[HASH_SIZE_SHA512]; hasher_t *hasher; diff --git a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c index d07776354..1d4dec565 100644 --- a/src/libstrongswan/plugins/curve25519/curve25519_public_key.c +++ b/src/libstrongswan/plugins/curve25519/curve25519_public_key.c @@ -50,7 +50,7 @@ METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, verify, bool, private_curve25519_public_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t signature) + void *params, chunk_t data, chunk_t signature) { hasher_t *hasher; uint8_t d = 0, k[HASH_SIZE_SHA512], r[32], *sig; diff --git a/src/libstrongswan/plugins/des/Makefile.in b/src/libstrongswan/plugins/des/Makefile.in index 89b279875..5ffa778cd 100644 --- a/src/libstrongswan/plugins/des/Makefile.in +++ b/src/libstrongswan/plugins/des/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/dnskey/Makefile.in b/src/libstrongswan/plugins/dnskey/Makefile.in index 385749a11..37799583a 100644 --- a/src/libstrongswan/plugins/dnskey/Makefile.in +++ b/src/libstrongswan/plugins/dnskey/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/files/Makefile.in b/src/libstrongswan/plugins/files/Makefile.in index 7708f9551..87b66df04 100644 --- a/src/libstrongswan/plugins/files/Makefile.in +++ b/src/libstrongswan/plugins/files/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/fips_prf/Makefile.in b/src/libstrongswan/plugins/fips_prf/Makefile.in index 478ae818e..aa0bd5fa8 100644 --- a/src/libstrongswan/plugins/fips_prf/Makefile.in +++ b/src/libstrongswan/plugins/fips_prf/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/gcm/Makefile.in b/src/libstrongswan/plugins/gcm/Makefile.in index 91ea7c673..da118ce57 100644 --- a/src/libstrongswan/plugins/gcm/Makefile.in +++ b/src/libstrongswan/plugins/gcm/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/gcrypt/Makefile.in b/src/libstrongswan/plugins/gcrypt/Makefile.in index 2212be0e2..3ed4a910f 100644 --- a/src/libstrongswan/plugins/gcrypt/Makefile.in +++ b/src/libstrongswan/plugins/gcrypt/Makefile.in @@ -248,9 +248,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c index cee25ea74..5519125ba 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.c @@ -289,11 +289,13 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group) /* * Described in header. */ -gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, - chunk_t g, chunk_t p) +gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, ...) { if (group == MODP_CUSTOM) { + chunk_t g, p; + + VA_ARGS_GET(group, g, p); return create_generic(group, p.len, g, p); } return NULL; diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h index a70958dc4..c6259f7ac 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_dh.h @@ -48,12 +48,10 @@ gcrypt_dh_t *gcrypt_dh_create(diffie_hellman_group_t group); * Creates a new gcrypt_dh_t object for MODP_CUSTOM. * * @param group MODP_CUSTOM - * @param g generator - * @param p prime + * @param ... expects generator and prime as chunk_t * @return gcrypt_dh_t object, NULL if not supported */ -gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, - chunk_t g, chunk_t p); +gcrypt_dh_t *gcrypt_dh_create_custom(diffie_hellman_group_t group, ...); #endif /** GCRYPT_DH_H_ @}*/ diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c index 7ecba8fa9..8a3de1e01 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_plugin.c @@ -118,6 +118,28 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), PLUGIN_REGISTER(PRIVKEY_GEN, gcrypt_rsa_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA), + /* signature schemes, private */ +#if GCRYPT_VERSION_NUMBER >= 0x010700 + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS), +#endif + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_224), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_256), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_384), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_512), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1), + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5), + /* signature verification schemes */ +#if GCRYPT_VERSION_NUMBER >= 0x010700 + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS), +#endif + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_224), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_256), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_384), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_512), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_MD5), /* random numbers */ PLUGIN_REGISTER(RNG, gcrypt_rng_create), PLUGIN_PROVIDE(RNG, RNG_WEAK), diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c index 15b876b3f..c06f43348 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * 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 @@ -21,6 +22,7 @@ #include <asn1/oid.h> #include <asn1/asn1.h> #include <asn1/asn1_parser.h> +#include <credentials/keys/signature_params.h> typedef struct private_gcrypt_rsa_private_key_t private_gcrypt_rsa_private_key_t; @@ -147,51 +149,100 @@ static bool sign_raw(private_gcrypt_rsa_private_key_t *this, } /** - * Sign a chunk of data using hashing and PKCS#1 encoding + * Sign a chunk of data using hashing and PKCS#1v1.5/EMSA-PSS encoding */ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this, - hash_algorithm_t hash_algorithm, char *hash_name, + hash_algorithm_t hash_algorithm, rsa_pss_params_t *pss, chunk_t data, chunk_t *signature) { hasher_t *hasher; chunk_t hash; gcry_error_t err; gcry_sexp_t in, out; - int hash_oid; + char *hash_name = enum_to_name(hash_algorithm_short_names, hash_algorithm); - hash_oid = hasher_algorithm_to_oid(hash_algorithm); - if (hash_oid == OID_UNKNOWN) + hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm); + if (!hasher) { + DBG1(DBG_LIB, "hash algorithm %N not supported", + hash_algorithm_names, hash_algorithm); return FALSE; } - hasher = lib->crypto->create_hasher(lib->crypto, hash_algorithm); - if (!hasher || !hasher->allocate_hash(hasher, data, &hash)) + if (!hasher->allocate_hash(hasher, data, &hash)) { - DESTROY_IF(hasher); + hasher->destroy(hasher); return FALSE; } hasher->destroy(hasher); - err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", - hash_name, hash.len, hash.ptr); + if (pss) + { + if (pss->salt.len) + { + err = gcry_sexp_build(&in, NULL, + "(data(flags pss)(salt-length %u)" + "(random-override %b)(hash %s %b))", + pss->salt.len, pss->salt.len, pss->salt.ptr, + hash_name, hash.len, hash.ptr); + } + else + { + u_int slen = hasher_hash_size(hash_algorithm); + if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + slen = pss->salt_len; + } + err = gcry_sexp_build(&in, NULL, + "(data(flags pss)(salt-length %u)(hash %s %b))", + slen, hash_name, hash.len, hash.ptr); + } + } + else + { + err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", + hash_name, hash.len, hash.ptr); + } chunk_free(&hash); if (err) { - DBG1(DBG_LIB, "building signature S-expression failed: %s", gpg_strerror(err)); + DBG1(DBG_LIB, "building signature S-expression failed: %s", + gpg_strerror(err)); return FALSE; } err = gcry_pk_sign(&out, in, this->key); gcry_sexp_release(in); if (err) { - DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", gpg_strerror(err)); + DBG1(DBG_LIB, "creating pkcs1 signature failed: %s", + gpg_strerror(err)); return FALSE; } + *signature = gcrypt_rsa_find_token(out, "s", this->key); gcry_sexp_release(out); return !!signature->len; } +#if GCRYPT_VERSION_NUMBER >= 0x010700 +/** + * Sign a chunk of data using hashing and EMSA-PSS encoding + */ +static bool sign_pss(private_gcrypt_rsa_private_key_t *this, + rsa_pss_params_t *params, chunk_t data, chunk_t *signature) +{ + if (!params) + { + return FALSE; + } + if (params->mgf1_hash != params->hash) + { + DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS"); + return FALSE; + } + return sign_pkcs1(this, params->hash, params, data, signature); +} +#endif + METHOD(private_key_t, get_type, key_type_t, private_gcrypt_rsa_private_key_t *this) { @@ -200,24 +251,28 @@ METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, sign, bool, private_gcrypt_rsa_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *sig) + void *params, chunk_t data, chunk_t *sig) { switch (scheme) { case SIGN_RSA_EMSA_PKCS1_NULL: return sign_raw(this, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_224: - return sign_pkcs1(this, HASH_SHA224, "sha224", data, sig); + return sign_pkcs1(this, HASH_SHA224, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_256: - return sign_pkcs1(this, HASH_SHA256, "sha256", data, sig); + return sign_pkcs1(this, HASH_SHA256, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_384: - return sign_pkcs1(this, HASH_SHA384, "sha384", data, sig); + return sign_pkcs1(this, HASH_SHA384, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA2_512: - return sign_pkcs1(this, HASH_SHA512, "sha512", data, sig); + return sign_pkcs1(this, HASH_SHA512, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_SHA1: - return sign_pkcs1(this, HASH_SHA1, "sha1", data, sig); + return sign_pkcs1(this, HASH_SHA1, NULL, data, sig); case SIGN_RSA_EMSA_PKCS1_MD5: - return sign_pkcs1(this, HASH_MD5, "md5", data, sig); + return sign_pkcs1(this, HASH_MD5, NULL, data, sig); +#if GCRYPT_VERSION_NUMBER >= 0x010700 + case SIGN_RSA_EMSA_PSS: + return sign_pss(this, params, data, sig); +#endif default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); @@ -498,16 +553,131 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_gen(key_type_t type, } /** + * Recover the primes from n, e and d using the algorithm described in + * Appendix C of NIST SP 800-56B. + */ +static bool calculate_pqu(chunk_t cn, chunk_t ce, chunk_t cd, chunk_t *cp, + chunk_t *cq, chunk_t *cu) +{ + gcry_mpi_t n, e, d, p, q, u, k, r, g, y, n1, x, two; + int i, t, j; + gcry_error_t err; + bool success = FALSE; + + n = e = d = p = q = u = k = r = g = y = n1 = x = two = NULL; + err = gcry_mpi_scan(&n, GCRYMPI_FMT_USG, cn.ptr, cn.len, NULL) + | gcry_mpi_scan(&e, GCRYMPI_FMT_USG, ce.ptr, ce.len, NULL) + | gcry_mpi_scan(&d, GCRYMPI_FMT_USG, cd.ptr, cd.len, NULL); + if (err) + { + goto error; + } + /* k = (d * e) - 1 */ + k = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_mul(k, d, e); + gcry_mpi_sub_ui(k, k, 1); + if (gcry_mpi_test_bit(k, 0)) + { + goto error; + } + /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ + r = gcry_mpi_copy(k); + for (t = 0; !gcry_mpi_test_bit(r, 0); t++) + { /* r = r/2 */ + gcry_mpi_rshift(r, r, 1); + } + /* we need n-1 below */ + n1 = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_sub_ui(n1, n, 1); + y = gcry_mpi_new(gcry_mpi_get_nbits(n)); + g = gcry_mpi_new(gcry_mpi_get_nbits(n)); + x = gcry_mpi_new(gcry_mpi_get_nbits(n)); + two = gcry_mpi_set_ui(NULL, 2); + for (i = 0; i < 100; i++) + { /* generate random integer g in [0, n-1] */ + do + { + gcry_mpi_randomize(g, gcry_mpi_get_nbits(n), GCRY_WEAK_RANDOM); + } + while (gcry_mpi_cmp(n, g) <= 0); + /* y = g^r mod n */ + gcry_mpi_powm(y, g, r, n); + /* try again if y == 1 or y == n-1 */ + if (gcry_mpi_cmp_ui(y, 1) == 0 || gcry_mpi_cmp(y, n1) == 0) + { + continue; + } + for (j = 0; j < t; j++) + { /* x = y^2 mod n */ + gcry_mpi_powm(x, y, two, n); + /* stop if x == 1 */ + if (gcry_mpi_cmp_ui(x, 1) == 0) + { + goto done; + } + /* retry with new g if x = n-1 */ + if (gcry_mpi_cmp(x, n1) == 0) + { + break; + } + /* y = x */ + gcry_mpi_set(y, x); + } + } + goto error; + +done: + /* p = gcd(y-1, n) */ + gcry_mpi_sub_ui(y, y, 1); + p = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_gcd(p, y, n); + /* q = n/p */ + q = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_div(q, NULL, n, p, 0); + if (gcry_mpi_cmp(p, q) > 0) + { /* gcrypt expects q < p */ + gcry_mpi_swap(p, q); + } + /* u = q^-1 mod p */ + u = gcry_mpi_new(gcry_mpi_get_nbits(n)); + gcry_mpi_invm(u, p, q); + err = gcry_mpi_aprint(GCRYMPI_FMT_USG, &cp->ptr, &cp->len, p) + | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cq->ptr, &cq->len, q) + | gcry_mpi_aprint(GCRYMPI_FMT_USG, &cu->ptr, &cu->len, u); + if (err) + { + goto error; + } + success = TRUE; + +error: + gcry_mpi_release(n); + gcry_mpi_release(e); + gcry_mpi_release(d); + gcry_mpi_release(p); + gcry_mpi_release(q); + gcry_mpi_release(u); + gcry_mpi_release(k); + gcry_mpi_release(r); + gcry_mpi_release(g); + gcry_mpi_release(y); + gcry_mpi_release(n1); + gcry_mpi_release(x); + gcry_mpi_release(two); + return success; +} + +/** * See header. */ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type, va_list args) { private_gcrypt_rsa_private_key_t *this; - chunk_t n, e, d, p, q, u; + chunk_t n, e, d, p, q, u, np, nq, nu; gcry_error_t err; - n = e = d = p = q = u = chunk_empty; + n = e = d = p = q = u = np = nq = nu = chunk_empty; while (TRUE) { switch (va_arg(args, builder_part_t)) @@ -543,12 +713,25 @@ gcrypt_rsa_private_key_t *gcrypt_rsa_private_key_load(key_type_t type, } break; } - + if (!p.len || !q.len || !u.len) + { + if (!calculate_pqu(n, e, d, &np, &nq, &nu)) + { + return NULL; + } + p = np; + q = nq; + u = nu; + } this = create_empty(); err = gcry_sexp_build(&this->key, NULL, "(private-key(rsa(n %b)(e %b)(d %b)(p %b)(q %b)(u %b)))", n.len, n.ptr, e.len, e.ptr, d.len, d.ptr, p.len, p.ptr, q.len, q.ptr, u.len, u.ptr); + + chunk_clear(&np); + chunk_clear(&nq); + chunk_clear(&nu); if (err) { DBG1(DBG_LIB, "loading private key failed: %s", gpg_strerror(err)); diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c index 90829e052..9e2ac1287 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c @@ -1,6 +1,7 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi - * Hochschule fuer Technik Rapperswil + * 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 @@ -22,6 +23,7 @@ #include <asn1/asn1.h> #include <asn1/asn1_parser.h> #include <crypto/hashers/hasher.h> +#include <credentials/keys/signature_params.h> typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t; @@ -109,27 +111,48 @@ static bool verify_raw(private_gcrypt_rsa_public_key_t *this, } /** - * Verification of an EMSA PKCS1 signature described in PKCS#1 + * Verification of an EMSA PKCS1v1.5 / EMSA-PSS signature described in PKCS#1 */ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this, - hash_algorithm_t algorithm, char *hash_name, + hash_algorithm_t algorithm, rsa_pss_params_t *pss, chunk_t data, chunk_t signature) { hasher_t *hasher; chunk_t hash; gcry_error_t err; gcry_sexp_t in, sig; + char *hash_name = enum_to_name(hash_algorithm_short_names, algorithm); hasher = lib->crypto->create_hasher(lib->crypto, algorithm); - if (!hasher || !hasher->allocate_hash(hasher, data, &hash)) + if (!hasher) { - DESTROY_IF(hasher); + DBG1(DBG_LIB, "hash algorithm %N not supported", + hash_algorithm_names, algorithm); + return FALSE; + } + if (!hasher->allocate_hash(hasher, data, &hash)) + { + hasher->destroy(hasher); return FALSE; } hasher->destroy(hasher); - err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", - hash_name, hash.len, hash.ptr); + if (pss) + { + u_int slen = hasher_hash_size(algorithm); + if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + slen = pss->salt_len; + } + err = gcry_sexp_build(&in, NULL, + "(data(flags pss)(salt-length %u)(hash %s %b))", + slen, hash_name, hash.len, hash.ptr); + } + else + { + err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", + hash_name, hash.len, hash.ptr); + } chunk_free(&hash); if (err) { @@ -159,6 +182,26 @@ static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this, return TRUE; } +#if GCRYPT_VERSION_NUMBER >= 0x010700 +/** + * Verification of an EMSA-PSS signature described in PKCS#1 + */ +static bool verify_pss(private_gcrypt_rsa_public_key_t *this, + rsa_pss_params_t *params, chunk_t data, chunk_t sig) +{ + if (!params) + { + return FALSE; + } + if (params->mgf1_hash != params->hash) + { + DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS"); + return FALSE; + } + return verify_pkcs1(this, params->hash, params, data, sig); +} +#endif + METHOD(public_key_t, get_type, key_type_t, private_gcrypt_rsa_public_key_t *this) { @@ -167,24 +210,28 @@ METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, verify, bool, private_gcrypt_rsa_public_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t signature) + void *params, chunk_t data, chunk_t signature) { switch (scheme) { case SIGN_RSA_EMSA_PKCS1_NULL: return verify_raw(this, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_224: - return verify_pkcs1(this, HASH_SHA224, "sha224", data, signature); + return verify_pkcs1(this, HASH_SHA224, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_256: - return verify_pkcs1(this, HASH_SHA256, "sha256", data, signature); + return verify_pkcs1(this, HASH_SHA256, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_384: - return verify_pkcs1(this, HASH_SHA384, "sha384", data, signature); + return verify_pkcs1(this, HASH_SHA384, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA2_512: - return verify_pkcs1(this, HASH_SHA512, "sha512", data, signature); + return verify_pkcs1(this, HASH_SHA512, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_SHA1: - return verify_pkcs1(this, HASH_SHA1, "sha1", data, signature); + return verify_pkcs1(this, HASH_SHA1, NULL, data, signature); case SIGN_RSA_EMSA_PKCS1_MD5: - return verify_pkcs1(this, HASH_MD5, "md5", data, signature); + return verify_pkcs1(this, HASH_MD5, NULL, data, signature); +#if GCRYPT_VERSION_NUMBER >= 0x010700 + case SIGN_RSA_EMSA_PSS: + return verify_pss(this, params, data, signature); +#endif default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); diff --git a/src/libstrongswan/plugins/gmp/Makefile.in b/src/libstrongswan/plugins/gmp/Makefile.in index 39a2bcabb..11aef42f0 100644 --- a/src/libstrongswan/plugins/gmp/Makefile.in +++ b/src/libstrongswan/plugins/gmp/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c index b7ee94ee0..b01adfe01 100644 --- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c +++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.c @@ -272,7 +272,7 @@ static gmp_diffie_hellman_t *create_generic(diffie_hellman_group_t group, } /* - * Described in header. + * Described in header */ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group) { @@ -287,12 +287,17 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group) params->generator, params->prime); } - +/* + * Described in header + */ gmp_diffie_hellman_t *gmp_diffie_hellman_create_custom( - diffie_hellman_group_t group, chunk_t g, chunk_t p) + diffie_hellman_group_t group, ...) { if (group == MODP_CUSTOM) { + chunk_t g, p; + + VA_ARGS_GET(group, g, p); return create_generic(MODP_CUSTOM, p.len, g, p); } return NULL; diff --git a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h index 6d73c0863..a8cde7bca 100644 --- a/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h +++ b/src/libstrongswan/plugins/gmp/gmp_diffie_hellman.h @@ -49,12 +49,11 @@ gmp_diffie_hellman_t *gmp_diffie_hellman_create(diffie_hellman_group_t group); * Creates a new gmp_diffie_hellman_t object for MODP_CUSTOM. * * @param group MODP_CUSTOM - * @param g generator - * @param p prime + * @param ... expects generator and prime as chunk_t * @return gmp_diffie_hellman_t object, NULL if not supported */ gmp_diffie_hellman_t *gmp_diffie_hellman_create_custom( - diffie_hellman_group_t group, chunk_t g, chunk_t p); + diffie_hellman_group_t group, ...); #endif /** GMP_DIFFIE_HELLMAN_H_ @}*/ diff --git a/src/libstrongswan/plugins/gmp/gmp_plugin.c b/src/libstrongswan/plugins/gmp/gmp_plugin.c index c75975301..700e29bf6 100644 --- a/src/libstrongswan/plugins/gmp/gmp_plugin.c +++ b/src/libstrongswan/plugins/gmp/gmp_plugin.c @@ -79,6 +79,14 @@ METHOD(plugin_t, get_features, int, PLUGIN_REGISTER(PUBKEY, gmp_rsa_public_key_load, TRUE), PLUGIN_PROVIDE(PUBKEY, KEY_RSA), /* signature schemes, private */ + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS), + PLUGIN_SDEPEND(HASHER, HASH_SHA1), + PLUGIN_SDEPEND(HASHER, HASH_SHA256), + PLUGIN_SDEPEND(HASHER, HASH_SHA512), + PLUGIN_SDEPEND(RNG, RNG_STRONG), + PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA1), + PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA256), + PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA512), PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL), PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA2_224), PLUGIN_DEPENDS(HASHER, HASH_SHA224), @@ -101,6 +109,13 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_MD5), PLUGIN_DEPENDS(HASHER, HASH_MD5), /* signature verification schemes */ + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS), + PLUGIN_SDEPEND(HASHER, HASH_SHA1), + PLUGIN_SDEPEND(HASHER, HASH_SHA256), + PLUGIN_SDEPEND(HASHER, HASH_SHA512), + PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA1), + PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA256), + PLUGIN_SDEPEND(XOF, XOF_MGF1_SHA512), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA2_224), PLUGIN_DEPENDS(HASHER, HASH_SHA224), diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c index 21b420866..aca232c86 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_private_key.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2005 Jan Hutter * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2012 Andreas Steffen @@ -27,6 +28,7 @@ #include <asn1/oid.h> #include <asn1/asn1.h> #include <asn1/asn1_parser.h> +#include <credentials/keys/signature_params.h> #ifdef HAVE_MPZ_POWM_SEC # undef mpz_powm @@ -333,6 +335,120 @@ static bool build_emsa_pkcs1_signature(private_gmp_rsa_private_key_t *this, return TRUE; } +/** + * Build a signature using the PKCS#1 EMSA PSS scheme + */ +static bool build_emsa_pss_signature(private_gmp_rsa_private_key_t *this, + rsa_pss_params_t *params, chunk_t data, + chunk_t *signature) +{ + ext_out_function_t xof; + hasher_t *hasher = NULL; + rng_t *rng = NULL; + xof_t *mgf = NULL; + chunk_t hash, salt = chunk_empty, m, ps, db, dbmask, em; + size_t embits, emlen, maskbits; + bool success = FALSE; + + if (!params) + { + return FALSE; + } + xof = xof_mgf1_from_hash_algorithm(params->mgf1_hash); + if (xof == XOF_UNDEFINED) + { + DBG1(DBG_LIB, "%N is not supported for MGF1", hash_algorithm_names, + params->mgf1_hash); + return FALSE; + } + /* emBits = modBits - 1 */ + embits = mpz_sizeinbase(this->n, 2) - 1; + /* emLen = ceil(emBits/8) */ + emlen = (embits + 7) / BITS_PER_BYTE; + /* mHash = Hash(M) */ + hasher = lib->crypto->create_hasher(lib->crypto, params->hash); + if (!hasher) + { + DBG1(DBG_LIB, "hash algorithm %N not supported", + hash_algorithm_names, params->hash); + return FALSE; + } + hash = chunk_alloca(hasher->get_hash_size(hasher)); + if (!hasher->get_hash(hasher, data, hash.ptr)) + { + goto error; + } + + salt.len = hash.len; + if (params->salt.len) + { + salt = params->salt; + } + else if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + salt.len = params->salt_len; + } + if (emlen < (hash.len + salt.len + 2)) + { /* too long */ + goto error; + } + if (salt.len && !params->salt.len) + { + salt = chunk_alloca(salt.len); + rng = lib->crypto->create_rng(lib->crypto, RNG_STRONG); + if (!rng || !rng->get_bytes(rng, salt.len, salt.ptr)) + { + goto error; + } + } + /* M' = 0x0000000000000000 | mHash | salt */ + m = chunk_cata("ccc", + chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00), + hash, salt); + /* H = Hash(M') */ + if (!hasher->get_hash(hasher, m, hash.ptr)) + { + goto error; + } + /* PS = 00...<padding depending on hash and salt length> */ + ps = chunk_alloca(emlen - salt.len - hash.len - 2); + memset(ps.ptr, 0, ps.len); + /* DB = PS | 0x01 | salt */ + db = chunk_cata("ccc", ps, chunk_from_chars(0x01), salt); + /* dbMask = MGF(H, emLen - hLen - 1) */ + mgf = lib->crypto->create_xof(lib->crypto, xof); + dbmask = chunk_alloca(db.len); + if (!mgf) + { + DBG1(DBG_LIB, "%N not supported", ext_out_function_names, xof); + goto error; + } + if (!mgf->set_seed(mgf, hash) || + !mgf->get_bytes(mgf, dbmask.len, dbmask.ptr)) + { + goto error; + } + /* maskedDB = DB xor dbMask */ + memxor(db.ptr, dbmask.ptr, db.len); + /* zero out unused bits */ + maskbits = (8 * emlen) - embits; + if (maskbits) + { + db.ptr[0] &= (0xff >> maskbits); + } + /* EM = maskedDB | H | 0xbc */ + em = chunk_cata("ccc", db, hash, chunk_from_chars(0xbc)); + /* S = RSASP1(K, EM) */ + *signature = rsasp1(this, em); + success = TRUE; + +error: + DESTROY_IF(hasher); + DESTROY_IF(rng); + DESTROY_IF(mgf); + return success; +} + METHOD(private_key_t, get_type, key_type_t, private_gmp_rsa_private_key_t *this) { @@ -341,7 +457,7 @@ METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, sign, bool, private_gmp_rsa_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) + void *params, chunk_t data, chunk_t *signature) { switch (scheme) { @@ -367,6 +483,8 @@ METHOD(private_key_t, sign, bool, return build_emsa_pkcs1_signature(this, HASH_SHA1, data, signature); case SIGN_RSA_EMSA_PKCS1_MD5: return build_emsa_pkcs1_signature(this, HASH_MD5, data, signature); + case SIGN_RSA_EMSA_PSS: + return build_emsa_pss_signature(this, params, data, signature); default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); @@ -807,6 +925,82 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_gen(key_type_t type, va_list args) } /** + * Recover the primes from n, e and d using the algorithm described in + * Appendix C of NIST SP 800-56B. + */ +static bool calculate_pq(private_gmp_rsa_private_key_t *this) +{ + gmp_randstate_t rstate; + mpz_t k, r, g, y, n1, x; + int i, t, j; + bool success = FALSE; + + gmp_randinit_default(rstate); + mpz_inits(k, r, g, y, n1, x, NULL); + /* k = (d * e) - 1 */ + mpz_mul(k, *this->d, this->e); + mpz_sub_ui(k, k, 1); + if (mpz_odd_p(k)) + { + goto error; + } + /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ + mpz_set(r, k); + for (t = 0; !mpz_odd_p(r); t++) + { /* r = r/2 */ + mpz_divexact_ui(r, r, 2); + } + /* we need n-1 below */ + mpz_sub_ui(n1, this->n, 1); + for (i = 0; i < 100; i++) + { /* generate random integer g in [0, n-1] */ + mpz_urandomm(g, rstate, this->n); + /* y = g^r mod n */ + mpz_powm_sec(y, g, r, this->n); + /* try again if y == 1 or y == n-1 */ + if (mpz_cmp_ui(y, 1) == 0 || mpz_cmp(y, n1) == 0) + { + continue; + } + for (j = 0; j < t; j++) + { /* x = y^2 mod n */ + mpz_powm_ui(x, y, 2, this->n); + /* stop if x == 1 */ + if (mpz_cmp_ui(x, 1) == 0) + { + goto done; + } + /* retry with new g if x = n-1 */ + if (mpz_cmp(x, n1) == 0) + { + break; + } + /* y = x */ + mpz_set(y, x); + } + } + goto error; + +done: + /* p = gcd(y-1, n) */ + mpz_sub_ui(y, y, 1); + mpz_gcd(this->p, y, this->n); + /* q = n/p */ + mpz_divexact(this->q, this->n, this->p); + success = TRUE; + +error: + mpz_clear_sensitive(k); + mpz_clear_sensitive(r); + mpz_clear_sensitive(g); + mpz_clear_sensitive(y); + mpz_clear_sensitive(x); + mpz_clear(n1); + gmp_randclear(rstate); + return success; +} + +/** * See header. */ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args) @@ -868,9 +1062,30 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args) mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr); mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr); mpz_import(*this->d, d.len, 1, 1, 1, 0, d.ptr); - mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr); - mpz_import(this->q, q.len, 1, 1, 1, 0, q.ptr); - mpz_import(this->coeff, coeff.len, 1, 1, 1, 0, coeff.ptr); + if (p.len) + { + mpz_import(this->p, p.len, 1, 1, 1, 0, p.ptr); + } + if (q.len) + { + mpz_import(this->q, q.len, 1, 1, 1, 0, q.ptr); + } + if (!p.len && !q.len) + { /* p and q missing in key, recalculate from n, e and d */ + if (!calculate_pq(this)) + { + destroy(this); + return NULL; + } + } + else if (!p.len) + { /* p missing in key, recalculate: p = n / q */ + mpz_divexact(this->p, this->n, this->q); + } + else if (!q.len) + { /* q missing in key, recalculate: q = n / p */ + mpz_divexact(this->q, this->n, this->p); + } if (!exp1.len) { /* exp1 missing in key, recalculate: exp1 = d mod (p-1) */ mpz_sub_ui(this->exp1, this->p, 1); @@ -889,6 +1104,14 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args) { mpz_import(this->exp2, exp2.len, 1, 1, 1, 0, exp2.ptr); } + if (!coeff.len) + { /* coeff missing in key, recalculate: coeff = q^-1 mod p */ + mpz_invert(this->coeff, this->q, this->p); + } + else + { + mpz_import(this->coeff, coeff.len, 1, 1, 1, 0, coeff.ptr); + } this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE; if (check(this) != SUCCESS) { @@ -897,4 +1120,3 @@ gmp_rsa_private_key_t *gmp_rsa_private_key_load(key_type_t type, va_list args) } return &this->public; } - diff --git a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c index 065c88903..52bc9fb38 100644 --- a/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c +++ b/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c @@ -1,7 +1,8 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2005-2009 Martin Willi * Copyright (C) 2005 Jan Hutter - * Hochschule fuer Technik Rapperswil + * 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 @@ -27,6 +28,7 @@ #include <asn1/asn1.h> #include <asn1/asn1_parser.h> #include <crypto/hashers/hasher.h> +#include <credentials/keys/signature_params.h> #ifdef HAVE_MPZ_POWM_SEC # undef mpz_powm @@ -126,7 +128,7 @@ static const asn1Object_t digestInfoObjects[] = { #define DIGEST_INFO_DIGEST 2 /** - * Verification of an EMPSA PKCS1 signature described in PKCS#1 + * Verification of an EMSA PKCS1 signature described in PKCS#1 */ static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this, hash_algorithm_t algorithm, @@ -283,6 +285,124 @@ end: return success; } +/** + * Verification of an EMSA PSS signature described in PKCS#1 + */ +static bool verify_emsa_pss_signature(private_gmp_rsa_public_key_t *this, + rsa_pss_params_t *params, chunk_t data, + chunk_t signature) +{ + ext_out_function_t xof; + hasher_t *hasher = NULL; + xof_t *mgf = NULL; + chunk_t em, hash, salt, db, h, dbmask, m; + size_t embits, maskbits; + int i; + bool success = FALSE; + + if (!params) + { + return FALSE; + } + xof = xof_mgf1_from_hash_algorithm(params->mgf1_hash); + if (xof == XOF_UNDEFINED) + { + DBG1(DBG_LIB, "%N is not supported for MGF1", hash_algorithm_names, + params->mgf1_hash); + return FALSE; + } + chunk_skip_zero(signature); + if (signature.len == 0 || signature.len > this->k) + { + return FALSE; + } + /* EM = RSAVP1((n, e), S) */ + em = rsavp1(this, signature); + if (!em.len) + { + goto error; + } + /* emBits = modBits - 1 */ + embits = mpz_sizeinbase(this->n, 2) - 1; + /* mHash = Hash(M) */ + hasher = lib->crypto->create_hasher(lib->crypto, params->hash); + if (!hasher) + { + DBG1(DBG_LIB, "hash algorithm %N not supported", + hash_algorithm_names, params->hash); + goto error; + } + hash = chunk_alloca(hasher->get_hash_size(hasher)); + if (!hasher->get_hash(hasher, data, hash.ptr)) + { + goto error; + } + /* determine salt length */ + salt.len = hash.len; + if (params->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + salt.len = params->salt_len; + } + /* verify general structure of EM */ + maskbits = (8 * em.len) - embits; + if (em.len < (hash.len + salt.len + 2) || em.ptr[em.len-1] != 0xbc || + (em.ptr[0] & (0xff << (8-maskbits)))) + { /* inconsistent */ + goto error; + } + /* split EM in maskedDB and H */ + db = chunk_create(em.ptr, em.len - hash.len - 1); + h = chunk_create(em.ptr + db.len, hash.len); + /* dbMask = MGF(H, emLen - hLen - 1) */ + mgf = lib->crypto->create_xof(lib->crypto, xof); + if (!mgf) + { + DBG1(DBG_LIB, "%N not supported", ext_out_function_names, xof); + goto error; + } + dbmask = chunk_alloca(db.len); + if (!mgf->set_seed(mgf, h) || + !mgf->get_bytes(mgf, dbmask.len, dbmask.ptr)) + { + DBG1(DBG_LIB, "%N not supported or failed", ext_out_function_names, xof); + goto error; + } + /* DB = maskedDB xor dbMask */ + memxor(db.ptr, dbmask.ptr, db.len); + if (maskbits) + { + db.ptr[0] &= (0xff >> maskbits); + } + /* check DB = PS | 0x01 | salt */ + for (i = 0; i < (db.len - salt.len - 1); i++) + { + if (db.ptr[i]) + { /* padding not 0 */ + goto error; + } + } + if (db.ptr[i++] != 0x01) + { /* 0x01 not found */ + goto error; + } + salt.ptr = &db.ptr[i]; + /* M' = 0x0000000000000000 | mHash | salt */ + m = chunk_cata("ccc", + chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00), + hash, salt); + if (!hasher->get_hash(hasher, m, hash.ptr)) + { + goto error; + } + success = memeq_const(h.ptr, hash.ptr, hash.len); + +error: + DESTROY_IF(hasher); + DESTROY_IF(mgf); + free(em.ptr); + return success; +} + METHOD(public_key_t, get_type, key_type_t, private_gmp_rsa_public_key_t *this) { @@ -290,7 +410,7 @@ METHOD(public_key_t, get_type, key_type_t, } METHOD(public_key_t, verify, bool, - private_gmp_rsa_public_key_t *this, signature_scheme_t scheme, + private_gmp_rsa_public_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t signature) { switch (scheme) @@ -317,6 +437,8 @@ METHOD(public_key_t, verify, bool, return verify_emsa_pkcs1_signature(this, HASH_SHA1, data, signature); case SIGN_RSA_EMSA_PKCS1_MD5: return verify_emsa_pkcs1_signature(this, HASH_MD5, data, signature); + case SIGN_RSA_EMSA_PSS: + return verify_emsa_pss_signature(this, params, data, signature); default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); diff --git a/src/libstrongswan/plugins/hmac/Makefile.in b/src/libstrongswan/plugins/hmac/Makefile.in index cddeace7f..8de79663e 100644 --- a/src/libstrongswan/plugins/hmac/Makefile.in +++ b/src/libstrongswan/plugins/hmac/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/keychain/Makefile.in b/src/libstrongswan/plugins/keychain/Makefile.in index e072c9225..6573b311d 100644 --- a/src/libstrongswan/plugins/keychain/Makefile.in +++ b/src/libstrongswan/plugins/keychain/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/ldap/Makefile.in b/src/libstrongswan/plugins/ldap/Makefile.in index 229a0cad0..324157bc0 100644 --- a/src/libstrongswan/plugins/ldap/Makefile.in +++ b/src/libstrongswan/plugins/ldap/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/md4/Makefile.in b/src/libstrongswan/plugins/md4/Makefile.in index d135c291f..111f53239 100644 --- a/src/libstrongswan/plugins/md4/Makefile.in +++ b/src/libstrongswan/plugins/md4/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/md5/Makefile.in b/src/libstrongswan/plugins/md5/Makefile.in index e81213c2a..1a41f73ea 100644 --- a/src/libstrongswan/plugins/md5/Makefile.in +++ b/src/libstrongswan/plugins/md5/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/mgf1/Makefile.in b/src/libstrongswan/plugins/mgf1/Makefile.in index 8a2788319..fd69f4042 100644 --- a/src/libstrongswan/plugins/mgf1/Makefile.in +++ b/src/libstrongswan/plugins/mgf1/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/mgf1/mgf1_plugin.c b/src/libstrongswan/plugins/mgf1/mgf1_plugin.c index 8df3ac261..a78d2f254 100644 --- a/src/libstrongswan/plugins/mgf1/mgf1_plugin.c +++ b/src/libstrongswan/plugins/mgf1/mgf1_plugin.c @@ -44,8 +44,12 @@ METHOD(plugin_t, get_features, int, PLUGIN_REGISTER(XOF, mgf1_xof_create), PLUGIN_PROVIDE(XOF, XOF_MGF1_SHA1), PLUGIN_DEPENDS(HASHER, HASH_SHA1), + PLUGIN_PROVIDE(XOF, XOF_MGF1_SHA224), + PLUGIN_DEPENDS(HASHER, HASH_SHA224), PLUGIN_PROVIDE(XOF, XOF_MGF1_SHA256), PLUGIN_DEPENDS(HASHER, HASH_SHA256), + PLUGIN_PROVIDE(XOF, XOF_MGF1_SHA384), + PLUGIN_DEPENDS(HASHER, HASH_SHA384), PLUGIN_PROVIDE(XOF, XOF_MGF1_SHA512), PLUGIN_DEPENDS(HASHER, HASH_SHA512), }; diff --git a/src/libstrongswan/plugins/mgf1/mgf1_xof.c b/src/libstrongswan/plugins/mgf1/mgf1_xof.c index 0f5fda952..8f5a18f87 100644 --- a/src/libstrongswan/plugins/mgf1/mgf1_xof.c +++ b/src/libstrongswan/plugins/mgf1/mgf1_xof.c @@ -244,9 +244,15 @@ mgf1_xof_t *mgf1_xof_create(ext_out_function_t algorithm) case XOF_MGF1_SHA1: hash_alg = HASH_SHA1; break; + case XOF_MGF1_SHA224: + hash_alg = HASH_SHA224; + break; case XOF_MGF1_SHA256: hash_alg = HASH_SHA256; break; + case XOF_MGF1_SHA384: + hash_alg = HASH_SHA384; + break; case XOF_MGF1_SHA512: hash_alg = HASH_SHA512; break; @@ -261,7 +267,7 @@ mgf1_xof_t *mgf1_xof_create(ext_out_function_t algorithm) hash_algorithm_names, hash_alg); return NULL; } - + INIT(this, .public = { .mgf1_interface = { diff --git a/src/libstrongswan/plugins/mysql/Makefile.in b/src/libstrongswan/plugins/mysql/Makefile.in index c99e4f806..114507eeb 100644 --- a/src/libstrongswan/plugins/mysql/Makefile.in +++ b/src/libstrongswan/plugins/mysql/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/newhope/Makefile.in b/src/libstrongswan/plugins/newhope/Makefile.in index 786337420..81c10d5c9 100644 --- a/src/libstrongswan/plugins/newhope/Makefile.in +++ b/src/libstrongswan/plugins/newhope/Makefile.in @@ -253,9 +253,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/newhope/tests/Makefile.in b/src/libstrongswan/plugins/newhope/tests/Makefile.in index be6ffef28..114035a4a 100644 --- a/src/libstrongswan/plugins/newhope/tests/Makefile.in +++ b/src/libstrongswan/plugins/newhope/tests/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/nonce/Makefile.in b/src/libstrongswan/plugins/nonce/Makefile.in index fca8309e5..0e24d4861 100644 --- a/src/libstrongswan/plugins/nonce/Makefile.in +++ b/src/libstrongswan/plugins/nonce/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/ntru/Makefile.in b/src/libstrongswan/plugins/ntru/Makefile.in index 2ef9aa8dc..cdfee525b 100644 --- a/src/libstrongswan/plugins/ntru/Makefile.in +++ b/src/libstrongswan/plugins/ntru/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/openssl/Makefile.in b/src/libstrongswan/plugins/openssl/Makefile.in index dcf4c2c8a..856055c6a 100644 --- a/src/libstrongswan/plugins/openssl/Makefile.in +++ b/src/libstrongswan/plugins/openssl/Makefile.in @@ -254,9 +254,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/openssl/openssl_crl.c b/src/libstrongswan/plugins/openssl/openssl_crl.c index 61cf3e884..88f7a67c2 100644 --- a/src/libstrongswan/plugins/openssl/openssl_crl.c +++ b/src/libstrongswan/plugins/openssl/openssl_crl.c @@ -1,4 +1,7 @@ /* + * Copyright (C) 2017 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG * @@ -47,14 +50,13 @@ #include <credentials/certificates/x509.h> #if OPENSSL_VERSION_NUMBER < 0x10100000L -static inline void X509_CRL_get0_signature(ASN1_BIT_STRING **psig, X509_ALGOR **palg, const X509_CRL *crl) { +static inline void X509_CRL_get0_signature(const X509_CRL *crl, ASN1_BIT_STRING **psig, X509_ALGOR **palg) { if (psig) { *psig = crl->signature; } if (palg) { *palg = crl->sig_alg; } } #define X509_REVOKED_get0_serialNumber(r) ({ (r)->serialNumber; }) #define X509_REVOKED_get0_revocationDate(r) ({ (r)->revocationDate; }) #define X509_CRL_get0_extensions(c) ({ (c)->crl->extensions; }) -#define X509_ALGOR_get0(oid, ppt, ppv, alg) ({ *(oid) = (alg)->algorithm; }) #endif typedef struct private_openssl_crl_t private_openssl_crl_t; @@ -85,6 +87,16 @@ struct private_openssl_crl_t { chunk_t serial; /** + * Number of base CRL (deltaCrlIndicator), if a delta CRL + */ + chunk_t base; + + /** + * List of Freshest CRL distribution points + */ + linked_list_t *crl_uris; + + /** * AuthorityKeyIdentifier of the issuing CA */ chunk_t authKeyIdentifier; @@ -107,7 +119,7 @@ struct private_openssl_crl_t { /** * Signature scheme used in this CRL */ - signature_scheme_t scheme; + signature_params_t *scheme; /** * References to this CRL @@ -140,6 +152,11 @@ typedef struct { int i; } crl_enumerator_t; +/** + * from openssl_x509 + */ +bool openssl_parse_crlDistributionPoints(X509_EXTENSION *ext, + linked_list_t *list); METHOD(enumerator_t, crl_enumerate, bool, crl_enumerator_t *this, va_list args) @@ -215,6 +232,26 @@ METHOD(crl_t, get_serial, chunk_t, return this->serial; } +METHOD(crl_t, is_delta_crl, bool, + private_openssl_crl_t *this, chunk_t *base_crl) +{ + if (this->base.len) + { + if (base_crl) + { + *base_crl = this->base; + } + return TRUE; + } + return FALSE; +} + +METHOD(crl_t, create_delta_crl_uri_enumerator, enumerator_t*, + private_openssl_crl_t *this) +{ + return this->crl_uris->create_enumerator(this->crl_uris); +} + METHOD(crl_t, get_authKeyIdentifier, chunk_t, private_openssl_crl_t *this) { @@ -246,7 +283,7 @@ METHOD(certificate_t, has_subject_or_issuer, id_match_t, METHOD(certificate_t, issued_by, bool, private_openssl_crl_t *this, certificate_t *issuer, - signature_scheme_t *scheme) + signature_params_t **scheme) { chunk_t fingerprint, tbs; public_key_t *key; @@ -283,23 +320,20 @@ METHOD(certificate_t, issued_by, bool, return FALSE; } } - if (this->scheme == SIGN_UNKNOWN) - { - return FALSE; - } /* i2d_re_X509_CRL_tbs() was added with 1.1.0 when X509_CRL became opaque */ #if OPENSSL_VERSION_NUMBER >= 0x10100000L tbs = openssl_i2chunk(re_X509_CRL_tbs, this->crl); #else tbs = openssl_i2chunk(X509_CRL_INFO, this->crl->crl); #endif - X509_CRL_get0_signature(&sig, NULL, this->crl); - valid = key->verify(key, this->scheme, tbs, openssl_asn1_str2chunk(sig)); + X509_CRL_get0_signature(this->crl, &sig, NULL); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs, + openssl_asn1_str2chunk(sig)); free(tbs.ptr); key->destroy(key); if (valid && scheme) { - *scheme = this->scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -379,8 +413,12 @@ METHOD(certificate_t, destroy, void, { X509_CRL_free(this->crl); } + signature_params_destroy(this->scheme); + this->crl_uris->destroy_function(this->crl_uris, + (void*)x509_cdp_destroy); DESTROY_IF(this->issuer); free(this->authKeyIdentifier.ptr); + free(this->base.ptr); free(this->serial.ptr); free(this->encoding.ptr); free(this); @@ -413,11 +451,12 @@ static private_openssl_crl_t *create_empty() }, .get_serial = _get_serial, .get_authKeyIdentifier = _get_authKeyIdentifier, - .is_delta_crl = (void*)return_false, - .create_delta_crl_uri_enumerator = (void*)enumerator_create_empty, + .is_delta_crl = _is_delta_crl, + .create_delta_crl_uri_enumerator = _create_delta_crl_uri_enumerator, .create_enumerator = _create_enumerator, }, }, + .crl_uris = linked_list_create(), .ref = 1, ); return this; @@ -444,21 +483,19 @@ static bool parse_authKeyIdentifier_ext(private_openssl_crl_t *this, } /** - * Parse the crlNumber extension + * Quick and dirty INTEGER unwrap for crlNumber/deltaCrlIndicator extensions */ -static bool parse_crlNumber_ext(private_openssl_crl_t *this, - X509_EXTENSION *ext) +static bool parse_integer_ext(X509_EXTENSION *ext, chunk_t *out) { chunk_t chunk; chunk = openssl_asn1_str2chunk(X509_EXTENSION_get_data(ext)); - /* quick and dirty INTEGER unwrap */ if (chunk.len > 1 && chunk.ptr[0] == V_ASN1_INTEGER && chunk.ptr[1] == chunk.len - 2) { chunk = chunk_skip(chunk, 2); - free(this->serial.ptr); - this->serial = chunk_clone(chunk); + free(out->ptr); + *out = chunk_clone(chunk); return TRUE; } return FALSE; @@ -488,7 +525,13 @@ static bool parse_extensions(private_openssl_crl_t *this) ok = parse_authKeyIdentifier_ext(this, ext); break; case NID_crl_number: - ok = parse_crlNumber_ext(this, ext); + ok = parse_integer_ext(ext, &this->serial); + break; + case NID_delta_crl: + ok = parse_integer_ext(ext, &this->base); + break; + case NID_freshest_crl: + ok = openssl_parse_crlDistributionPoints(ext, this->crl_uris); break; case NID_issuing_distribution_point: /* TODO support of IssuingDistributionPoints */ @@ -520,7 +563,7 @@ static bool parse_extensions(private_openssl_crl_t *this) static bool parse_crl(private_openssl_crl_t *this) { const unsigned char *ptr = this->encoding.ptr; - ASN1_OBJECT *oid; + chunk_t sig_scheme; X509_ALGOR *alg; this->crl = d2i_X509_CRL(NULL, &ptr, this->encoding.len); @@ -529,28 +572,16 @@ static bool parse_crl(private_openssl_crl_t *this) return FALSE; } - X509_CRL_get0_signature(NULL, &alg, this->crl); - X509_ALGOR_get0(&oid, NULL, NULL, alg); -#if OPENSSL_VERSION_NUMBER < 0x10100000L - if (!chunk_equals( - openssl_asn1_obj2chunk(this->crl->crl->sig_alg->algorithm), - openssl_asn1_obj2chunk(this->crl->sig_alg->algorithm))) + X509_CRL_get0_signature(this->crl, NULL, &alg); + sig_scheme = openssl_i2chunk(X509_ALGOR, alg); + INIT(this->scheme); + if (!signature_params_parse(sig_scheme, 0, this->scheme)) { + DBG1(DBG_ASN, "unable to parse signature algorithm"); + free(sig_scheme.ptr); return FALSE; } -#elif 0 - /* FIXME: we currently can't do this if X509_CRL is opaque (>= 1.1.0) as - * X509_CRL_get0_tbs_sigalg() does not exist and there does not seem to be - * another easy way to get the algorithm from the tbsCertList of the CRL */ - alg = X509_CRL_get0_tbs_sigalg(this->crl); - X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg); - if (!chunk_equals(openssl_asn1_obj2chunk(oid), - openssl_asn1_obj2chunk(oid_tbs))) - { - return FALSE; - } -#endif - this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid)); + free(sig_scheme.ptr); this->issuer = openssl_x509_name2id(X509_CRL_get_issuer(this->crl)); if (!this->issuer) diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c index f08dfff7e..8e9c1183f 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.c @@ -193,7 +193,7 @@ METHOD(diffie_hellman_t, destroy, void, * Described in header. */ openssl_diffie_hellman_t *openssl_diffie_hellman_create( - diffie_hellman_group_t group, chunk_t g, chunk_t p) + diffie_hellman_group_t group, ...) { private_openssl_diffie_hellman_t *this; const BIGNUM *privkey; @@ -225,6 +225,9 @@ openssl_diffie_hellman_t *openssl_diffie_hellman_create( if (group == MODP_CUSTOM) { + chunk_t g, p; + + VA_ARGS_GET(group, g, p); if (!DH_set0_pqg(this->dh, BN_bin2bn(p.ptr, p.len, NULL), NULL, BN_bin2bn(g.ptr, g.len, NULL))) { diff --git a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h index 53dc59c78..5de5520b5 100644 --- a/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h +++ b/src/libstrongswan/plugins/openssl/openssl_diffie_hellman.h @@ -40,12 +40,11 @@ struct openssl_diffie_hellman_t { * Creates a new openssl_diffie_hellman_t object. * * @param group Diffie Hellman group number to use - * @param g custom generator, if MODP_CUSTOM - * @param p custom prime, if MODP_CUSTOM + * @param ... expects generator and prime as chunk_t if MODP_CUSTOM * @return openssl_diffie_hellman_t object, NULL if not supported */ openssl_diffie_hellman_t *openssl_diffie_hellman_create( - diffie_hellman_group_t group, chunk_t g, chunk_t p); + diffie_hellman_group_t group, ...); #endif /** OPENSSL_DIFFIE_HELLMAN_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c index 22bbf6dc7..364190758 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.c @@ -49,6 +49,11 @@ struct private_openssl_ec_private_key_t { EC_KEY *ec; /** + * TRUE if the key is from an OpenSSL ENGINE and might not be readable + */ + bool engine; + + /** * reference count */ refcount_t ref; @@ -146,7 +151,7 @@ static bool build_der_signature(private_openssl_ec_private_key_t *this, METHOD(private_key_t, sign, bool, private_openssl_ec_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) + void *params, chunk_t data, chunk_t *signature) { switch (scheme) { @@ -226,6 +231,11 @@ METHOD(private_key_t, get_encoding, bool, { u_char *p; + if (this->engine) + { + return FALSE; + } + switch (type) { case PRIVKEY_ASN1_DER: @@ -307,7 +317,7 @@ static private_openssl_ec_private_key_t *create_empty(void) /* * See header. */ -private_key_t *openssl_ec_private_key_create(EVP_PKEY *key) +private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine) { private_openssl_ec_private_key_t *this; EC_KEY *ec; @@ -320,6 +330,7 @@ private_key_t *openssl_ec_private_key_create(EVP_PKEY *key) } this = create_empty(); this->ec = ec; + this->engine = engine; return &this->public.key; } diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h index 84314f671..56c59cfc8 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_ec_private_key.h @@ -67,8 +67,9 @@ openssl_ec_private_key_t *openssl_ec_private_key_load(key_type_t type, * Wrap an EVP_PKEY object of type EVP_PKEY_EC * * @param key EVP_PKEY_EC key object (adopted) + * @param engine whether the key was loaded via an engine * @return loaded key, NULL on failure */ -private_key_t *openssl_ec_private_key_create(EVP_PKEY *key); +private_key_t *openssl_ec_private_key_create(EVP_PKEY *key, bool engine); #endif /** OPENSSL_EC_PRIVATE_KEY_H_ @}*/ diff --git a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c index a1e56fc5e..faa940839 100644 --- a/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_ec_public_key.c @@ -151,7 +151,7 @@ METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, verify, bool, private_openssl_ec_public_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t signature) + void *params, chunk_t data, chunk_t signature) { switch (scheme) { diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.c b/src/libstrongswan/plugins/openssl/openssl_hasher.c index 96ee230c9..eb6c50508 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hasher.c +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008 Tobias Brunner - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2008-2017 Tobias Brunner + * 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 @@ -91,16 +91,24 @@ METHOD(hasher_t, destroy, void, /* * Described in header */ -openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) +const EVP_MD *openssl_get_md(hash_algorithm_t hash) { - private_openssl_hasher_t *this; - char* name; + char *name; - name = enum_to_name(hash_algorithm_short_names, algo); + name = enum_to_name(hash_algorithm_short_names, hash); if (!name) { return NULL; } + return EVP_get_digestbyname(name); +} + +/* + * Described in header + */ +openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) +{ + private_openssl_hasher_t *this; INIT(this, .public = { @@ -114,7 +122,7 @@ openssl_hasher_t *openssl_hasher_create(hash_algorithm_t algo) }, ); - this->hasher = EVP_get_digestbyname(name); + this->hasher = openssl_get_md(algo); if (!this->hasher) { /* OpenSSL does not support the requested algo */ diff --git a/src/libstrongswan/plugins/openssl/openssl_hasher.h b/src/libstrongswan/plugins/openssl/openssl_hasher.h index b03f6891b..66b9b505e 100644 --- a/src/libstrongswan/plugins/openssl/openssl_hasher.h +++ b/src/libstrongswan/plugins/openssl/openssl_hasher.h @@ -1,6 +1,6 @@ /* - * Copyright (C) 2008 Tobias Brunner - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2008-2017 Tobias Brunner + * 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 @@ -25,6 +25,8 @@ typedef struct openssl_hasher_t openssl_hasher_t; #include <crypto/hashers/hasher.h> +#include <openssl/evp.h> + /** * Implementation of hashers using OpenSSL. */ @@ -37,6 +39,14 @@ struct openssl_hasher_t { }; /** + * Determine EVP_MD for the given hash algorithm + * + * @param hash hash algorithm + * @return EVP_MD or NULL if not found/supported + */ +const EVP_MD *openssl_get_md(hash_algorithm_t hash); + +/** * Constructor to create openssl_hasher_t. * * @param algo algorithm diff --git a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c index 83ac8df5b..f94767cf5 100644 --- a/src/libstrongswan/plugins/openssl/openssl_pkcs7.c +++ b/src/libstrongswan/plugins/openssl/openssl_pkcs7.c @@ -256,7 +256,7 @@ static auth_cfg_t *verify_signature(CMS_SignerInfo *si, int hash_oid) key = cert->get_public_key(cert); if (key) { - if (key->verify(key, signature_scheme_from_oid(hash_oid), + if (key->verify(key, signature_scheme_from_oid(hash_oid), NULL, attrs, sig)) { found = auth->clone(auth); diff --git a/src/libstrongswan/plugins/openssl/openssl_plugin.c b/src/libstrongswan/plugins/openssl/openssl_plugin.c index ab73d718f..8b0a7c5c7 100644 --- a/src/libstrongswan/plugins/openssl/openssl_plugin.c +++ b/src/libstrongswan/plugins/openssl/openssl_plugin.c @@ -301,11 +301,11 @@ static private_key_t *openssl_private_key_load(key_type_t type, va_list args) { #ifndef OPENSSL_NO_RSA case EVP_PKEY_RSA: - return openssl_rsa_private_key_create(key); + return openssl_rsa_private_key_create(key, FALSE); #endif #ifndef OPENSSL_NO_ECDSA case EVP_PKEY_EC: - return openssl_ec_private_key_create(key); + return openssl_ec_private_key_create(key, FALSE); #endif default: EVP_PKEY_free(key); @@ -316,6 +316,152 @@ static private_key_t *openssl_private_key_load(key_type_t type, va_list args) return NULL; } +#ifndef OPENSSL_NO_ENGINE +/** + * Login to engine with a PIN specified for a keyid + */ +static bool login(ENGINE *engine, chunk_t keyid) +{ + enumerator_t *enumerator; + shared_key_t *shared; + identification_t *id; + chunk_t key; + char pin[64]; + bool found = FALSE, success = FALSE; + + id = identification_create_from_encoding(ID_KEY_ID, keyid); + enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, + SHARED_PIN, id, NULL); + while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) + { + found = TRUE; + key = shared->get_key(shared); + if (snprintf(pin, sizeof(pin), + "%.*s", (int)key.len, key.ptr) >= sizeof(pin)) + { + continue; + } + if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) + { + success = TRUE; + break; + } + else + { + DBG1(DBG_CFG, "setting PIN on engine failed"); + } + } + enumerator->destroy(enumerator); + id->destroy(id); + if (!found) + { + DBG1(DBG_CFG, "no PIN found for %#B", &keyid); + } + return success; +} +#endif /* OPENSSL_NO_ENGINE */ + +/** + * Load private key via engine + */ +static private_key_t *openssl_private_key_connect(key_type_t type, + va_list args) +{ +#ifndef OPENSSL_NO_ENGINE + char *engine_id = NULL; + char keyname[BUF_LEN]; + chunk_t keyid = chunk_empty;; + EVP_PKEY *key; + ENGINE *engine; + int slot = -1; + + while (TRUE) + { + switch (va_arg(args, builder_part_t)) + { + case BUILD_PKCS11_KEYID: + keyid = va_arg(args, chunk_t); + continue; + case BUILD_PKCS11_SLOT: + slot = va_arg(args, int); + continue; + case BUILD_PKCS11_MODULE: + engine_id = va_arg(args, char*); + continue; + case BUILD_END: + break; + default: + return NULL; + } + break; + } + if (!keyid.len || keyid.len > 40) + { + return NULL; + } + + memset(keyname, 0, sizeof(keyname)); + if (slot != -1) + { + snprintf(keyname, sizeof(keyname), "%d:", slot); + } + if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) + { + return NULL; + } + chunk_to_hex(keyid, keyname + strlen(keyname), FALSE); + + if (!engine_id) + { + engine_id = lib->settings->get_str(lib->settings, + "%s.plugins.openssl.engine_id", "pkcs11", lib->ns); + } + engine = ENGINE_by_id(engine_id); + if (!engine) + { + DBG2(DBG_LIB, "engine '%s' is not available", engine_id); + return NULL; + } + if (!ENGINE_init(engine)) + { + DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id); + ENGINE_free(engine); + return NULL; + } + if (!login(engine, keyid)) + { + DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); + ENGINE_free(engine); + return NULL; + } + key = ENGINE_load_private_key(engine, keyname, NULL, NULL); + if (!key) + { + DBG1(DBG_LIB, "failed to load private key with ID '%s' from " + "engine '%s'", keyname, engine_id); + ENGINE_free(engine); + return NULL; + } + ENGINE_free(engine); + + switch (EVP_PKEY_base_id(key)) + { +#ifndef OPENSSL_NO_RSA + case EVP_PKEY_RSA: + return openssl_rsa_private_key_create(key, TRUE); +#endif +#ifndef OPENSSL_NO_ECDSA + case EVP_PKEY_EC: + return openssl_ec_private_key_create(key, TRUE); +#endif + default: + EVP_PKEY_free(key); + break; + } +#endif /* OPENSSL_NO_ENGINE */ + return NULL; +} + METHOD(plugin_t, get_name, char*, private_openssl_plugin_t *this) { @@ -469,8 +615,6 @@ METHOD(plugin_t, get_features, int, /* RSA private/public key loading */ PLUGIN_REGISTER(PRIVKEY, openssl_rsa_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_RSA), - PLUGIN_REGISTER(PRIVKEY, openssl_rsa_private_key_connect, FALSE), - PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(PRIVKEY_GEN, openssl_rsa_private_key_gen, FALSE), PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_RSA), PLUGIN_REGISTER(PUBKEY, openssl_rsa_public_key_load, TRUE), @@ -480,6 +624,10 @@ METHOD(plugin_t, get_features, int, /* signature/encryption schemes */ PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_NULL), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_NULL), +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PSS), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PSS), +#endif #ifndef OPENSSL_NO_SHA1 PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_RSA_EMSA_PKCS1_SHA1), PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_RSA_EMSA_PKCS1_SHA1), @@ -554,6 +702,8 @@ METHOD(plugin_t, get_features, int, /* generic key loader */ PLUGIN_REGISTER(PRIVKEY, openssl_private_key_load, TRUE), PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), + PLUGIN_REGISTER(PRIVKEY, openssl_private_key_connect, FALSE), + PLUGIN_PROVIDE(PRIVKEY, KEY_ANY), PLUGIN_REGISTER(RNG, openssl_rng_create), PLUGIN_PROVIDE(RNG, RNG_STRONG), PLUGIN_PROVIDE(RNG, RNG_WEAK), diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c index 54ecf2542..401a51a0b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2016 Tobias Brunner + * Copyright (C) 2008-2017 Tobias Brunner * Copyright (C) 2009 Martin Willi * HSR Hochschule fuer Technik Rapperswil * @@ -20,16 +20,15 @@ #include "openssl_rsa_private_key.h" #include "openssl_rsa_public_key.h" +#include "openssl_hasher.h" #include "openssl_util.h" #include <utils/debug.h> +#include <credentials/keys/signature_params.h> #include <openssl/bn.h> #include <openssl/evp.h> #include <openssl/rsa.h> -#ifndef OPENSSL_NO_ENGINE -#include <openssl/engine.h> -#endif /* OPENSSL_NO_ENGINE */ /** * Public exponent to use for key generation. @@ -40,6 +39,7 @@ OPENSSL_KEY_FALLBACK(RSA, key, n, e, d) OPENSSL_KEY_FALLBACK(RSA, factors, p, q) OPENSSL_KEY_FALLBACK(RSA, crt_params, dmp1, dmq1, iqmp) +#define BN_secure_new() BN_new() #endif typedef struct private_openssl_rsa_private_key_t private_openssl_rsa_private_key_t; @@ -72,8 +72,126 @@ struct private_openssl_rsa_private_key_t { /* implemented in rsa public key */ bool openssl_rsa_fingerprint(RSA *rsa, cred_encoding_type_t type, chunk_t *fp); +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + /** - * Build an EMPSA PKCS1 signature described in PKCS#1 + * Build RSA signature + */ +static bool build_signature(private_openssl_rsa_private_key_t *this, + const EVP_MD *md, rsa_pss_params_t *pss, + chunk_t data, chunk_t *sig) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY *key; + bool success = FALSE; + + mctx = EVP_MD_CTX_create(); + key = EVP_PKEY_new(); + if (!mctx || !key) + { + goto error; + } + if (!EVP_PKEY_set1_RSA(key, this->rsa)) + { + goto error; + } + if (EVP_DigestSignInit(mctx, &pctx, md, NULL, key) <= 0) + { + goto error; + } + if (pss) + { + const EVP_MD *mgf1md = openssl_get_md(pss->mgf1_hash); + int slen = EVP_MD_size(md); + if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + slen = pss->salt_len; + } + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, slen) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md) <= 0) + { + goto error; + } + } + if (EVP_DigestSignUpdate(mctx, data.ptr, data.len) <= 0) + { + goto error; + } + success = (EVP_DigestSignFinal(mctx, sig->ptr, &sig->len) == 1); + +error: + if (key) + { + EVP_PKEY_free(key); + } + if (mctx) + { + EVP_MD_CTX_destroy(mctx); + } + return success; +} + +/** + * Build an EMSA PKCS1 signature described in PKCS#1 + */ +static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, + int type, chunk_t data, chunk_t *sig) +{ + const EVP_MD *md; + + *sig = chunk_alloc(RSA_size(this->rsa)); + + if (type == NID_undef) + { + if (RSA_private_encrypt(data.len, data.ptr, sig->ptr, this->rsa, + RSA_PKCS1_PADDING) == sig->len) + { + return TRUE; + } + } + else + { + md = EVP_get_digestbynid(type); + if (md && build_signature(this, md, NULL, data, sig)) + { + return TRUE; + } + } + chunk_free(sig); + return FALSE; +} + +/** + * Build an EMSA PSS signature described in PKCS#1 + */ +static bool build_emsa_pss_signature(private_openssl_rsa_private_key_t *this, + rsa_pss_params_t *params, chunk_t data, + chunk_t *sig) +{ + const EVP_MD *md; + + if (!params) + { + return FALSE; + } + + *sig = chunk_alloc(RSA_size(this->rsa)); + + md = openssl_get_md(params->hash); + if (md && build_signature(this, md, params, data, sig)) + { + return TRUE; + } + chunk_free(sig); + return FALSE; +} + +#else /* OPENSSL_VERSION_NUMBER < 1.0 */ + +/** + * Build an EMSA PKCS1 signature described in PKCS#1 */ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, int type, chunk_t data, chunk_t *sig) @@ -92,15 +210,15 @@ static bool build_emsa_pkcs1_signature(private_openssl_rsa_private_key_t *this, } else { - EVP_MD_CTX *ctx; - EVP_PKEY *key; + EVP_MD_CTX *ctx = NULL; + EVP_PKEY *key = NULL; const EVP_MD *hasher; u_int len; hasher = EVP_get_digestbynid(type); if (!hasher) { - return FALSE; + goto error; } ctx = EVP_MD_CTX_create(); @@ -142,7 +260,7 @@ error: } return success; } - +#endif /* OPENSSL_VERSION_NUMBER < 1.0 */ METHOD(private_key_t, get_type, key_type_t, private_openssl_rsa_private_key_t *this) @@ -152,7 +270,7 @@ METHOD(private_key_t, get_type, key_type_t, METHOD(private_key_t, sign, bool, private_openssl_rsa_private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) + void *params, chunk_t data, chunk_t *signature) { switch (scheme) { @@ -170,6 +288,10 @@ METHOD(private_key_t, sign, bool, return build_emsa_pkcs1_signature(this, NID_sha1, data, signature); case SIGN_RSA_EMSA_PKCS1_MD5: return build_emsa_pkcs1_signature(this, NID_md5, data, signature); +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + case SIGN_RSA_EMSA_PSS: + return build_emsa_pss_signature(this, params, data, signature); +#endif default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); @@ -386,7 +508,7 @@ error: /* * See header */ -private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key) +private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key, bool engine) { private_openssl_rsa_private_key_t *this; RSA *rsa; @@ -399,9 +521,199 @@ private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key) } this = create_empty(); this->rsa = rsa; + this->engine = engine; return &this->public.key; } +/** + * Recover the primes from n, e and d using the algorithm described in + * Appendix C of NIST SP 800-56B. + */ +static bool calculate_pq(BIGNUM *n, BIGNUM *e, BIGNUM *d, + BIGNUM **p, BIGNUM **q) +{ + BN_CTX *ctx; + BIGNUM *k, *r, *g, *y, *n1, *x; + int i, t, j; + bool success = FALSE; + + ctx = BN_CTX_new(); + if (!ctx) + { + return FALSE; + } + BN_CTX_start(ctx); + k = BN_CTX_get(ctx); + r = BN_CTX_get(ctx); + g = BN_CTX_get(ctx); + y = BN_CTX_get(ctx); + n1 = BN_CTX_get(ctx); + x = BN_CTX_get(ctx); + if (!x) + { + goto error; + } + /* k = (d * e) - 1 */ + if (!BN_mul(k, d, e, ctx) || !BN_sub(k, k, BN_value_one())) + { + goto error; + } + /* k must be even */ + if (BN_is_odd(k)) + { + goto error; + } + /* k = 2^t * r, where r is the largest odd integer dividing k, and t >= 1 */ + if (!BN_copy(r, k)) + { + goto error; + } + for (t = 0; !BN_is_odd(r); t++) + { /* r = r/2 */ + if (!BN_rshift(r, r, 1)) + { + goto error; + } + } + /* we need n-1 below */ + if (!BN_sub(n1, n, BN_value_one())) + { + goto error; + } + for (i = 0; i < 100; i++) + { /* generate random integer g in [0, n-1] */ + if (!BN_pseudo_rand_range(g, n)) + { + goto error; + } + /* y = g^r mod n */ + if (!BN_mod_exp(y, g, r, n, ctx)) + { + goto error; + } + /* try again if y == 1 or y == n-1 */ + if (BN_is_one(y) || BN_cmp(y, n1) == 0) + { + continue; + } + for (j = 0; j < t; j++) + { /* x = y^2 mod n */ + if (!BN_mod_sqr(x, y, n, ctx)) + { + goto error; + } + /* stop if x == 1 */ + if (BN_is_one(x)) + { + goto done; + } + /* retry with new g if x = n-1 */ + if (BN_cmp(x, n1) == 0) + { + break; + } + /* y = x */ + if (!BN_copy(y, x)) + { + goto error; + } + } + } + goto error; + +done: + /* p = gcd(y-1, n) */ + if (!BN_sub(y, y, BN_value_one())) + { + goto error; + } + *p = BN_secure_new(); + if (!BN_gcd(*p, y, n, ctx)) + { + BN_clear_free(*p); + goto error; + } + /* q = n/p */ + *q = BN_secure_new(); + if (!BN_div(*q, NULL, n, *p, ctx)) + { + BN_clear_free(*p); + BN_clear_free(*q); + goto error; + } + success = TRUE; + +error: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return success; +} + +/** + * Calculates dp = d (mod p-1) or dq = d (mod q-1) for the Chinese remainder + * algorithm. + */ +static BIGNUM *dmodpq1(BIGNUM *d, BIGNUM *pq) +{ + BN_CTX *ctx; + BIGNUM *res = NULL, *pq1; + + ctx = BN_CTX_new(); + if (!ctx) + { + return NULL; + } + BN_CTX_start(ctx); + pq1 = BN_CTX_get(ctx); + /* p|q - 1 */ + if (!BN_sub(pq1, pq, BN_value_one())) + { + goto error; + } + /* d (mod p|q -1) */ + res = BN_secure_new(); + if (!BN_mod(res, d, pq1, ctx)) + { + BN_clear_free(res); + res = NULL; + goto error; + } + +error: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return res; +} + +/** + * Calculates qinv = q^-1 (mod p) for the Chinese remainder algorithm. + */ +static BIGNUM *qinv(BIGNUM *q, BIGNUM *p) +{ + BN_CTX *ctx; + BIGNUM *res = NULL; + + ctx = BN_CTX_new(); + if (!ctx) + { + return NULL; + } + BN_CTX_start(ctx); + /* q^-1 (mod p) */ + res = BN_secure_new(); + if (!BN_mod_inverse(res, q, p, ctx)) + { + BN_clear_free(res); + res = NULL; + goto error; + } + +error: + BN_CTX_end(ctx); + BN_CTX_free(ctx); + return res; +} + /* * See header */ @@ -460,7 +772,7 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, return &this->public; } } - else if (n.ptr && e.ptr && d.ptr && p.ptr && q.ptr && coeff.ptr) + else if (n.ptr && e.ptr && d.ptr) { BIGNUM *bn_n, *bn_e, *bn_d, *bn_p, *bn_q; BIGNUM *dmp1 = NULL, *dmq1 = NULL, *iqmp = NULL; @@ -472,178 +784,58 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, bn_d = BN_bin2bn((const u_char*)d.ptr, d.len, NULL); if (!RSA_set0_key(this->rsa, bn_n, bn_e, bn_d)) { - destroy(this); - return NULL; + goto error; } - bn_p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL); - bn_q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL); + if (p.ptr && q.ptr) + { + bn_p = BN_bin2bn((const u_char*)p.ptr, p.len, NULL); + bn_q = BN_bin2bn((const u_char*)q.ptr, q.len, NULL); + } + else + { + if (!calculate_pq(bn_n, bn_e, bn_d, &bn_p, &bn_q)) + { + goto error; + } + } if (!RSA_set0_factors(this->rsa, bn_p, bn_q)) { - destroy(this); - return NULL; + goto error; } if (exp1.ptr) { dmp1 = BN_bin2bn((const u_char*)exp1.ptr, exp1.len, NULL); } - if (exp2.ptr) + else { - dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL); + dmp1 = dmodpq1(bn_d, bn_p); } - iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL); - if (RSA_set0_crt_params(this->rsa, dmp1, dmq1, iqmp) && - RSA_check_key(this->rsa) == 1) + if (exp2.ptr) { - return &this->public; + dmq1 = BN_bin2bn((const u_char*)exp2.ptr, exp2.len, NULL); } - } - destroy(this); - return NULL; -} - -#ifndef OPENSSL_NO_ENGINE -/** - * Login to engine with a PIN specified for a keyid - */ -static bool login(ENGINE *engine, chunk_t keyid) -{ - enumerator_t *enumerator; - shared_key_t *shared; - identification_t *id; - chunk_t key; - char pin[64]; - bool found = FALSE, success = FALSE; - - id = identification_create_from_encoding(ID_KEY_ID, keyid); - enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, - SHARED_PIN, id, NULL); - while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) - { - found = TRUE; - key = shared->get_key(shared); - if (snprintf(pin, sizeof(pin), - "%.*s", (int)key.len, key.ptr) >= sizeof(pin)) + else { - continue; + dmq1 = dmodpq1(bn_d, bn_q); } - if (ENGINE_ctrl_cmd_string(engine, "PIN", pin, 0)) + if (coeff.ptr) { - success = TRUE; - break; + iqmp = BN_bin2bn((const u_char*)coeff.ptr, coeff.len, NULL); } else { - DBG1(DBG_CFG, "setting PIN on engine failed"); + iqmp = qinv(bn_q, bn_p); } - } - enumerator->destroy(enumerator); - id->destroy(id); - if (!found) - { - DBG1(DBG_CFG, "no PIN found for %#B", &keyid); - } - return success; -} -#endif /* OPENSSL_NO_ENGINE */ - -/* - * See header. - */ -openssl_rsa_private_key_t *openssl_rsa_private_key_connect(key_type_t type, - va_list args) -{ -#ifndef OPENSSL_NO_ENGINE - private_openssl_rsa_private_key_t *this; - char *engine_id = NULL; - char keyname[64]; - chunk_t keyid = chunk_empty;; - EVP_PKEY *key; - ENGINE *engine; - int slot = -1; - - while (TRUE) - { - switch (va_arg(args, builder_part_t)) + if (RSA_set0_crt_params(this->rsa, dmp1, dmq1, iqmp) && + RSA_check_key(this->rsa) == 1) { - case BUILD_PKCS11_KEYID: - keyid = va_arg(args, chunk_t); - continue; - case BUILD_PKCS11_SLOT: - slot = va_arg(args, int); - continue; - case BUILD_PKCS11_MODULE: - engine_id = va_arg(args, char*); - continue; - case BUILD_END: - break; - default: - return NULL; + return &this->public; } - break; - } - if (!keyid.len || keyid.len > 40) - { - return NULL; - } - - memset(keyname, 0, sizeof(keyname)); - if (slot != -1) - { - snprintf(keyname, sizeof(keyname), "%d:", slot); - } - if (sizeof(keyname) - strlen(keyname) <= keyid.len * 4 / 3 + 1) - { - return NULL; - } - chunk_to_hex(keyid, keyname + strlen(keyname), FALSE); - - if (!engine_id) - { - engine_id = lib->settings->get_str(lib->settings, - "%s.plugins.openssl.engine_id", "pkcs11", lib->ns); - } - engine = ENGINE_by_id(engine_id); - if (!engine) - { - DBG2(DBG_LIB, "engine '%s' is not available", engine_id); - return NULL; - } - if (!ENGINE_init(engine)) - { - DBG1(DBG_LIB, "failed to initialize engine '%s'", engine_id); - ENGINE_free(engine); - return NULL; - } - if (!login(engine, keyid)) - { - DBG1(DBG_LIB, "login to engine '%s' failed", engine_id); - ENGINE_free(engine); - return NULL; - } - key = ENGINE_load_private_key(engine, keyname, NULL, NULL); - if (!key) - { - DBG1(DBG_LIB, "failed to load private key with ID '%s' from " - "engine '%s'", keyname, engine_id); - ENGINE_free(engine); - return NULL; - } - ENGINE_free(engine); - - this = create_empty(); - this->rsa = EVP_PKEY_get1_RSA(key); - this->engine = TRUE; - if (!this->rsa) - { - destroy(this); - return NULL; } - - return &this->public; -#else /* OPENSSL_NO_ENGINE */ +error: + destroy(this); return NULL; -#endif /* OPENSSL_NO_ENGINE */ } #endif /* OPENSSL_NO_RSA */ diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h index 34ce4c776..783181c1d 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_private_key.h @@ -67,9 +67,10 @@ openssl_rsa_private_key_t *openssl_rsa_private_key_load(key_type_t type, * Wrap an EVP_PKEY object of type EVP_PKEY_RSA * * @param key EVP_PKEY_RSA key object (adopted) + * @param engine whether the key was loaded via an engine * @return loaded key, NULL on failure */ -private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key); +private_key_t *openssl_rsa_private_key_create(EVP_PKEY *key, bool engine); /** * Connect to a RSA private key on a smartcard. diff --git a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c index d3a644f72..20bf30ae9 100644 --- a/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c +++ b/src/libstrongswan/plugins/openssl/openssl_rsa_public_key.c @@ -1,7 +1,7 @@ /* + * Copyright (C) 2008-2017 Tobias Brunner * Copyright (C) 2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner - * Hochschule fuer Technik Rapperswil + * 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 @@ -19,9 +19,11 @@ #ifndef OPENSSL_NO_RSA #include "openssl_rsa_public_key.h" +#include "openssl_hasher.h" #include "openssl_util.h" #include <utils/debug.h> +#include <credentials/keys/signature_params.h> #include <openssl/bn.h> #include <openssl/evp.h> @@ -54,8 +56,138 @@ struct private_openssl_rsa_public_key_t { refcount_t ref; }; + +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + +/** + * Verify RSA signature + */ +static bool verify_signature(private_openssl_rsa_public_key_t *this, + const EVP_MD *md, rsa_pss_params_t *pss, + chunk_t data, chunk_t signature) +{ + EVP_PKEY_CTX *pctx = NULL; + EVP_MD_CTX *mctx = NULL; + EVP_PKEY *key; + int rsa_size = RSA_size(this->rsa); + bool valid = FALSE; + + /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */ + if (signature.len > rsa_size) + { + signature = chunk_skip(signature, signature.len - rsa_size); + } + + mctx = EVP_MD_CTX_create(); + key = EVP_PKEY_new(); + if (!mctx || !key) + { + goto error; + } + if (!EVP_PKEY_set1_RSA(key, this->rsa)) + { + goto error; + } + if (EVP_DigestVerifyInit(mctx, &pctx, md, NULL, key) <= 0) + { + goto error; + } + if (pss) + { + const EVP_MD *mgf1md = openssl_get_md(pss->mgf1_hash); + int slen = EVP_MD_size(md); + if (pss->salt_len > RSA_PSS_SALT_LEN_DEFAULT) + { + slen = pss->salt_len; + } + if (EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) <= 0 || + EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx, slen) <= 0 || + EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf1md) <= 0) + { + goto error; + } + } + if (EVP_DigestVerifyUpdate(mctx, data.ptr, data.len) <= 0) + { + goto error; + } + valid = (EVP_DigestVerifyFinal(mctx, signature.ptr, signature.len) == 1); + +error: + if (key) + { + EVP_PKEY_free(key); + } + if (mctx) + { + EVP_MD_CTX_destroy(mctx); + } + return valid; +} + /** - * Verification of an EMPSA PKCS1 signature described in PKCS#1 + * Verification of a signature without hashing + */ +static bool verify_plain_signature(private_openssl_rsa_public_key_t *this, + chunk_t data, chunk_t signature) +{ + char *buf; + int len, rsa_size = RSA_size(this->rsa); + bool valid = FALSE; + + /* OpenSSL expects a signature of exactly RSA size (no leading 0x00) */ + if (signature.len > rsa_size) + { + signature = chunk_skip(signature, signature.len - rsa_size); + } + buf = malloc(rsa_size); + len = RSA_public_decrypt(signature.len, signature.ptr, buf, this->rsa, + RSA_PKCS1_PADDING); + if (len != -1) + { + valid = chunk_equals_const(data, chunk_create(buf, len)); + } + free(buf); + return valid; +} + +/** + * Verification of an EMSA PKCS1 signature described in PKCS#1 + */ +static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this, + int type, chunk_t data, chunk_t signature) +{ + const EVP_MD *md; + + if (type == NID_undef) + { + return verify_plain_signature(this, data, signature); + } + md = EVP_get_digestbynid(type); + return md && verify_signature(this, md, NULL, data, signature); +} + +/** + * Verification of an EMSA PSS signature described in PKCS#1 + */ +static bool verify_emsa_pss_signature(private_openssl_rsa_public_key_t *this, + rsa_pss_params_t *params, chunk_t data, + chunk_t signature) +{ + const EVP_MD *md; + + if (!params) + { + return FALSE; + } + md = openssl_get_md(params->hash); + return md && verify_signature(this, md, params, data, signature); +} + +#else /* OPENSSL_VERSION_NUMBER < 1.0 */ + +/** + * Verification of an EMSA PKCS1 signature described in PKCS#1 */ static bool verify_emsa_pkcs1_signature(private_openssl_rsa_public_key_t *this, int type, chunk_t data, chunk_t signature) @@ -129,6 +261,8 @@ error: return valid; } +#endif /* OPENSSL_VERSION_NUMBER < 1.0 */ + METHOD(public_key_t, get_type, key_type_t, private_openssl_rsa_public_key_t *this) { @@ -137,7 +271,7 @@ METHOD(public_key_t, get_type, key_type_t, METHOD(public_key_t, verify, bool, private_openssl_rsa_public_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t signature) + void *params, chunk_t data, chunk_t signature) { switch (scheme) { @@ -155,6 +289,10 @@ METHOD(public_key_t, verify, bool, return verify_emsa_pkcs1_signature(this, NID_sha1, data, signature); case SIGN_RSA_EMSA_PKCS1_MD5: return verify_emsa_pkcs1_signature(this, NID_md5, data, signature); +#if OPENSSL_VERSION_NUMBER >= 0x10000000L + case SIGN_RSA_EMSA_PSS: + return verify_emsa_pss_signature(this, params, data, signature); +#endif default: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", signature_scheme_names, scheme); diff --git a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c index f6df03f12..3a6d2f193 100644 --- a/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c +++ b/src/libstrongswan/plugins/openssl/openssl_sha1_prf.c @@ -20,6 +20,7 @@ #include "openssl_sha1_prf.h" #include <openssl/sha.h> +#include <crypto/hashers/hasher.h> typedef struct private_openssl_sha1_prf_t private_openssl_sha1_prf_t; diff --git a/src/libstrongswan/plugins/openssl/openssl_x509.c b/src/libstrongswan/plugins/openssl/openssl_x509.c index e03a4255d..60c08770b 100644 --- a/src/libstrongswan/plugins/openssl/openssl_x509.c +++ b/src/libstrongswan/plugins/openssl/openssl_x509.c @@ -1,6 +1,6 @@ /* - * Copyright (C) 2011 Tobias Brunner - * Hochschule fuer Technik Rapperswil + * Copyright (C) 2011-2017 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil * * Copyright (C) 2010 Martin Willi * Copyright (C) 2010 revosec AG @@ -154,7 +154,7 @@ struct private_openssl_x509_t { /** * Signature scheme of the certificate */ - signature_scheme_t scheme; + signature_params_t *scheme; /** * subjectAltNames @@ -189,16 +189,6 @@ struct private_openssl_x509_t { }; /** - * Destroy a CRL URI struct - */ -static void crl_uri_destroy(x509_cdp_t *this) -{ - free(this->uri); - DESTROY_IF(this->issuer); - free(this); -} - -/** * Convert a GeneralName to an identification_t. */ static identification_t *general_name2id(GENERAL_NAME *name) @@ -394,7 +384,7 @@ METHOD(certificate_t, has_issuer, id_match_t, METHOD(certificate_t, issued_by, bool, private_openssl_x509_t *this, certificate_t *issuer, - signature_scheme_t *scheme) + signature_params_t **scheme) { public_key_t *key; bool valid; @@ -406,7 +396,8 @@ METHOD(certificate_t, issued_by, bool, { if (this->flags & X509_SELF_SIGNED) { - return TRUE; + valid = TRUE; + goto out; } } else @@ -424,10 +415,6 @@ METHOD(certificate_t, issued_by, bool, return FALSE; } } - if (this->scheme == SIGN_UNKNOWN) - { - return FALSE; - } key = issuer->get_public_key(issuer); if (!key) { @@ -440,12 +427,15 @@ METHOD(certificate_t, issued_by, bool, tbs = openssl_i2chunk(X509_CINF, this->x509->cert_info); #endif X509_get0_signature(&sig, NULL, this->x509); - valid = key->verify(key, this->scheme, tbs, openssl_asn1_str2chunk(sig)); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, tbs, + openssl_asn1_str2chunk(sig)); free(tbs.ptr); key->destroy(key); + +out: if (valid && scheme) { - *scheme = this->scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -538,6 +528,7 @@ METHOD(certificate_t, destroy, void, { X509_free(this->x509); } + signature_params_destroy(this->scheme); DESTROY_IF(this->subject); DESTROY_IF(this->issuer); DESTROY_IF(this->pubkey); @@ -549,7 +540,8 @@ METHOD(certificate_t, destroy, void, offsetof(identification_t, destroy)); this->issuerAltNames->destroy_offset(this->issuerAltNames, offsetof(identification_t, destroy)); - this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy); + this->crl_uris->destroy_function(this->crl_uris, + (void*)x509_cdp_destroy); this->ocsp_uris->destroy_function(this->ocsp_uris, free); this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks, offsetof(traffic_selector_t, destroy)); @@ -739,15 +731,15 @@ static bool parse_extKeyUsage_ext(private_openssl_x509_t *this, /** * Parse CRL distribution points */ -static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this, - X509_EXTENSION *ext) +bool openssl_parse_crlDistributionPoints(X509_EXTENSION *ext, + linked_list_t *list) { CRL_DIST_POINTS *cdps; DIST_POINT *cdp; identification_t *id, *issuer; x509_cdp_t *entry; char *uri; - int i, j, k, point_num, name_num, issuer_num; + int i, j, k, point_num, name_num, issuer_num, len; cdps = X509V3_EXT_d2i(ext); if (!cdps) @@ -770,7 +762,12 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this, cdp->distpoint->name.fullname, j)); if (id) { - if (asprintf(&uri, "%Y", id) > 0) + len = asprintf(&uri, "%Y", id); + if (!len) + { + free(uri); + } + else if (len > 0) { if (cdp->CRLissuer) { @@ -785,8 +782,7 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this, .uri = strdup(uri), .issuer = issuer, ); - this->crl_uris->insert_last( - this->crl_uris, entry); + list->insert_last(list, entry); } } free(uri); @@ -796,7 +792,7 @@ static bool parse_crlDistributionPoints_ext(private_openssl_x509_t *this, INIT(entry, .uri = uri, ); - this->crl_uris->insert_last(this->crl_uris, entry); + list->insert_last(list, entry); } } id->destroy(id); @@ -820,7 +816,7 @@ static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this, AUTHORITY_INFO_ACCESS *infos; ACCESS_DESCRIPTION *desc; identification_t *id; - int i, num; + int i, num, len; char *uri; infos = X509V3_EXT_d2i(ext); @@ -839,7 +835,12 @@ static bool parse_authorityInfoAccess_ext(private_openssl_x509_t *this, id = general_name2id(desc->location); if (id) { - if (asprintf(&uri, "%Y", id) > 0) + len = asprintf(&uri, "%Y", id); + if (!len) + { + free(uri); + } + else if (len > 0) { this->ocsp_uris->insert_last(this->ocsp_uris, uri); } @@ -1025,7 +1026,7 @@ static bool parse_extensions(private_openssl_x509_t *this) ok = parse_extKeyUsage_ext(this, ext); break; case NID_crl_distribution_points: - ok = parse_crlDistributionPoints_ext(this, ext); + ok = openssl_parse_crlDistributionPoints(ext, this->crl_uris); break; #ifndef OPENSSL_NO_RFC3779 case NID_sbgp_ipAddrBlock: @@ -1063,8 +1064,8 @@ static bool parse_certificate(private_openssl_x509_t *this) { const unsigned char *ptr = this->encoding.ptr; hasher_t *hasher; - chunk_t chunk; - ASN1_OBJECT *oid, *oid_tbs; + chunk_t chunk, sig_scheme, sig_scheme_tbs; + ASN1_OBJECT *oid; X509_ALGOR *alg; this->x509 = d2i_X509(NULL, &ptr, this->encoding.len); @@ -1089,6 +1090,10 @@ static bool parse_certificate(private_openssl_x509_t *this) } switch (openssl_asn1_known_oid(oid)) { + case OID_RSASSA_PSS: + /* TODO: we should treat such keys special and use the params as + * restrictions regarding the use of this key (or rather the + * associated private key) */ case OID_RSA_ENCRYPTION: this->pubkey = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_RSA, BUILD_BLOB_ASN1_DER, @@ -1119,15 +1124,25 @@ static bool parse_certificate(private_openssl_x509_t *this) /* while X509_ALGOR_cmp() is declared in the headers of older OpenSSL * versions, at least on Ubuntu 14.04 it is not actually defined */ X509_get0_signature(NULL, &alg, this->x509); - X509_ALGOR_get0(&oid, NULL, NULL, alg); + sig_scheme = openssl_i2chunk(X509_ALGOR, alg); alg = X509_get0_tbs_sigalg(this->x509); - X509_ALGOR_get0(&oid_tbs, NULL, NULL, alg); - if (!chunk_equals(openssl_asn1_obj2chunk(oid), - openssl_asn1_obj2chunk(oid_tbs))) + sig_scheme_tbs = openssl_i2chunk(X509_ALGOR, alg); + if (!chunk_equals(sig_scheme, sig_scheme_tbs)) + { + free(sig_scheme_tbs.ptr); + free(sig_scheme.ptr); + return FALSE; + } + free(sig_scheme_tbs.ptr); + + INIT(this->scheme); + if (!signature_params_parse(sig_scheme, 0, this->scheme)) { + DBG1(DBG_ASN, "unable to parse signature algorithm"); + free(sig_scheme.ptr); return FALSE; } - this->scheme = signature_scheme_from_oid(openssl_asn1_known_oid(oid)); + free(sig_scheme.ptr); if (!parse_extensions(this)) { diff --git a/src/libstrongswan/plugins/padlock/Makefile.in b/src/libstrongswan/plugins/padlock/Makefile.in index 101119300..02a022d03 100644 --- a/src/libstrongswan/plugins/padlock/Makefile.in +++ b/src/libstrongswan/plugins/padlock/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pem/Makefile.in b/src/libstrongswan/plugins/pem/Makefile.in index 4b69f9f49..37917d441 100644 --- a/src/libstrongswan/plugins/pem/Makefile.in +++ b/src/libstrongswan/plugins/pem/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pem/pem_encoder.c b/src/libstrongswan/plugins/pem/pem_encoder.c index 76b0b7b40..8c6c5dae7 100644 --- a/src/libstrongswan/plugins/pem/pem_encoder.c +++ b/src/libstrongswan/plugins/pem/pem_encoder.c @@ -15,6 +15,8 @@ #include "pem_encoder.h" +#include <library.h> + #define BYTES_PER_LINE 48 /** diff --git a/src/libstrongswan/plugins/pgp/Makefile.in b/src/libstrongswan/plugins/pgp/Makefile.in index 8104a2a94..10eb82619 100644 --- a/src/libstrongswan/plugins/pgp/Makefile.in +++ b/src/libstrongswan/plugins/pgp/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pgp/pgp_builder.c b/src/libstrongswan/plugins/pgp/pgp_builder.c index fe0be45d9..e8f5c5ddf 100644 --- a/src/libstrongswan/plugins/pgp/pgp_builder.c +++ b/src/libstrongswan/plugins/pgp/pgp_builder.c @@ -116,21 +116,17 @@ static private_key_t *parse_rsa_private_key(chunk_t blob) BUILD_END); } -/** - * Implementation of private_key_t.sign for encryption-only keys - */ -static bool sign_not_allowed(private_key_t *this, signature_scheme_t scheme, - chunk_t data, chunk_t *signature) +METHOD(private_key_t, sign_not_allowed, bool, + private_key_t *this, signature_scheme_t scheme, void *params, + chunk_t data, chunk_t *signature) { DBG1(DBG_LIB, "signing failed - decryption only key"); return FALSE; } -/** - * Implementation of private_key_t.decrypt for signature-only keys - */ -static bool decrypt_not_allowed(private_key_t *this, encryption_scheme_t scheme, - chunk_t crypto, chunk_t *plain) +METHOD(private_key_t, decrypt_not_allowed, bool, + private_key_t *this, encryption_scheme_t scheme, + chunk_t crypto, chunk_t *plain) { DBG1(DBG_LIB, "decryption failed - signature only key"); return FALSE; @@ -186,7 +182,7 @@ static private_key_t *parse_private_key(chunk_t blob) BUILD_BLOB_PGP, packet, BUILD_END); if (key) { - key->sign = sign_not_allowed; + key->sign = _sign_not_allowed; } return key; case PGP_PUBKEY_ALG_RSA_SIGN_ONLY: @@ -194,7 +190,7 @@ static private_key_t *parse_private_key(chunk_t blob) BUILD_BLOB_PGP, packet, BUILD_END); if (key) { - key->decrypt = decrypt_not_allowed; + key->decrypt = _decrypt_not_allowed; } return key; case PGP_PUBKEY_ALG_ECDSA: diff --git a/src/libstrongswan/plugins/pgp/pgp_cert.c b/src/libstrongswan/plugins/pgp/pgp_cert.c index 0ffce4cfc..392ef5440 100644 --- a/src/libstrongswan/plugins/pgp/pgp_cert.c +++ b/src/libstrongswan/plugins/pgp/pgp_cert.c @@ -114,7 +114,7 @@ METHOD(certificate_t, has_issuer, id_match_t, } METHOD(certificate_t, issued_by,bool, - private_pgp_cert_t *this, certificate_t *issuer, signature_scheme_t *scheme) + private_pgp_cert_t *this, certificate_t *issuer, signature_params_t **scheme) { /* TODO: check signature blobs for a valid signature */ return FALSE; diff --git a/src/libstrongswan/plugins/pgp/pgp_encoder.c b/src/libstrongswan/plugins/pgp/pgp_encoder.c index 100f3ef33..eba936b83 100644 --- a/src/libstrongswan/plugins/pgp/pgp_encoder.c +++ b/src/libstrongswan/plugins/pgp/pgp_encoder.c @@ -15,6 +15,7 @@ #include "pgp_encoder.h" +#include <library.h> #include <utils/debug.h> /** diff --git a/src/libstrongswan/plugins/pkcs1/Makefile.in b/src/libstrongswan/plugins/pkcs1/Makefile.in index 6f6c6237f..ae24d4085 100644 --- a/src/libstrongswan/plugins/pkcs1/Makefile.in +++ b/src/libstrongswan/plugins/pkcs1/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c index f64294783..967e501d1 100644 --- a/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c +++ b/src/libstrongswan/plugins/pkcs1/pkcs1_builder.c @@ -57,8 +57,13 @@ static public_key_t *parse_public_key(chunk_t blob) int oid = asn1_parse_algorithmIdentifier(object, parser->get_level(parser)+1, NULL); - if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP) + if (oid == OID_RSA_ENCRYPTION || oid == OID_RSAES_OAEP || + oid == OID_RSASSA_PSS) { + /* TODO: we should parse parameters for PSS and pass them + * (and the type), or the complete subjectPublicKeyInfo, + * along so we can treat these as restrictions when + * generating signatures with the associated private key */ type = KEY_RSA; } else if (oid == OID_EC_PUBLICKEY) diff --git a/src/libstrongswan/plugins/pkcs11/Makefile.in b/src/libstrongswan/plugins/pkcs11/Makefile.in index 7bf33d967..00d5a6a5d 100644 --- a/src/libstrongswan/plugins/pkcs11/Makefile.in +++ b/src/libstrongswan/plugins/pkcs11/Makefile.in @@ -249,9 +249,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c index c0033bd8e..b0fa41b6a 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.c @@ -415,13 +415,15 @@ static chunk_t ecparams_lookup(diffie_hellman_group_t group) /** * Described in header. */ -pkcs11_dh_t *pkcs11_dh_create(diffie_hellman_group_t group, - chunk_t g, chunk_t p) +pkcs11_dh_t *pkcs11_dh_create(diffie_hellman_group_t group, ...) { switch (group) { case MODP_CUSTOM: { + chunk_t g, p; + + VA_ARGS_GET(group, g, p); return create_modp(group, p.len, g, p); } case ECP_192_BIT: diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.h b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.h index 2654130c0..1ad58e7a1 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_dh.h +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_dh.h @@ -40,12 +40,10 @@ struct pkcs11_dh_t { * Creates a new pkcs11_dh_t object. * * @param group Diffie Hellman group number to use - * @param g generator in case group is MODP_CUSTOM - * @param p prime in case group is MODP_CUSTOM + * @param ... expects generator and prime as chunk_t if MODP_CUSTOM * @return pkcs11_dh_t object, NULL if not supported */ -pkcs11_dh_t *pkcs11_dh_create(diffie_hellman_group_t group, - chunk_t g, chunk_t p); +pkcs11_dh_t *pkcs11_dh_create(diffie_hellman_group_t group, ...); #endif /** PKCS11_DH_H_ @}*/ diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c index 31bcb0d25..c7dfe69d7 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_manager.c @@ -164,18 +164,13 @@ static void handle_slot(lib_entry_t *entry, CK_SLOT_ID slot, bool hot) } } -/** - * Dispatch slot events - */ -static job_requeue_t dispatch_slot_events(lib_entry_t *entry) +CALLBACK(dispatch_slot_events, job_requeue_t, + lib_entry_t *entry) { CK_SLOT_ID slot; CK_RV rv; - bool old; - old = thread_cancelability(TRUE); rv = entry->lib->f->C_WaitForSlotEvent(0, &slot, NULL); - thread_cancelability(old); if (rv == CKR_FUNCTION_NOT_SUPPORTED || rv == CKR_NO_EVENT) { DBG1(DBG_CFG, "module '%s' does not support hot-plugging, cancelled", @@ -195,6 +190,16 @@ static job_requeue_t dispatch_slot_events(lib_entry_t *entry) return JOB_REQUEUE_DIRECT; } +CALLBACK(cancel_events, bool, + lib_entry_t *entry) +{ + /* it's possible other threads still use the API after this call, but we + * have no other way to return from C_WaitForSlotEvent() if we can't cancel + * the thread because libraries hold locks they don't release */ + entry->lib->f->C_Finalize(NULL); + return TRUE; +} + /** * Get the slot list of a library */ @@ -377,8 +382,8 @@ pkcs11_manager_t *pkcs11_manager_create(pkcs11_manager_token_event_t cb, { query_slots(entry); lib->processor->queue_job(lib->processor, - (job_t*)callback_job_create_with_prio((void*)dispatch_slot_events, - entry, NULL, (void*)return_false, JOB_PRIO_CRITICAL)); + (job_t*)callback_job_create_with_prio(dispatch_slot_events, + entry, NULL, cancel_events, JOB_PRIO_CRITICAL)); } enumerator->destroy(enumerator); diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c index 1d1016911..6158f6d25 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_private_key.c @@ -243,7 +243,7 @@ static bool reauth(private_pkcs11_private_key_t *this, } METHOD(private_key_t, sign, bool, - private_pkcs11_private_key_t *this, signature_scheme_t scheme, + private_pkcs11_private_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t *signature) { CK_MECHANISM_PTR mechanism; diff --git a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c index 384777610..36029fa30 100644 --- a/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c +++ b/src/libstrongswan/plugins/pkcs11/pkcs11_public_key.c @@ -201,7 +201,7 @@ METHOD(public_key_t, get_keysize, int, } METHOD(public_key_t, verify, bool, - private_pkcs11_public_key_t *this, signature_scheme_t scheme, + private_pkcs11_public_key_t *this, signature_scheme_t scheme, void *params, chunk_t data, chunk_t sig) { CK_MECHANISM_PTR mechanism; diff --git a/src/libstrongswan/plugins/pkcs12/Makefile.in b/src/libstrongswan/plugins/pkcs12/Makefile.in index d25a1af44..6bb1b9a36 100644 --- a/src/libstrongswan/plugins/pkcs12/Makefile.in +++ b/src/libstrongswan/plugins/pkcs12/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pkcs7/Makefile.in b/src/libstrongswan/plugins/pkcs7/Makefile.in index e5698a302..f56df39d1 100644 --- a/src/libstrongswan/plugins/pkcs7/Makefile.in +++ b/src/libstrongswan/plugins/pkcs7/Makefile.in @@ -248,9 +248,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c index 413c3fff5..9b6d3a808 100644 --- a/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c +++ b/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c @@ -227,7 +227,8 @@ METHOD(enumerator_t, enumerate, bool, if (key) { chunk = info->attributes->get_encoding(info->attributes); - if (key->verify(key, scheme, chunk, info->encrypted_digest)) + if (key->verify(key, scheme, NULL, chunk, + info->encrypted_digest)) { this->auth = auth->clone(auth); key->destroy(key); @@ -563,7 +564,7 @@ static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key, attributes = pkcs9->get_encoding(pkcs9); - if (!key->sign(key, scheme, attributes, &encryptedDigest)) + if (!key->sign(key, scheme, NULL, attributes, &encryptedDigest)) { free(data.ptr); return FALSE; diff --git a/src/libstrongswan/plugins/pkcs8/Makefile.in b/src/libstrongswan/plugins/pkcs8/Makefile.in index 3ff09f5f2..9c408c443 100644 --- a/src/libstrongswan/plugins/pkcs8/Makefile.in +++ b/src/libstrongswan/plugins/pkcs8/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c index beb8866f8..6cd5da4fd 100644 --- a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c +++ b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c @@ -63,6 +63,17 @@ static private_key_t *parse_private_key(chunk_t blob) switch (oid) { + case OID_RSASSA_PSS: + /* TODO: parameters associated with such keys should be + * treated as restrictions later when signing (the type + * itself is already a restriction). However, the + * builders currently don't expect any parameters for + * RSA keys (we also only pass along the params, not the + * exact type, so we'd have to guess that params + * indicate RSA/PSS, but they are optional so that won't + * work for keys without specific restrictions) */ + params = chunk_empty; + /* fall-through */ case OID_RSA_ENCRYPTION: type = KEY_RSA; break; diff --git a/src/libstrongswan/plugins/plugin_loader.c b/src/libstrongswan/plugins/plugin_loader.c index 42d443b7a..7d0cc88ed 100644 --- a/src/libstrongswan/plugins/plugin_loader.c +++ b/src/libstrongswan/plugins/plugin_loader.c @@ -438,7 +438,7 @@ static plugin_entry_t *load_plugin(private_plugin_loader_t *this, char *name, } } if (lib->settings->get_bool(lib->settings, "%s.dlopen_use_rtld_now", - lib->ns, FALSE)) + FALSE, lib->ns)) { flag = RTLD_NOW; } @@ -698,7 +698,6 @@ static bool load_dependencies(private_plugin_loader_t *this, int level) { registered_feature_t *registered, lookup; - int indent = level * 2; int i; /* first entry is provided feature, followed by dependencies */ @@ -741,6 +740,7 @@ static bool load_dependencies(private_plugin_loader_t *this, #ifndef USE_FUZZING char *name, *provide, *depend; + int indent = level * 2; name = provided->entry->plugin->get_name(provided->entry->plugin); provide = plugin_feature_get_string(&provided->feature[0]); @@ -828,7 +828,6 @@ static void load_provided(private_plugin_loader_t *this, provided_feature_t *provided, int level) { - int indent = level * 2; if (provided->loaded || provided->failed) { @@ -837,6 +836,7 @@ static void load_provided(private_plugin_loader_t *this, #ifndef USE_FUZZING char *name, *provide; + int indent = level * 2; name = provided->entry->plugin->get_name(provided->entry->plugin); provide = plugin_feature_get_string(provided->feature); diff --git a/src/libstrongswan/plugins/pubkey/Makefile.in b/src/libstrongswan/plugins/pubkey/Makefile.in index 02607958f..ff7501c00 100644 --- a/src/libstrongswan/plugins/pubkey/Makefile.in +++ b/src/libstrongswan/plugins/pubkey/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/pubkey/pubkey_cert.c b/src/libstrongswan/plugins/pubkey/pubkey_cert.c index 0631a6857..81dad65b7 100644 --- a/src/libstrongswan/plugins/pubkey/pubkey_cert.c +++ b/src/libstrongswan/plugins/pubkey/pubkey_cert.c @@ -137,13 +137,16 @@ METHOD(certificate_t, equals, bool, METHOD(certificate_t, issued_by, bool, private_pubkey_cert_t *this, certificate_t *issuer, - signature_scheme_t *scheme) + signature_params_t **scheme) { - if (scheme) + bool valid = equals(this, issuer); + if (valid && scheme) { - *scheme = SIGN_UNKNOWN; + INIT(*scheme, + .scheme = SIGN_UNKNOWN, + ); } - return equals(this, issuer); + return valid; } METHOD(certificate_t, get_public_key, public_key_t*, diff --git a/src/libstrongswan/plugins/random/Makefile.in b/src/libstrongswan/plugins/random/Makefile.in index 98702d0d3..3a22a6316 100644 --- a/src/libstrongswan/plugins/random/Makefile.in +++ b/src/libstrongswan/plugins/random/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/rc2/Makefile.in b/src/libstrongswan/plugins/rc2/Makefile.in index b874e9081..d37c9834d 100644 --- a/src/libstrongswan/plugins/rc2/Makefile.in +++ b/src/libstrongswan/plugins/rc2/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/rdrand/Makefile.in b/src/libstrongswan/plugins/rdrand/Makefile.in index 40b1d7644..371e34db8 100644 --- a/src/libstrongswan/plugins/rdrand/Makefile.in +++ b/src/libstrongswan/plugins/rdrand/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/revocation/Makefile.in b/src/libstrongswan/plugins/revocation/Makefile.in index 8254c1424..15e91b24a 100644 --- a/src/libstrongswan/plugins/revocation/Makefile.in +++ b/src/libstrongswan/plugins/revocation/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/sha1/Makefile.in b/src/libstrongswan/plugins/sha1/Makefile.in index 0c68798a9..ff0a30462 100644 --- a/src/libstrongswan/plugins/sha1/Makefile.in +++ b/src/libstrongswan/plugins/sha1/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/sha2/Makefile.in b/src/libstrongswan/plugins/sha2/Makefile.in index 109726b6a..81284e137 100644 --- a/src/libstrongswan/plugins/sha2/Makefile.in +++ b/src/libstrongswan/plugins/sha2/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/sha3/Makefile.in b/src/libstrongswan/plugins/sha3/Makefile.in index a1f79740b..3ca2f5e24 100644 --- a/src/libstrongswan/plugins/sha3/Makefile.in +++ b/src/libstrongswan/plugins/sha3/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/soup/Makefile.in b/src/libstrongswan/plugins/soup/Makefile.in index ceccab7f1..47af2c5fd 100644 --- a/src/libstrongswan/plugins/soup/Makefile.in +++ b/src/libstrongswan/plugins/soup/Makefile.in @@ -245,9 +245,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/sqlite/Makefile.in b/src/libstrongswan/plugins/sqlite/Makefile.in index 39d705622..f0649b52a 100644 --- a/src/libstrongswan/plugins/sqlite/Makefile.in +++ b/src/libstrongswan/plugins/sqlite/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/sshkey/Makefile.in b/src/libstrongswan/plugins/sshkey/Makefile.in index ded2bf8f1..ac644ec0b 100644 --- a/src/libstrongswan/plugins/sshkey/Makefile.in +++ b/src/libstrongswan/plugins/sshkey/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/test_vectors/Makefile.in b/src/libstrongswan/plugins/test_vectors/Makefile.in index b7332d4a7..45879e841 100644 --- a/src/libstrongswan/plugins/test_vectors/Makefile.in +++ b/src/libstrongswan/plugins/test_vectors/Makefile.in @@ -265,9 +265,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/unbound/Makefile.in b/src/libstrongswan/plugins/unbound/Makefile.in index 93159ff17..2a4788ee1 100644 --- a/src/libstrongswan/plugins/unbound/Makefile.in +++ b/src/libstrongswan/plugins/unbound/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/winhttp/Makefile.in b/src/libstrongswan/plugins/winhttp/Makefile.in index 91033262d..7cd680095 100644 --- a/src/libstrongswan/plugins/winhttp/Makefile.in +++ b/src/libstrongswan/plugins/winhttp/Makefile.in @@ -247,9 +247,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/x509/Makefile.in b/src/libstrongswan/plugins/x509/Makefile.in index 3596d1f85..0f54f8cf0 100644 --- a/src/libstrongswan/plugins/x509/Makefile.in +++ b/src/libstrongswan/plugins/x509/Makefile.in @@ -246,9 +246,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ diff --git a/src/libstrongswan/plugins/x509/x509_ac.c b/src/libstrongswan/plugins/x509/x509_ac.c index ba459288b..7a5a31af7 100644 --- a/src/libstrongswan/plugins/x509/x509_ac.c +++ b/src/libstrongswan/plugins/x509/x509_ac.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2002 Ueli Galizzi, Ariane Seiler * Copyright (C) 2003 Martin Berner, Lukas Suter * Copyright (C) 2002-2017 Andreas Steffen @@ -116,9 +117,9 @@ struct private_x509_ac_t { bool noRevAvail; /** - * Signature algorithm + * Signature scheme */ - int algorithm; + signature_params_t *scheme; /** * Signature @@ -425,7 +426,7 @@ static bool parse_certificate(private_x509_ac_t *this) int objectID; int type = OID_UNKNOWN; int extn_oid = OID_UNKNOWN; - int sig_alg = OID_UNKNOWN; + signature_params_t sig_alg = {}; bool success = FALSE; bool critical; @@ -476,7 +477,11 @@ static bool parse_certificate(private_x509_ac_t *this) } break; case AC_OBJ_SIG_ALG: - sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL); + if (!signature_params_parse(object, level, &sig_alg)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } break; case AC_OBJ_SERIAL_NUMBER: this->serialNumber = chunk_clone(object); @@ -550,12 +555,15 @@ static bool parse_certificate(private_x509_ac_t *this) break; } case AC_OBJ_ALGORITHM: - this->algorithm = asn1_parse_algorithmIdentifier(object, level, - NULL); - if (this->algorithm != sig_alg) + INIT(this->scheme); + if (!signature_params_parse(object, level, this->scheme)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } + if (!signature_params_equal(this->scheme, &sig_alg)) { DBG1(DBG_ASN, " signature algorithms do not agree"); - success = FALSE; goto end; } break; @@ -570,6 +578,7 @@ static bool parse_certificate(private_x509_ac_t *this) end: parser->destroy(parser); + signature_params_clear(&sig_alg); return success; } @@ -742,13 +751,13 @@ static chunk_t build_extensions(private_x509_ac_t *this) /** * build attributeCertificateInfo */ -static chunk_t build_attr_cert_info(private_x509_ac_t *this) +static chunk_t build_attr_cert_info(private_x509_ac_t *this, chunk_t sig_scheme) { - return asn1_wrap(ASN1_SEQUENCE, "cmmmmmmm", + return asn1_wrap(ASN1_SEQUENCE, "cmmcmmmm", ASN1_INTEGER_1, build_holder(this), build_v2_form(this), - asn1_algorithmIdentifier(OID_SHA1_WITH_RSA), + sig_scheme, asn1_simple_object(ASN1_INTEGER, this->serialNumber), build_attr_cert_validity(this), build_attributes(this), @@ -758,20 +767,39 @@ static chunk_t build_attr_cert_info(private_x509_ac_t *this) /** * build an X.509 attribute certificate */ -static bool build_ac(private_x509_ac_t *this) +static bool build_ac(private_x509_ac_t *this, hash_algorithm_t digest_alg) { - chunk_t signatureValue, attributeCertificateInfo; + chunk_t signatureValue, attributeCertificateInfo, sig_scheme; + private_key_t *key = this->signerKey; - attributeCertificateInfo = build_attr_cert_info(this); - if (!this->signerKey->sign(this->signerKey, SIGN_RSA_EMSA_PKCS1_SHA1, - attributeCertificateInfo, &signatureValue)) + if (!this->scheme) + { + INIT(this->scheme, + .scheme = signature_scheme_from_oid( + hasher_signature_algorithm_to_oid(digest_alg, + key->get_type(key))), + ); + } + if (this->scheme->scheme == SIGN_UNKNOWN) + { + return FALSE; + } + if (!signature_params_build(this->scheme, &sig_scheme)) + { + return FALSE; + } + + attributeCertificateInfo = build_attr_cert_info(this, sig_scheme); + if (!key->sign(key, this->scheme->scheme, this->scheme->params, + attributeCertificateInfo, &signatureValue)) { free(attributeCertificateInfo.ptr); + free(sig_scheme.ptr); return FALSE; } this->encoding = asn1_wrap(ASN1_SEQUENCE, "mmm", attributeCertificateInfo, - asn1_algorithmIdentifier(OID_SHA1_WITH_RSA), + sig_scheme, asn1_bitstring("m", signatureValue)); return TRUE; } @@ -886,10 +914,10 @@ METHOD(certificate_t, has_issuer, id_match_t, } METHOD(certificate_t, issued_by, bool, - private_x509_ac_t *this, certificate_t *issuer, signature_scheme_t *schemep) + private_x509_ac_t *this, certificate_t *issuer, + signature_params_t **scheme) { public_key_t *key; - signature_scheme_t scheme; bool valid; x509_t *x509 = (x509_t*)issuer; @@ -926,18 +954,16 @@ METHOD(certificate_t, issued_by, bool, } } - /* determine signature scheme */ - scheme = signature_scheme_from_oid(this->algorithm); - - if (scheme == SIGN_UNKNOWN || key == NULL) + if (!key) { return FALSE; } - valid = key->verify(key, scheme, this->certificateInfo, this->signature); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, + this->certificateInfo, this->signature); key->destroy(key); - if (valid && schemep) + if (valid && scheme) { - *schemep = scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -1020,6 +1046,7 @@ METHOD(certificate_t, destroy, void, DESTROY_IF(this->signerCert); DESTROY_IF(this->signerKey); this->groups->destroy_function(this->groups, (void*)group_destroy); + signature_params_destroy(this->scheme); free(this->serialNumber.ptr); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); @@ -1126,6 +1153,7 @@ static void add_groups_from_list(private_x509_ac_t *this, linked_list_t *list) */ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) { + hash_algorithm_t digest_alg = HASH_SHA1; private_x509_ac_t *ac; ac = create_empty(); @@ -1157,6 +1185,13 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) ac->signerKey = va_arg(args, private_key_t*); ac->signerKey->get_ref(ac->signerKey); continue; + case BUILD_SIGNATURE_SCHEME: + ac->scheme = va_arg(args, signature_params_t*); + ac->scheme = signature_params_clone(ac->scheme); + continue; + case BUILD_DIGEST_ALG: + digest_alg = va_arg(args, int); + continue; case BUILD_END: break; default: @@ -1170,7 +1205,7 @@ x509_ac_t *x509_ac_gen(certificate_type_t type, va_list args) ac->holderCert->get_type(ac->holderCert) == CERT_X509 && ac->signerCert->get_type(ac->signerCert) == CERT_X509) { - if (build_ac(ac)) + if (build_ac(ac, digest_alg)) { return &ac->public; } diff --git a/src/libstrongswan/plugins/x509/x509_cert.c b/src/libstrongswan/plugins/x509/x509_cert.c index 974e687f9..d1f9d9aac 100644 --- a/src/libstrongswan/plugins/x509/x509_cert.c +++ b/src/libstrongswan/plugins/x509/x509_cert.c @@ -4,7 +4,7 @@ * Copyright (C) 2002 Mario Strasser * Copyright (C) 2000-2017 Andreas Steffen * Copyright (C) 2006-2009 Martin Willi - * Copyright (C) 2008 Tobias Brunner + * Copyright (C) 2008-2017 Tobias Brunner * HSR Hochschule fuer Technik Rapperswil * * This program is free software; you can redistribute it and/or modify it @@ -197,9 +197,9 @@ struct private_x509_cert_t { x509_flag_t flags; /** - * Signature algorithm + * Signature scheme */ - int algorithm; + signature_params_t *scheme; /** * Signature @@ -241,16 +241,6 @@ static bool gn_to_string(identification_t *id, char **uri) } /** - * Destroy a CertificateDistributionPoint - */ -static void crl_uri_destroy(x509_cdp_t *this) -{ - free(this->uri); - DESTROY_IF(this->issuer); - free(this); -} - -/** * Destroy a CertificatePolicy */ static void cert_policy_destroy(x509_cert_policy_t *this) @@ -1385,7 +1375,7 @@ static bool parse_certificate(private_x509_cert_t *this) chunk_t object; int objectID; int extn_oid = OID_UNKNOWN; - int sig_alg = OID_UNKNOWN; + signature_params_t sig_alg = {}; bool success = FALSE; bool critical = FALSE; @@ -1416,7 +1406,11 @@ static bool parse_certificate(private_x509_cert_t *this) this->serialNumber = object; break; case X509_OBJ_SIG_ALG: - sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL); + if (!signature_params_parse(object, level, &sig_alg)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } break; case X509_OBJ_ISSUER: this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); @@ -1570,8 +1564,13 @@ static bool parse_certificate(private_x509_cert_t *this) break; } case X509_OBJ_ALGORITHM: - this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); - if (this->algorithm != sig_alg) + INIT(this->scheme); + if (!signature_params_parse(object, level, this->scheme)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } + if (!signature_params_equal(this->scheme, &sig_alg)) { DBG1(DBG_ASN, " signature algorithms do not agree"); goto end; @@ -1588,6 +1587,7 @@ static bool parse_certificate(private_x509_cert_t *this) end: parser->destroy(parser); + signature_params_clear(&sig_alg); if (success) { hasher_t *hasher; @@ -1687,10 +1687,9 @@ METHOD(certificate_t, has_issuer, id_match_t, METHOD(certificate_t, issued_by, bool, private_x509_cert_t *this, certificate_t *issuer, - signature_scheme_t *schemep) + signature_params_t **scheme) { public_key_t *key; - signature_scheme_t scheme; bool valid; x509_t *x509 = (x509_t*)issuer; @@ -1698,6 +1697,10 @@ METHOD(certificate_t, issued_by, bool, { if (this->flags & X509_SELF_SIGNED) { + if (scheme) + { + *scheme = signature_params_clone(this->scheme); + } return TRUE; } } @@ -1717,23 +1720,18 @@ METHOD(certificate_t, issued_by, bool, return FALSE; } - /* determine signature scheme */ - scheme = signature_scheme_from_oid(this->algorithm); - if (scheme == SIGN_UNKNOWN) - { - return FALSE; - } /* get the public key of the issuer */ key = issuer->get_public_key(issuer); if (!key) { return FALSE; } - valid = key->verify(key, scheme, this->tbsCertificate, this->signature); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, + this->tbsCertificate, this->signature); key->destroy(key); - if (valid && schemep) + if (valid && scheme) { - *schemep = scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -1920,7 +1918,8 @@ METHOD(certificate_t, destroy, void, { this->subjectAltNames->destroy_offset(this->subjectAltNames, offsetof(identification_t, destroy)); - this->crl_uris->destroy_function(this->crl_uris, (void*)crl_uri_destroy); + this->crl_uris->destroy_function(this->crl_uris, + (void*)x509_cdp_destroy); this->ocsp_uris->destroy_function(this->ocsp_uris, free); this->ipAddrBlocks->destroy_offset(this->ipAddrBlocks, offsetof(traffic_selector_t, destroy)); @@ -1932,6 +1931,7 @@ METHOD(certificate_t, destroy, void, (void*)cert_policy_destroy); this->policy_mappings->destroy_function(this->policy_mappings, (void*)policy_mapping_destroy); + signature_params_destroy(this->scheme); DESTROY_IF(this->issuer); DESTROY_IF(this->subject); DESTROY_IF(this->public_key); @@ -2187,10 +2187,9 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, chunk_t crlDistributionPoints = chunk_empty, authorityInfoAccess = chunk_empty; chunk_t policyConstraints = chunk_empty, inhibitAnyPolicy = chunk_empty; chunk_t ikeIntermediate = chunk_empty, msSmartcardLogon = chunk_empty; - chunk_t ipAddrBlocks = chunk_empty; + chunk_t ipAddrBlocks = chunk_empty, sig_scheme = chunk_empty; identification_t *issuer, *subject; chunk_t key_info; - signature_scheme_t scheme; hasher_t *hasher; enumerator_t *enumerator; char *uri; @@ -2223,18 +2222,28 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, cert->notAfter = cert->notBefore + 60 * 60 * 24 * 365; } - /* select signature scheme */ - cert->algorithm = hasher_signature_algorithm_to_oid(digest_alg, - sign_key->get_type(sign_key)); - if (cert->algorithm == OID_UNKNOWN) + /* select signature scheme, if not already specified */ + if (!cert->scheme) + { + INIT(cert->scheme, + .scheme = signature_scheme_from_oid( + hasher_signature_algorithm_to_oid(digest_alg, + sign_key->get_type(sign_key))), + ); + } + if (cert->scheme->scheme == SIGN_UNKNOWN) + { + return FALSE; + } + if (!signature_params_build(cert->scheme, &sig_scheme)) { return FALSE; } - scheme = signature_scheme_from_oid(cert->algorithm); if (!cert->public_key->get_encoding(cert->public_key, PUBKEY_SPKI_ASN1_DER, &key_info)) { + chunk_free(&sig_scheme); return FALSE; } @@ -2559,10 +2568,10 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, ipAddrBlocks)); } - cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmmcmcmm", + cert->tbsCertificate = asn1_wrap(ASN1_SEQUENCE, "mmccmcmm", asn1_simple_object(ASN1_CONTEXT_C_0, ASN1_INTEGER_2), asn1_integer("c", cert->serialNumber), - asn1_algorithmIdentifier(cert->algorithm), + sig_scheme, issuer->get_encoding(issuer), asn1_wrap(ASN1_SEQUENCE, "mm", asn1_from_time(&cert->notBefore, ASN1_UTCTIME), @@ -2570,12 +2579,14 @@ static bool generate(private_x509_cert_t *cert, certificate_t *sign_cert, subject->get_encoding(subject), key_info, extensions); - if (!sign_key->sign(sign_key, scheme, cert->tbsCertificate, &cert->signature)) + if (!sign_key->sign(sign_key, cert->scheme->scheme, cert->scheme->params, + cert->tbsCertificate, &cert->signature)) { + chunk_free(&sig_scheme); return FALSE; } cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm", cert->tbsCertificate, - asn1_algorithmIdentifier(cert->algorithm), + sig_scheme, asn1_bitstring("c", cert->signature)); hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1); @@ -2639,7 +2650,7 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) private_x509_cert_t *cert; certificate_t *sign_cert = NULL; private_key_t *sign_key = NULL; - hash_algorithm_t digest_alg = HASH_SHA1; + hash_algorithm_t digest_alg = HASH_SHA256; u_int constraint; cert = create_empty(); @@ -2831,6 +2842,10 @@ x509_cert_t *x509_cert_gen(certificate_type_t type, va_list args) case BUILD_SERIAL: cert->serialNumber = chunk_clone(va_arg(args, chunk_t)); continue; + case BUILD_SIGNATURE_SCHEME: + cert->scheme = va_arg(args, signature_params_t*); + cert->scheme = signature_params_clone(cert->scheme); + continue; case BUILD_DIGEST_ALG: digest_alg = va_arg(args, int); continue; diff --git a/src/libstrongswan/plugins/x509/x509_crl.c b/src/libstrongswan/plugins/x509/x509_crl.c index d8913ad73..699ac5a39 100644 --- a/src/libstrongswan/plugins/x509/x509_crl.c +++ b/src/libstrongswan/plugins/x509/x509_crl.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2014-2017 Tobias Brunner * Copyright (C) 2008-2009 Martin Willi * Copyright (C) 2017 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil @@ -121,9 +122,9 @@ struct private_x509_crl_t { chunk_t baseCrlNumber; /** - * Signature algorithm + * Signature scheme */ - int algorithm; + signature_params_t *scheme; /** * Signature @@ -225,7 +226,7 @@ static bool parse(private_x509_crl_t *this) chunk_t extnID = chunk_empty; chunk_t userCertificate = chunk_empty; int objectID; - int sig_alg = OID_UNKNOWN; + signature_params_t sig_alg = {}; bool success = FALSE; bool critical = FALSE; revoked_t *revoked = NULL; @@ -246,7 +247,11 @@ static bool parse(private_x509_crl_t *this) DBG2(DBG_ASN, " v%d", this->version); break; case CRL_OBJ_SIG_ALG: - sig_alg = asn1_parse_algorithmIdentifier(object, level, NULL); + if (!signature_params_parse(object, level, &sig_alg)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } break; case CRL_OBJ_ISSUER: this->issuer = identification_create_from_encoding(ID_DER_ASN1_DN, object); @@ -342,8 +347,13 @@ static bool parse(private_x509_crl_t *this) } case CRL_OBJ_ALGORITHM: { - this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); - if (this->algorithm != sig_alg) + INIT(this->scheme); + if (!signature_params_parse(object, level, this->scheme)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } + if (!signature_params_equal(this->scheme, &sig_alg)) { DBG1(DBG_ASN, " signature algorithms do not agree"); goto end; @@ -361,6 +371,7 @@ static bool parse(private_x509_crl_t *this) end: parser->destroy(parser); + signature_params_clear(&sig_alg); return success; } @@ -457,10 +468,10 @@ METHOD(certificate_t, has_issuer, id_match_t, } METHOD(certificate_t, issued_by, bool, - private_x509_crl_t *this, certificate_t *issuer, signature_scheme_t *schemep) + private_x509_crl_t *this, certificate_t *issuer, + signature_params_t **scheme) { public_key_t *key; - signature_scheme_t scheme; bool valid; x509_t *x509 = (x509_t*)issuer; chunk_t keyid = chunk_empty; @@ -492,21 +503,17 @@ METHOD(certificate_t, issued_by, bool, } } - scheme = signature_scheme_from_oid(this->algorithm); - if (scheme == SIGN_UNKNOWN) - { - return FALSE; - } key = issuer->get_public_key(issuer); if (!key) { return FALSE; } - valid = key->verify(key, scheme, this->tbsCertList, this->signature); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, + this->tbsCertList, this->signature); key->destroy(key); - if (valid && schemep) + if (valid && scheme) { - *schemep = scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -585,23 +592,15 @@ static void revoked_destroy(revoked_t *revoked) free(revoked); } -/** - * Destroy a CDP entry - */ -static void cdp_destroy(x509_cdp_t *this) -{ - free(this->uri); - DESTROY_IF(this->issuer); - free(this); -} - METHOD(certificate_t, destroy, void, private_x509_crl_t *this) { if (ref_put(&this->ref)) { this->revoked->destroy_function(this->revoked, (void*)revoked_destroy); - this->crl_uris->destroy_function(this->crl_uris, (void*)cdp_destroy); + this->crl_uris->destroy_function(this->crl_uris, + (void*)x509_cdp_destroy); + signature_params_destroy(this->scheme); DESTROY_IF(this->issuer); free(this->authKeyIdentifier.ptr); free(this->encoding.ptr); @@ -718,6 +717,7 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, { chunk_t extensions = chunk_empty, certList = chunk_empty, serial; chunk_t crlDistributionPoints = chunk_empty, baseCrlNumber = chunk_empty; + chunk_t sig_scheme = chunk_empty; enumerator_t *enumerator; crl_reason_t reason; time_t date; @@ -730,10 +730,20 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, this->authKeyIdentifier = chunk_clone(x509->get_subjectKeyIdentifier(x509)); - /* select signature scheme */ - this->algorithm = hasher_signature_algorithm_to_oid(digest_alg, - key->get_type(key)); - if (this->algorithm == OID_UNKNOWN) + /* select signature scheme, if not already specified */ + if (!this->scheme) + { + INIT(this->scheme, + .scheme = signature_scheme_from_oid( + hasher_signature_algorithm_to_oid(digest_alg, + key->get_type(key))), + ); + } + if (this->scheme->scheme == SIGN_UNKNOWN) + { + return FALSE; + } + if (!signature_params_build(this->scheme, &sig_scheme)) { return FALSE; } @@ -787,23 +797,24 @@ static bool generate(private_x509_crl_t *this, certificate_t *cert, asn1_integer("c", this->crlNumber))), crlDistributionPoints, baseCrlNumber)); - this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cmcmmmm", + this->tbsCertList = asn1_wrap(ASN1_SEQUENCE, "cccmmmm", ASN1_INTEGER_1, - asn1_algorithmIdentifier(this->algorithm), + sig_scheme, this->issuer->get_encoding(this->issuer), asn1_from_time(&this->thisUpdate, ASN1_UTCTIME), asn1_from_time(&this->nextUpdate, ASN1_UTCTIME), asn1_wrap(ASN1_SEQUENCE, "m", certList), extensions); - if (!key->sign(key, signature_scheme_from_oid(this->algorithm), + if (!key->sign(key, this->scheme->scheme, this->scheme->params, this->tbsCertList, &this->signature)) { + chunk_free(&sig_scheme); return FALSE; } this->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm", this->tbsCertList, - asn1_algorithmIdentifier(this->algorithm), + sig_scheme, asn1_bitstring("c", this->signature)); return TRUE; } @@ -842,6 +853,10 @@ x509_crl_t *x509_crl_gen(certificate_type_t type, va_list args) crl->crlNumber = va_arg(args, chunk_t); crl->crlNumber = chunk_clone(crl->crlNumber); continue; + case BUILD_SIGNATURE_SCHEME: + crl->scheme = va_arg(args, signature_params_t*); + crl->scheme = signature_params_clone(crl->scheme); + continue; case BUILD_DIGEST_ALG: digest_alg = va_arg(args, int); continue; diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_request.c b/src/libstrongswan/plugins/x509/x509_ocsp_request.c index aef76af32..de22ab6be 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_request.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_request.c @@ -276,7 +276,7 @@ static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this, return chunk_empty; } - if (!this->key->sign(this->key, scheme, tbsRequest, &signature)) + if (!this->key->sign(this->key, scheme, NULL, tbsRequest, &signature)) { DBG1(DBG_LIB, "creating OCSP signature failed, skipped"); return chunk_empty; @@ -372,7 +372,7 @@ METHOD(certificate_t, has_issuer, id_match_t, METHOD(certificate_t, issued_by, bool, private_x509_ocsp_request_t *this, certificate_t *issuer, - signature_scheme_t *scheme) + signature_params_t **scheme) { DBG1(DBG_LIB, "OCSP request validation not implemented!"); return FALSE; diff --git a/src/libstrongswan/plugins/x509/x509_ocsp_response.c b/src/libstrongswan/plugins/x509/x509_ocsp_response.c index 140e9bfa9..aa4999cbd 100644 --- a/src/libstrongswan/plugins/x509/x509_ocsp_response.c +++ b/src/libstrongswan/plugins/x509/x509_ocsp_response.c @@ -1,4 +1,5 @@ -/** +/* + * Copyright (C) 2017 Tobias Brunner * Copyright (C) 2008-2009 Martin Willi * Copyright (C) 2007-2015 Andreas Steffen * HSR Hochschule fuer Technik Rapperswil @@ -63,9 +64,9 @@ struct private_x509_ocsp_response_t { chunk_t tbsResponseData; /** - * signature algorithm (OID) + * signature scheme */ - int signatureAlgorithm; + signature_params_t *scheme; /** * signature @@ -576,8 +577,13 @@ static bool parse_basicOCSPResponse(private_x509_ocsp_response_t *this, } break; case BASIC_RESPONSE_ALGORITHM: - this->signatureAlgorithm = asn1_parse_algorithmIdentifier(object, - parser->get_level(parser)+1, NULL); + INIT(this->scheme); + if (!signature_params_parse(object, parser->get_level(parser)+1, + this->scheme)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } break; case BASIC_RESPONSE_SIGNATURE: this->signature = chunk_skip(object, 1); @@ -703,10 +709,9 @@ METHOD(certificate_t, has_issuer, id_match_t, METHOD(certificate_t, issued_by, bool, private_x509_ocsp_response_t *this, certificate_t *issuer, - signature_scheme_t *schemep) + signature_params_t **scheme) { public_key_t *key; - signature_scheme_t scheme; bool valid; x509_t *x509 = (x509_t*)issuer; @@ -743,21 +748,17 @@ METHOD(certificate_t, issued_by, bool, return FALSE; } - /* get the public key of the issuer */ key = issuer->get_public_key(issuer); - - /* determine signature scheme */ - scheme = signature_scheme_from_oid(this->signatureAlgorithm); - - if (scheme == SIGN_UNKNOWN || key == NULL) + if (!key) { return FALSE; } - valid = key->verify(key, scheme, this->tbsResponseData, this->signature); + valid = key->verify(key, this->scheme->scheme, this->scheme->params, + this->tbsResponseData, this->signature); key->destroy(key); - if (valid && schemep) + if (valid && scheme) { - *schemep = scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -839,6 +840,7 @@ METHOD(certificate_t, destroy, void, { this->certs->destroy_offset(this->certs, offsetof(certificate_t, destroy)); this->responses->destroy_function(this->responses, free); + signature_params_destroy(this->scheme); DESTROY_IF(this->responderId); free(this->encoding.ptr); free(this); @@ -879,7 +881,6 @@ static x509_ocsp_response_t *load(chunk_t blob) .producedAt = UNDEFINED_TIME, .usableUntil = UNDEFINED_TIME, .responses = linked_list_create(), - .signatureAlgorithm = OID_UNKNOWN, .certs = linked_list_create(), ); diff --git a/src/libstrongswan/plugins/x509/x509_pkcs10.c b/src/libstrongswan/plugins/x509/x509_pkcs10.c index e39e24bff..587fbd5d6 100644 --- a/src/libstrongswan/plugins/x509/x509_pkcs10.c +++ b/src/libstrongswan/plugins/x509/x509_pkcs10.c @@ -72,9 +72,9 @@ struct private_x509_pkcs10_t { chunk_t challengePassword; /** - * Signature algorithm + * Signature scheme */ - int algorithm; + signature_params_t *scheme; /** * Signature @@ -124,10 +124,9 @@ METHOD(certificate_t, has_subject, id_match_t, METHOD(certificate_t, issued_by, bool, private_x509_pkcs10_t *this, certificate_t *issuer, - signature_scheme_t *schemep) + signature_params_t **scheme) { public_key_t *key; - signature_scheme_t scheme; bool valid; if (&this->public.interface.interface != issuer) @@ -136,27 +135,22 @@ METHOD(certificate_t, issued_by, bool, } if (this->self_signed) { - return TRUE; + valid = TRUE; } - - /* determine signature scheme */ - scheme = signature_scheme_from_oid(this->algorithm); - if (scheme == SIGN_UNKNOWN) + else { - return FALSE; - } - - /* get the public key contained in the certificate request */ - key = this->public_key; - if (!key) - { - return FALSE; + /* get the public key contained in the certificate request */ + key = this->public_key; + if (!key) + { + return FALSE; + } + valid = key->verify(key, this->scheme->scheme, this->scheme->params, + this->certificationRequestInfo, this->signature); } - valid = key->verify(key, scheme, this->certificationRequestInfo, - this->signature); - if (valid && schemep) + if (valid && scheme) { - *schemep = scheme; + *scheme = signature_params_clone(this->scheme); } return valid; } @@ -410,7 +404,7 @@ static bool parse_certificate_request(private_x509_pkcs10_t *this) case PKCS10_SUBJECT_PUBLIC_KEY_INFO: this->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY, KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END); - if (this->public_key == NULL) + if (!this->public_key) { goto end; } @@ -438,7 +432,12 @@ static bool parse_certificate_request(private_x509_pkcs10_t *this) } break; case PKCS10_ALGORITHM: - this->algorithm = asn1_parse_algorithmIdentifier(object, level, NULL); + INIT(this->scheme); + if (!signature_params_parse(object, level, this->scheme)) + { + DBG1(DBG_ASN, " unable to parse signature algorithm"); + goto end; + } break; case PKCS10_SIGNATURE: this->signature = chunk_skip(object, 1); @@ -474,6 +473,7 @@ METHOD(certificate_t, destroy, void, { this->subjectAltNames->destroy_offset(this->subjectAltNames, offsetof(identification_t, destroy)); + signature_params_destroy(this->scheme); DESTROY_IF(this->subject); DESTROY_IF(this->public_key); chunk_free(&this->encoding); @@ -530,25 +530,34 @@ static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key, { chunk_t key_info, subjectAltNames, attributes; chunk_t extensionRequest = chunk_empty; - chunk_t challengePassword = chunk_empty; - signature_scheme_t scheme; + chunk_t challengePassword = chunk_empty, sig_scheme = chunk_empty; identification_t *subject; subject = cert->subject; cert->public_key = sign_key->get_public_key(sign_key); - /* select signature scheme */ - cert->algorithm = hasher_signature_algorithm_to_oid(digest_alg, - sign_key->get_type(sign_key)); - if (cert->algorithm == OID_UNKNOWN) + /* select signature scheme, if not already specified */ + if (!cert->scheme) + { + INIT(cert->scheme, + .scheme = signature_scheme_from_oid( + hasher_signature_algorithm_to_oid(digest_alg, + sign_key->get_type(sign_key))), + ); + } + if (cert->scheme->scheme == SIGN_UNKNOWN) + { + return FALSE; + } + if (!signature_params_build(cert->scheme, &sig_scheme)) { return FALSE; } - scheme = signature_scheme_from_oid(cert->algorithm); if (!cert->public_key->get_encoding(cert->public_key, PUBKEY_SPKI_ASN1_DER, &key_info)) { + chunk_free(&sig_scheme); return FALSE; } @@ -584,15 +593,16 @@ static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key, key_info, attributes); - if (!sign_key->sign(sign_key, scheme, cert->certificationRequestInfo, - &cert->signature)) + if (!sign_key->sign(sign_key, cert->scheme->scheme, cert->scheme->params, + cert->certificationRequestInfo, &cert->signature)) { + chunk_free(&sig_scheme); return FALSE; } cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm", cert->certificationRequestInfo, - asn1_algorithmIdentifier(cert->algorithm), + sig_scheme, asn1_bitstring("c", cert->signature)); return TRUE; } @@ -674,6 +684,10 @@ x509_pkcs10_t *x509_pkcs10_gen(certificate_type_t type, va_list args) case BUILD_CHALLENGE_PWD: cert->challengePassword = chunk_clone(va_arg(args, chunk_t)); continue; + case BUILD_SIGNATURE_SCHEME: + cert->scheme = va_arg(args, signature_params_t*); + cert->scheme = signature_params_clone(cert->scheme); + continue; case BUILD_DIGEST_ALG: digest_alg = va_arg(args, int); continue; diff --git a/src/libstrongswan/plugins/xcbc/Makefile.in b/src/libstrongswan/plugins/xcbc/Makefile.in index d5d47694f..3a39037bc 100644 --- a/src/libstrongswan/plugins/xcbc/Makefile.in +++ b/src/libstrongswan/plugins/xcbc/Makefile.in @@ -244,9 +244,11 @@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ +FUZZING_LDFLAGS = @FUZZING_LDFLAGS@ GEM = @GEM@ GENHTML = @GENHTML@ GPERF = @GPERF@ +GPERF_LEN_TYPE = @GPERF_LEN_TYPE@ GPRBUILD = @GPRBUILD@ GREP = @GREP@ INSTALL = @INSTALL@ |