diff options
Diffstat (limited to 'debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch')
-rw-r--r-- | debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch | 306 |
1 files changed, 306 insertions, 0 deletions
diff --git a/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch b/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch new file mode 100644 index 0000000..5e9080f --- /dev/null +++ b/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch @@ -0,0 +1,306 @@ +From 48bb9d0cf5de06cfb483aea66ff5a2c7aa3eb46f Mon Sep 17 00:00:00 2001 +From: Daiki Ueno <ueno@gnu.org> +Date: Tue, 20 Sep 2022 16:06:13 +0900 +Subject: [PATCH 08/29] fips: fix checking on hash algorithm used in ECDSA + +Previously we checked against the "preferred" hash algorithm based on +the curve, instead of the one actually used. + +Signed-off-by: Daiki Ueno <ueno@gnu.org> +--- + lib/crypto-backend.h | 12 ++++--- + lib/nettle/pk.c | 33 ++++++++--------- + lib/pubkey.c | 5 ++- + tests/fips-test.c | 86 ++++++++++++++++++++++++++++++++++++++++++-- + 4 files changed, 111 insertions(+), 25 deletions(-) + +--- a/lib/crypto-backend.h ++++ b/lib/crypto-backend.h +@@ -245,15 +245,17 @@ typedef enum { + GNUTLS_PK_FLAG_PROVABLE = 1, + GNUTLS_PK_FLAG_REPRODUCIBLE = 2, + GNUTLS_PK_FLAG_RSA_PSS_FIXED_SALT_LENGTH = 4 + } gnutls_pk_flag_t; + +-#define FIX_SIGN_PARAMS(params, flags, dig) do { \ +- if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) { \ +- (params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE; \ +- (params).dsa_dig = (dig); \ +- } \ ++#define FIX_SIGN_PARAMS(params, flags, dig) do { \ ++ if ((flags) & GNUTLS_PRIVKEY_FLAG_REPRODUCIBLE) { \ ++ (params).flags |= GNUTLS_PK_FLAG_REPRODUCIBLE; \ ++ } \ ++ if ((params).pk == GNUTLS_PK_DSA || (params).pk == GNUTLS_PK_ECDSA) { \ ++ (params).dsa_dig = (dig); \ ++ } \ + } while (0) + + void gnutls_pk_params_release(gnutls_pk_params_st * p); + void gnutls_pk_params_clear(gnutls_pk_params_st * p); + void gnutls_pk_params_init(gnutls_pk_params_st * p); +--- a/lib/nettle/pk.c ++++ b/lib/nettle/pk.c +@@ -1102,29 +1102,29 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm + dsa_signature_init(&sig); + + me = _gnutls_dsa_q_to_hash(pk_params, + &hash_len); + ++ if (hash_len > vdata->size) { ++ gnutls_assert(); ++ _gnutls_debug_log ++ ("Security level of algorithm requires hash %s(%d) or better\n", ++ _gnutls_mac_get_name(me), hash_len); ++ hash_len = vdata->size; ++ } ++ + /* Only SHA-2 is allowed in FIPS 140-3 */ +- switch (me->id) { ++ switch (DIG_TO_MAC(sign_params->dsa_dig)) { + case GNUTLS_MAC_SHA256: + case GNUTLS_MAC_SHA384: + case GNUTLS_MAC_SHA512: + case GNUTLS_MAC_SHA224: + break; + default: + not_approved = true; + } + +- if (hash_len > vdata->size) { +- gnutls_assert(); +- _gnutls_debug_log +- ("Security level of algorithm requires hash %s(%d) or better\n", +- _gnutls_mac_get_name(me), hash_len); +- hash_len = vdata->size; +- } +- + mpz_init(k); + if (_gnutls_get_lib_state() == LIB_STATE_SELFTEST || + (sign_params->flags & GNUTLS_PK_FLAG_REPRODUCIBLE)) { + ret = _gnutls_ecdsa_compute_k(k, + curve_id, +@@ -1543,11 +1543,10 @@ _wrap_nettle_pk_verify(gnutls_pk_algorit + { + struct ecc_point pub; + struct dsa_signature sig; + int curve_id = pk_params->curve; + const struct ecc_curve *curve; +- const mac_entry_st *me; + + curve = get_supported_nist_curve(curve_id); + if (curve == NULL) { + ret = gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE); + goto cleanup; +@@ -1569,28 +1568,28 @@ _wrap_nettle_pk_verify(gnutls_pk_algorit + } + + memcpy(sig.r, tmp[0], SIZEOF_MPZT); + memcpy(sig.s, tmp[1], SIZEOF_MPZT); + +- me = _gnutls_dsa_q_to_hash(pk_params, &hash_len); ++ (void)_gnutls_dsa_q_to_hash(pk_params, &hash_len); ++ ++ if (hash_len > vdata->size) ++ hash_len = vdata->size; + + /* SHA-1 is allowed for SigVer in FIPS 140-3 in legacy + * mode */ +- switch (me->id) { ++ switch (DIG_TO_MAC(sign_params->dsa_dig)) { + case GNUTLS_MAC_SHA1: + case GNUTLS_MAC_SHA256: + case GNUTLS_MAC_SHA384: + case GNUTLS_MAC_SHA512: + case GNUTLS_MAC_SHA224: + break; + default: + not_approved = true; + } + +- if (hash_len > vdata->size) +- hash_len = vdata->size; +- + ret = + ecdsa_verify(&pub, hash_len, vdata->data, + &sig); + if (ret == 0) { + gnutls_assert(); +@@ -2388,12 +2387,14 @@ static int pct_test(gnutls_pk_algorithm_ + + memcpy(&spki, ¶ms->spki, sizeof(spki)); + + if (algo == GNUTLS_PK_DSA || algo == GNUTLS_PK_EC) { + unsigned hash_len; ++ const mac_entry_st *me; + +- _gnutls_dsa_q_to_hash(params, &hash_len); ++ me = _gnutls_dsa_q_to_hash(params, &hash_len); ++ spki.dsa_dig = MAC_TO_DIG(me->id); + gen_data = gnutls_malloc(hash_len); + gnutls_rnd(GNUTLS_RND_NONCE, gen_data, hash_len); + + ddata.data = (void*)gen_data; + ddata.size = hash_len; +--- a/lib/pubkey.c ++++ b/lib/pubkey.c +@@ -1983,11 +1983,11 @@ gnutls_pubkey_import_dsa_raw(gnutls_pubk + /* Updates the gnutls_x509_spki_st parameters based on the signature + * information, and reports any incompatibilities between the existing + * parameters (if any) with the signature algorithm */ + static + int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_entry_st *se, +- const mac_entry_st *me, gnutls_x509_spki_st *params) ++ const mac_entry_st *me, gnutls_x509_spki_st *params) + { + unsigned bits; + + if (se->pk != key_params->algo) { + if (!sign_supports_priv_pk_algorithm(se, key_params->algo)) { +@@ -2016,10 +2016,13 @@ int fixup_spki_params(const gnutls_pk_pa + params->salt_size = ret; + } + + if (params->rsa_pss_dig != se->hash) + return gnutls_assert_val(GNUTLS_E_CONSTRAINT_ERROR); ++ } else if (params->pk == GNUTLS_PK_DSA || ++ params->pk == GNUTLS_PK_ECDSA) { ++ params->dsa_dig = se->hash; + } + + return 0; + } + +--- a/tests/fips-test.c ++++ b/tests/fips-test.c +@@ -78,12 +78,26 @@ static const uint8_t rsa2342_sha1_sig_da + static const gnutls_datum_t rsa2342_sha1_sig = { + .data = (unsigned char *)rsa2342_sha1_sig_data, + .size = sizeof(rsa2342_sha1_sig_data), + }; + ++static const uint8_t ecc256_sha1_sig_data[] = { ++ 0x30, 0x45, 0x02, 0x21, 0x00, 0x9a, 0x28, 0xc9, 0xbf, 0xc8, 0x70, 0x4f, ++ 0x27, 0x2d, 0xe1, 0x66, 0xc4, 0xa5, 0xc6, 0xf2, 0xdc, 0x33, 0xb9, 0x41, ++ 0xdf, 0x78, 0x98, 0x8a, 0x22, 0x4d, 0x29, 0x37, 0xa0, 0x0f, 0x6f, 0xd4, ++ 0xed, 0x02, 0x20, 0x0b, 0x15, 0xca, 0x30, 0x09, 0x2d, 0x55, 0x44, 0xb4, ++ 0x1d, 0x3f, 0x48, 0x7a, 0xc3, 0xd1, 0x2a, 0xc1, 0x0e, 0x47, 0xfa, 0xe6, ++ 0xe9, 0x0f, 0x03, 0xe2, 0x01, 0x4e, 0xe4, 0x73, 0x37, 0xa7, 0x90, ++}; ++ ++static const gnutls_datum_t ecc256_sha1_sig = { ++ .data = (unsigned char *)ecc256_sha1_sig_data, ++ .size = sizeof(ecc256_sha1_sig_data), ++}; ++ + static void +-rsa_import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey, ++import_keypair(gnutls_privkey_t *privkey, gnutls_pubkey_t *pubkey, + const char *filename) + { + const char *srcdir; + char path[256]; + gnutls_datum_t tmp; +@@ -422,11 +436,11 @@ void doit(void) + gnutls_x509_privkey_deinit(xprivkey); + FIPS_POP_CONTEXT(ERROR); + + /* Import 2432-bit RSA key; not a security function */ + FIPS_PUSH_CONTEXT(); +- rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem"); ++ import_keypair(&privkey, &pubkey, "rsa-2432.pem"); + FIPS_POP_CONTEXT(INITIAL); + + /* Create a signature with 2432-bit RSA and SHA256; approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, +@@ -468,11 +482,11 @@ void doit(void) + gnutls_pubkey_deinit(pubkey); + gnutls_privkey_deinit(privkey); + + /* Import 512-bit RSA key; not a security function */ + FIPS_PUSH_CONTEXT(); +- rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem"); ++ import_keypair(&privkey, &pubkey, "rsa-512.pem"); + FIPS_POP_CONTEXT(INITIAL); + + /* Create a signature with 512-bit RSA and SHA256; not approved */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, +@@ -491,10 +505,76 @@ void doit(void) + } + FIPS_POP_CONTEXT(NOT_APPROVED); + gnutls_free(signature.data); + gnutls_pubkey_deinit(pubkey); + gnutls_privkey_deinit(privkey); ++ ++ /* Import ECDSA key; not a security function */ ++ FIPS_PUSH_CONTEXT(); ++ import_keypair(&privkey, &pubkey, "ecc256.pem"); ++ FIPS_POP_CONTEXT(INITIAL); ++ ++ /* Create a signature with ECDSA and SHA256; approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA256, 0, ++ &data, &signature); ++ if (ret < 0) { ++ fail("gnutls_privkey_sign_data2 failed\n"); ++ } ++ FIPS_POP_CONTEXT(APPROVED); ++ ++ /* Verify a signature with ECDSA and SHA256; approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA256, 0, ++ &data, &signature); ++ if (ret < 0) { ++ fail("gnutls_pubkey_verify_data2 failed\n"); ++ } ++ FIPS_POP_CONTEXT(APPROVED); ++ gnutls_free(signature.data); ++ ++ /* Create a signature with ECDSA and SHA256 (old API); approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA256, 0, ++ &data, &signature); ++ if (ret < 0) { ++ fail("gnutls_privkey_sign_data failed\n"); ++ } ++ FIPS_POP_CONTEXT(APPROVED); ++ gnutls_free(signature.data); ++ ++ /* Create a signature with ECDSA and SHA-1; not approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_privkey_sign_data2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0, ++ &data, &signature); ++ if (ret < 0) { ++ fail("gnutls_privkey_sign_data2 failed\n"); ++ } ++ FIPS_POP_CONTEXT(NOT_APPROVED); ++ ++ /* Verify a signature created with ECDSA and SHA-1; approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_ECDSA_SHA1, ++ GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, &data, ++ &ecc256_sha1_sig); ++ if (ret < 0) { ++ fail("gnutls_pubkey_verify_data2 failed\n"); ++ } ++ FIPS_POP_CONTEXT(APPROVED); ++ gnutls_free(signature.data); ++ ++ /* Create a signature with ECDSA and SHA-1 (old API); not approved */ ++ FIPS_PUSH_CONTEXT(); ++ ret = gnutls_privkey_sign_data(privkey, GNUTLS_DIG_SHA1, 0, ++ &data, &signature); ++ if (ret < 0) { ++ fail("gnutls_privkey_sign_data failed\n"); ++ } ++ FIPS_POP_CONTEXT(NOT_APPROVED); ++ gnutls_free(signature.data); ++ gnutls_pubkey_deinit(pubkey); ++ gnutls_privkey_deinit(privkey); + + /* Test RND functions */ + FIPS_PUSH_CONTEXT(); + ret = gnutls_rnd(GNUTLS_RND_RANDOM, key16, sizeof(key16)); + if (ret < 0) { |