summaryrefslogtreecommitdiffstats
path: root/debian/patches/53-fips-fix-checking-on-hash-algorithm-used-in-ECDSA.patch
diff options
context:
space:
mode:
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.patch306
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, &params->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) {