import gnutls-3.7.6-18.el9

This commit is contained in:
CentOS Sources 2023-03-28 09:01:25 +00:00 committed by Stepan Oksanichenko
parent c046ee914f
commit a80d0f7f8e
15 changed files with 3589 additions and 68 deletions

View File

@ -0,0 +1,331 @@
From 26b2caef673aba8bfd10db3b1b8117f941c18e58 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Fri, 21 Oct 2022 15:48:39 +0900
Subject: [PATCH] cipher: add restriction on CCM tag length under FIPS mode
This change prohibits any use of tag length other than 4, 6, 8, 10,
12, 14, and 16 bytes in CCM used under FIPS mode, in accordance with
SP800-38C A.1. While use of tag lengths smaller than 8 bytes is not
recommended, we simply allow 4 and 6 bytes tags for now.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/accelerated/aarch64/aes-ccm-aarch64.c | 39 ++++++++++
lib/accelerated/x86/aes-ccm-x86-aesni.c | 39 ++++++++++
lib/nettle/cipher.c | 55 ++++++++++++++
tests/fips-test.c | 87 ++++++++++++++++++++++-
4 files changed, 218 insertions(+), 2 deletions(-)
diff --git a/lib/accelerated/aarch64/aes-ccm-aarch64.c b/lib/accelerated/aarch64/aes-ccm-aarch64.c
index a2ba259e99..b415d4ddfb 100644
--- a/lib/accelerated/aarch64/aes-ccm-aarch64.c
+++ b/lib/accelerated/aarch64/aes-ccm-aarch64.c
@@ -36,6 +36,7 @@
#include <byteswap.h>
#include <nettle/ccm.h>
#include <aes-aarch64.h>
+#include <fips.h>
typedef struct ccm_aarch64_aes_ctx {
AES_KEY key;
@@ -103,6 +104,25 @@ aes_ccm_aead_encrypt(void *_ctx,
if (unlikely(encr_size < plain_size + tag_size))
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ /* SP800-38C A.1 says Tlen must be a multiple of 16 between 32
+ * and 128.
+ */
+ switch (tag_size) {
+ case 4: case 6:
+ /* SP800-38C B.2 says Tlen smaller than 64 should not be used
+ * under sufficient restriction. We simply allow those for now.
+ */
+ FALLTHROUGH;
+ case 8: case 10: case 12: case 14: case 16:
+ break;
+ default:
+ if (_gnutls_fips_mode_enabled()) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ break;
+ }
+
ccm_encrypt_message(&ctx->key, aarch64_aes_encrypt,
nonce_size, nonce,
auth_size, auth,
@@ -129,6 +149,25 @@ aes_ccm_aead_decrypt(void *_ctx,
if (unlikely(plain_size < encr_size - tag_size))
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ /* SP800-38C A.1 says Tlen must be a multiple of 16 between 32
+ * and 128.
+ */
+ switch (tag_size) {
+ case 4: case 6:
+ /* SP800-38C B.2 says Tlen smaller than 64 should not be used
+ * under sufficient restriction. We simply allow those for now.
+ */
+ FALLTHROUGH;
+ case 8: case 10: case 12: case 14: case 16:
+ break;
+ default:
+ if (_gnutls_fips_mode_enabled()) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ break;
+ }
+
ret = ccm_decrypt_message(&ctx->key, aarch64_aes_encrypt,
nonce_size, nonce,
auth_size, auth,
diff --git a/lib/accelerated/x86/aes-ccm-x86-aesni.c b/lib/accelerated/x86/aes-ccm-x86-aesni.c
index 701c0f992a..9ebbdd7b2a 100644
--- a/lib/accelerated/x86/aes-ccm-x86-aesni.c
+++ b/lib/accelerated/x86/aes-ccm-x86-aesni.c
@@ -37,6 +37,7 @@
#include <byteswap.h>
#include <nettle/ccm.h>
#include <aes-x86.h>
+#include <fips.h>
typedef struct ccm_x86_aes_ctx {
AES_KEY key;
@@ -95,6 +96,25 @@ aes_ccm_aead_encrypt(void *_ctx,
if (unlikely(encr_size < plain_size + tag_size))
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ /* SP800-38C A.1 says Tlen must be a multiple of 16 between 32
+ * and 128.
+ */
+ switch (tag_size) {
+ case 4: case 6:
+ /* SP800-38C B.2 says Tlen smaller than 64 should not be used
+ * under sufficient restriction. We simply allow those for now.
+ */
+ FALLTHROUGH;
+ case 8: case 10: case 12: case 14: case 16:
+ break;
+ default:
+ if (_gnutls_fips_mode_enabled()) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ break;
+ }
+
ccm_encrypt_message(&ctx->key, x86_aes_encrypt,
nonce_size, nonce,
auth_size, auth,
@@ -121,6 +141,25 @@ aes_ccm_aead_decrypt(void *_ctx,
if (unlikely(plain_size < encr_size - tag_size))
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ /* SP800-38C A.1 says Tlen must be a multiple of 16 between 32
+ * and 128.
+ */
+ switch (tag_size) {
+ case 4: case 6:
+ /* SP800-38C B.2 says Tlen smaller than 64 should not be used
+ * under sufficient restriction. We simply allow those for now.
+ */
+ FALLTHROUGH;
+ case 8: case 10: case 12: case 14: case 16:
+ break;
+ default:
+ if (_gnutls_fips_mode_enabled()) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ break;
+ }
+
ret = ccm_decrypt_message(&ctx->key, x86_aes_encrypt,
nonce_size, nonce,
auth_size, auth,
diff --git a/lib/nettle/cipher.c b/lib/nettle/cipher.c
index 9c2ce19e7e..8c23d11252 100644
--- a/lib/nettle/cipher.c
+++ b/lib/nettle/cipher.c
@@ -1253,6 +1253,34 @@ wrap_nettle_cipher_aead_encrypt(void *_ctx,
ctx->cipher->tag(ctx->ctx_ptr, tag_size, ((uint8_t*)encr) + plain_size);
} else {
/* CCM-style cipher */
+
+ switch (ctx->cipher->algo) {
+ case GNUTLS_CIPHER_AES_128_CCM:
+ case GNUTLS_CIPHER_AES_256_CCM:
+ /* SP800-38C A.1 says Tlen must be a multiple of 16
+ * between 32 and 128.
+ */
+ switch (tag_size) {
+ case 4: case 6:
+ /* SP800-38C B.2 says Tlen smaller than 64
+ * should not be used under sufficient
+ * restriction. We simply allow those for now.
+ */
+ FALLTHROUGH;
+ case 8: case 10: case 12: case 14: case 16:
+ break;
+ default:
+ if (_gnutls_fips_mode_enabled()) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
ctx->cipher->aead_encrypt(ctx,
nonce_size, nonce,
auth_size, auth,
@@ -1302,6 +1330,33 @@ wrap_nettle_cipher_aead_decrypt(void *_ctx,
if (unlikely(plain_size < encr_size))
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ switch (ctx->cipher->algo) {
+ case GNUTLS_CIPHER_AES_128_CCM:
+ case GNUTLS_CIPHER_AES_256_CCM:
+ /* SP800-38C A.1 says Tlen must be a multiple of 16
+ * between 32 and 128.
+ */
+ switch (tag_size) {
+ case 4: case 6:
+ /* SP800-38C B.2 says Tlen smaller than 64
+ * should not be used under sufficient
+ * restriction. We simply allow those for now.
+ */
+ FALLTHROUGH;
+ case 8: case 10: case 12: case 14: case 16:
+ break;
+ default:
+ if (_gnutls_fips_mode_enabled()) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+
ret = ctx->cipher->aead_decrypt(ctx,
nonce_size, nonce,
auth_size, auth,
diff --git a/tests/fips-test.c b/tests/fips-test.c
index f7556d7bbb..c43503fba0 100644
--- a/tests/fips-test.c
+++ b/tests/fips-test.c
@@ -1,4 +1,5 @@
#include <config.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -213,14 +214,96 @@ test_cipher_disallowed(gnutls_cipher_algorithm_t cipher)
FIPS_POP_CONTEXT(ERROR);
}
+static void
+test_ccm_cipher(gnutls_cipher_algorithm_t cipher, size_t tag_length,
+ bool expect_encryption_fail,
+ gnutls_fips140_operation_state_t expected_state)
+{
+ int ret;
+ unsigned key_size = gnutls_cipher_get_key_size(cipher);
+ gnutls_aead_cipher_hd_t h;
+ gnutls_datum_t key = { key_data, key_size };
+ unsigned char buffer[256];
+ size_t length;
+ gnutls_memset(key_data, 0, key_size);
+
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_aead_cipher_init(&h, cipher, &key);
+ if (ret < 0) {
+ fail("gnutls_aead_cipher_init failed for %s\n",
+ gnutls_cipher_get_name(cipher));
+ }
+ FIPS_POP_CONTEXT(APPROVED);
+
+ fips_push_context(fips_context);
+ memset(buffer, 0, sizeof(buffer));
+ length = sizeof(buffer);
+ ret = gnutls_aead_cipher_encrypt(h, iv_data,
+ gnutls_cipher_get_iv_size(cipher),
+ NULL, 0, tag_length,
+ buffer, length - tag_length,
+ buffer, &length);
+ if (expect_encryption_fail) {
+ if (ret != GNUTLS_E_INVALID_REQUEST) {
+ fail("gnutls_aead_cipher_encrypt(%s) returned %d "
+ "while %d is expected\n",
+ gnutls_cipher_get_name(cipher),
+ ret, GNUTLS_E_INVALID_REQUEST);
+ }
+ } else if (ret < 0) {
+ fail("gnutls_aead_cipher_encrypt failed for %s\n",
+ gnutls_cipher_get_name(cipher));
+ }
+ fips_pop_context(fips_context, expected_state);
+
+ fips_push_context(fips_context);
+ length = sizeof(buffer);
+ ret = gnutls_aead_cipher_decrypt(h, iv_data,
+ gnutls_cipher_get_iv_size(cipher),
+ NULL, 0, tag_length,
+ buffer, length,
+ buffer, &length);
+ if (expect_encryption_fail) {
+ if (ret != GNUTLS_E_INVALID_REQUEST) {
+ fail("gnutls_aead_cipher_decrypt(%s) returned %d "
+ "while %d is expected\n",
+ gnutls_cipher_get_name(cipher),
+ ret, GNUTLS_E_INVALID_REQUEST);
+ }
+ } else if (ret < 0) {
+ fail("gnutls_aead_cipher_decrypt failed for %s\n",
+ gnutls_cipher_get_name(cipher));
+ }
+ fips_pop_context(fips_context, expected_state);
+
+ gnutls_aead_cipher_deinit(h);
+}
+
static inline void
test_ciphers(void)
{
+ size_t i;
+
test_cipher_approved(GNUTLS_CIPHER_AES_128_CBC);
test_cipher_approved(GNUTLS_CIPHER_AES_192_CBC);
test_cipher_approved(GNUTLS_CIPHER_AES_256_CBC);
- test_aead_cipher_approved(GNUTLS_CIPHER_AES_128_CCM);
- test_aead_cipher_approved(GNUTLS_CIPHER_AES_256_CCM);
+
+ /* Check for all allowed Tlen */
+ for (i = 4; i <= 16; i += 2) {
+ test_ccm_cipher(GNUTLS_CIPHER_AES_128_CCM, i,
+ false, GNUTLS_FIPS140_OP_APPROVED);
+ test_ccm_cipher(GNUTLS_CIPHER_AES_256_CCM, i,
+ false, GNUTLS_FIPS140_OP_APPROVED);
+ }
+ test_ccm_cipher(GNUTLS_CIPHER_AES_128_CCM, 3,
+ true, GNUTLS_FIPS140_OP_ERROR);
+ test_ccm_cipher(GNUTLS_CIPHER_AES_256_CCM, 3,
+ true, GNUTLS_FIPS140_OP_ERROR);
+ test_ccm_cipher(GNUTLS_CIPHER_AES_128_CCM, 5,
+ true, GNUTLS_FIPS140_OP_ERROR);
+ test_ccm_cipher(GNUTLS_CIPHER_AES_256_CCM, 5,
+ true, GNUTLS_FIPS140_OP_ERROR);
+
test_aead_cipher_approved(GNUTLS_CIPHER_AES_128_CCM_8);
test_aead_cipher_approved(GNUTLS_CIPHER_AES_256_CCM_8);
test_cipher_approved(GNUTLS_CIPHER_AES_128_CFB8);
--
2.38.1

View File

@ -0,0 +1,427 @@
From 171b934a8c054e98b110892cae4130e1db64e656 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Thu, 29 Sep 2022 21:28:19 +0900
Subject: [PATCH] gnutls-3.7.6-fips-ecdsa-hash-check.patch
---
lib/crypto-backend.h | 12 ++--
lib/nettle/pk.c | 33 +++++-----
lib/privkey.c | 42 ++++++++----
lib/pubkey.c | 5 +-
tests/fips-test.c | 150 ++++++++++++++++++++++++++++++++++++++++++-
5 files changed, 205 insertions(+), 37 deletions(-)
diff --git a/lib/crypto-backend.h b/lib/crypto-backend.h
index f0f68c3..4dd1ae2 100644
--- a/lib/crypto-backend.h
+++ b/lib/crypto-backend.h
@@ -247,11 +247,13 @@ typedef enum {
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);
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index f38016b..c098e2a 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -1104,8 +1104,16 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
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:
@@ -1115,14 +1123,6 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
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)) {
@@ -1545,7 +1545,6 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
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) {
@@ -1571,11 +1570,14 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
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:
@@ -1586,9 +1588,6 @@ _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
not_approved = true;
}
- if (hash_len > vdata->size)
- hash_len = vdata->size;
-
ret =
ecdsa_verify(&pub, hash_len, vdata->data,
&sig);
@@ -2390,8 +2389,10 @@ static int pct_test(gnutls_pk_algorithm_t algo, const gnutls_pk_params_st* param
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);
diff --git a/lib/privkey.c b/lib/privkey.c
index 0b77443..2069fc0 100644
--- a/lib/privkey.c
+++ b/lib/privkey.c
@@ -1251,27 +1251,36 @@ gnutls_privkey_sign_hash2(gnutls_privkey_t signer,
se = _gnutls_sign_to_entry(GNUTLS_SIGN_RSA_RAW);
} else {
se = _gnutls_sign_to_entry(algo);
- if (unlikely(se == NULL))
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
-
+ if (unlikely(se == NULL)) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
}
ret = _gnutls_privkey_get_spki_params(signer, &params);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash,
flags, &params);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
FIX_SIGN_PARAMS(params, flags, se->hash);
- return privkey_sign_prehashed(signer, se, hash_data, signature, &params);
+ ret = privkey_sign_prehashed(signer, se, hash_data, signature, &params);
+
+ cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ }
+ return ret;
}
int
@@ -1366,14 +1375,14 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
ret = _gnutls_privkey_get_spki_params(signer, &params);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm,
hash_algo, flags, &params);
if (ret < 0) {
gnutls_assert();
- return ret;
+ goto cleanup;
}
/* legacy callers of this API could use a hash algorithm of 0 (unknown)
@@ -1391,13 +1400,22 @@ gnutls_privkey_sign_hash(gnutls_privkey_t signer,
se = _gnutls_pk_to_sign_entry(params.pk, hash_algo);
}
- if (unlikely(se == NULL))
- return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ if (unlikely(se == NULL)) {
+ ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ goto cleanup;
+ }
FIX_SIGN_PARAMS(params, flags, hash_algo);
- return privkey_sign_prehashed(signer, se,
- hash_data, signature, &params);
+ ret = privkey_sign_prehashed(signer, se,
+ hash_data, signature, &params);
+ cleanup:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ }
+ return ret;
}
static int
diff --git a/lib/pubkey.c b/lib/pubkey.c
index eba1f5b..35126f3 100644
--- a/lib/pubkey.c
+++ b/lib/pubkey.c
@@ -1985,7 +1985,7 @@ gnutls_pubkey_import_dsa_raw(gnutls_pubkey_t key,
* 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;
@@ -2018,6 +2018,9 @@ int fixup_spki_params(const gnutls_pk_params_st *key_params, const gnutls_sign_e
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;
diff --git a/tests/fips-test.c b/tests/fips-test.c
index 788f4ab..ec0f4b4 100644
--- a/tests/fips-test.c
+++ b/tests/fips-test.c
@@ -80,8 +80,22 @@ static const gnutls_datum_t rsa2342_sha1_sig = {
.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;
@@ -274,6 +288,8 @@ void doit(void)
gnutls_datum_t signature;
unsigned int bits;
uint8_t hmac[64];
+ uint8_t hash[64];
+ gnutls_datum_t hashed_data;
uint8_t pbkdf2[64];
gnutls_datum_t temp_key = { NULL, 0 };
@@ -473,7 +489,7 @@ void doit(void)
/* 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 */
@@ -519,7 +535,7 @@ void doit(void)
/* 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 */
@@ -543,6 +559,134 @@ void doit(void)
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);
+
+ /* Create a SHA256 hashed data for 2-pass signature API; not a
+ * crypto operation */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_hash_fast(GNUTLS_DIG_SHA256, data.data, data.size, hash);
+ if (ret < 0) {
+ fail("gnutls_hash_fast failed\n");
+ }
+ hashed_data.data = hash;
+ hashed_data.size = 32;
+ FIPS_POP_CONTEXT(INITIAL);
+
+ /* Create a signature with ECDSA and SHA256 (2-pass API); not-approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_hash2(privkey, GNUTLS_SIGN_ECDSA_SHA256, 0,
+ &hashed_data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_hash2 failed\n");
+ }
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+ gnutls_free(signature.data);
+
+ /* Create a signature with ECDSA and SHA256 (2-pass old API); not-approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA256, 0,
+ &hashed_data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_hash failed\n");
+ }
+ FIPS_POP_CONTEXT(NOT_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);
+
+ /* Create a SHA1 hashed data for 2-pass signature API; not a
+ * crypto operation */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_hash_fast(GNUTLS_DIG_SHA1, data.data, data.size, hash);
+ if (ret < 0) {
+ fail("gnutls_hash_fast failed\n");
+ }
+ hashed_data.data = hash;
+ hashed_data.size = 20;
+ FIPS_POP_CONTEXT(INITIAL);
+
+ /* Create a signature with ECDSA and SHA1 (2-pass API); not-approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_hash2(privkey, GNUTLS_SIGN_ECDSA_SHA1, 0,
+ &hashed_data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_hash2 failed\n");
+ }
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+ gnutls_free(signature.data);
+
+ /* Create a signature with ECDSA and SHA1 (2-pass old API); not-approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_privkey_sign_hash(privkey, GNUTLS_DIG_SHA1, 0,
+ &hashed_data, &signature);
+ if (ret < 0) {
+ fail("gnutls_privkey_sign_hash 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));
--
2.37.3

View File

@ -0,0 +1,163 @@
From 3bd42dc88ff062bf9ede2b593e1ad1afa6f68f62 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Wed, 16 Nov 2022 23:02:13 +0900
Subject: [PATCH] nettle: mark non-compliant RSA-PSS salt length to be
not-approved
According to FIPS 186-5 5.4, the salt length must be in the range
between 0 and the hash length inclusive. While the use of those salt
lengths is still allowed for compatibility, it is reported as
non-approved operation through FIPS service indicator.
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/nettle/pk.c | 9 ++++++++
tests/rsa-rsa-pss.c | 54 ++++++++++++++++++++++++++++++++++++---------
2 files changed, 53 insertions(+), 10 deletions(-)
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index c098e2aa45..7732e90542 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -1316,6 +1316,15 @@ _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
mpz_init(s);
+ me = hash_to_entry(sign_params->rsa_pss_dig);
+
+ /* According to FIPS 186-5 5.4, the salt length must be
+ * in the range between 0 and the hash length inclusive.
+ */
+ if (sign_params->salt_size > _gnutls_mac_get_algo_len(me)) {
+ not_approved = true;
+ }
+
ret =
_rsa_pss_sign_digest_tr(sign_params->rsa_pss_dig,
&pub, &priv,
diff --git a/tests/rsa-rsa-pss.c b/tests/rsa-rsa-pss.c
index 19a175b722..d7799c1961 100644
--- a/tests/rsa-rsa-pss.c
+++ b/tests/rsa-rsa-pss.c
@@ -46,6 +46,8 @@ const gnutls_datum_t raw_data = {
11
};
+static gnutls_fips140_context_t fips_context;
+
static void inv_sign_check(unsigned sigalgo,
gnutls_privkey_t privkey, int exp_error)
{
@@ -86,13 +88,16 @@ static void inv_encryption_check(gnutls_pk_algorithm_t algorithm,
static void sign_verify_data(unsigned sigalgo, gnutls_privkey_t privkey,
unsigned int sign_flags, unsigned int verify_flags,
- int sign_exp_error, int verify_exp_error)
+ int sign_exp_error, int verify_exp_error,
+ gnutls_fips140_operation_state_t sign_exp_state)
{
int ret;
gnutls_datum_t signature = { NULL, 0 };
+ fips_push_context(fips_context);
ret = gnutls_privkey_sign_data2(privkey, sigalgo, sign_flags,
&raw_data, &signature);
+ fips_pop_context(fips_context, sign_exp_state);
if (ret != sign_exp_error)
fail("gnutls_x509_privkey_sign_data returned unexpected error: %s\n",
gnutls_strerror(ret));
@@ -180,11 +185,16 @@ void doit(void)
if (debug)
gnutls_global_set_log_level(4711);
+ assert(gnutls_fips140_context_init(&fips_context) >= 0);
+
prepare_keys(&pkey_rsa_pss, &pkey_rsa, GNUTLS_DIG_SHA256, 32);
- sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss, 0, 0, 0, 0);
- sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0);
- sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa, 0, 0, 0, 0);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss, 0, 0, 0, 0,
+ GNUTLS_FIPS140_OP_APPROVED);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0,
+ GNUTLS_FIPS140_OP_APPROVED);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa, 0, 0, 0, 0,
+ GNUTLS_FIPS140_OP_APPROVED);
if (debug)
success("success signing with RSA-PSS-SHA256\n");
@@ -213,41 +223,65 @@ void doit(void)
gnutls_privkey_deinit(pkey_rsa_pss);
gnutls_privkey_deinit(pkey_rsa);
+ /* Restrict key to use salt length larger than hash output
+ * length (not approved in FIPS).
+ */
+ prepare_keys(&pkey_rsa_pss, &pkey_rsa, GNUTLS_DIG_SHA256, 33);
+
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss, 0, 0, 0, 0,
+ GNUTLS_FIPS140_OP_NOT_APPROVED);
+
+ gnutls_privkey_deinit(pkey_rsa_pss);
+ gnutls_privkey_deinit(pkey_rsa);
+
/* Use the mismatched salt length with the digest length */
prepare_keys(&pkey_rsa_pss, &pkey_rsa, GNUTLS_DIG_SHA256, 48);
sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa_pss,
- 0, 0, 0, 0);
+ 0, 0, 0, 0, GNUTLS_FIPS140_OP_NOT_APPROVED);
sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss,
GNUTLS_PRIVKEY_FLAG_RSA_PSS_FIXED_SALT_LENGTH,
0,
GNUTLS_E_CONSTRAINT_ERROR,
- 0);
+ 0,
+ /* The error is caught before calling the actual
+ * signing operation.
+ */
+ GNUTLS_FIPS140_OP_INITIAL);
sign_verify_data(GNUTLS_SIGN_RSA_PSS_SHA256, pkey_rsa_pss,
0,
GNUTLS_VERIFY_RSA_PSS_FIXED_SALT_LENGTH,
0,
- GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ GNUTLS_E_PK_SIG_VERIFY_FAILED,
+ GNUTLS_FIPS140_OP_NOT_APPROVED);
assert(gnutls_x509_spki_init(&spki)>=0);
gnutls_x509_spki_set_rsa_pss_params(spki, GNUTLS_DIG_SHA256, 48);
assert(gnutls_privkey_set_spki(pkey_rsa, spki, 0)>=0);
- sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0);
+ sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa, 0, 0, 0, 0,
+ GNUTLS_FIPS140_OP_NOT_APPROVED);
sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa,
GNUTLS_PRIVKEY_FLAG_RSA_PSS_FIXED_SALT_LENGTH,
0,
GNUTLS_E_CONSTRAINT_ERROR,
- 0);
+ 0,
+ /* The error is caught before calling the actual
+ * signing operation.
+ */
+ GNUTLS_FIPS140_OP_INITIAL);
sign_verify_data(GNUTLS_SIGN_RSA_PSS_RSAE_SHA256, pkey_rsa,
0,
GNUTLS_VERIFY_RSA_PSS_FIXED_SALT_LENGTH,
0,
- GNUTLS_E_PK_SIG_VERIFY_FAILED);
+ GNUTLS_E_PK_SIG_VERIFY_FAILED,
+ GNUTLS_FIPS140_OP_NOT_APPROVED);
gnutls_privkey_deinit(pkey_rsa_pss);
gnutls_privkey_deinit(pkey_rsa);
gnutls_x509_spki_deinit(spki);
+ gnutls_fips140_context_deinit(fips_context);
+
gnutls_global_deinit();
}
--
2.38.1

View File

@ -440,3 +440,201 @@ index a6a283fa67..31a5e26111 100644
-- --
2.36.1 2.36.1
From 354027c0c09db60d3083fa48ae791046d336957b Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Tue, 28 Jun 2022 17:22:36 +0200
Subject: [PATCH] tests/fips-test: minor extension
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
---
tests/fips-test.c | 36 +++++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/tests/fips-test.c b/tests/fips-test.c
index 31a5e26111..f9bd34586a 100644
--- a/tests/fips-test.c
+++ b/tests/fips-test.c
@@ -427,34 +427,43 @@ void doit(void)
rsa_import_keypair(&privkey, &pubkey, "rsa-2432.pem");
FIPS_POP_CONTEXT(INITIAL);
- /* Create a signature with SHA256; approved */
+ /* Create a signature with 2432-bit RSA and SHA256; 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");
}
- gnutls_free(signature.data);
FIPS_POP_CONTEXT(APPROVED);
- /* Create a signature with SHA-1; not approved */
+ /* Verify a signature with 2432-bit RSA and SHA256; approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_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 2432-bit RSA and SHA-1; 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");
}
- gnutls_free(signature.data);
FIPS_POP_CONTEXT(NOT_APPROVED);
- /* Verify a signature created with SHA-1; approved */
+ /* Verify a signature created with 2432-bit RSA and SHA-1; approved */
FIPS_PUSH_CONTEXT();
- ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0, &data,
- &rsa2342_sha1_sig);
+ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
+ &data, &rsa2342_sha1_sig);
if (ret < 0) {
fail("gnutls_pubkey_verify_data2 failed\n");
}
FIPS_POP_CONTEXT(APPROVED);
+ gnutls_free(signature.data);
gnutls_pubkey_deinit(pubkey);
gnutls_privkey_deinit(privkey);
@@ -463,15 +472,24 @@ void doit(void)
rsa_import_keypair(&privkey, &pubkey, "rsa-512.pem");
FIPS_POP_CONTEXT(INITIAL);
- /* Create a signature; not approved */
+ /* Create a signature with 512-bit RSA and SHA256; not 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");
}
- gnutls_free(signature.data);
FIPS_POP_CONTEXT(NOT_APPROVED);
+
+ /* Verify a signature with 512-bit RSA and SHA256; not approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA256, 0,
+ &data, &signature);
+ if (ret < 0) {
+ fail("gnutls_pubkey_verify_data2 failed\n");
+ }
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+ gnutls_free(signature.data);
gnutls_pubkey_deinit(pubkey);
gnutls_privkey_deinit(privkey);
--
2.37.3
From 5a745120148861d873f47c1428c8c6dcadcf109b Mon Sep 17 00:00:00 2001
From: Richard Costa <richard.costa@suse.com>
Date: Sat, 9 Jul 2022 00:50:21 +0000
Subject: [PATCH] Add self-test code inside a FIPS context
Self-test code exercise lots of different FIPS-related code with
side-effects. So, in order to prevent it from losing information when
executing inside another context, we create an appropriated one.
If the self-test fails, then the library is placed in error state, so it
doesn't matter for other contexts.
Signed-off-by: Richard Maciel Costa <richard.costa@suse.com>
---
lib/fips.c | 19 +++++++++++++++++++
tests/fips-test.c | 20 ++++++++++++--------
2 files changed, 31 insertions(+), 8 deletions(-)
diff --git a/lib/fips.c b/lib/fips.c
index 31a52a990f..7d143e608e 100644
--- a/lib/fips.c
+++ b/lib/fips.c
@@ -902,6 +902,16 @@ gnutls_fips140_run_self_tests(void)
#ifdef ENABLE_FIPS140
int ret;
unsigned prev_lib_state;
+ gnutls_fips140_context_t fips_context = NULL;
+
+ /* Save the FIPS context, because self tests change it */
+ if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED) {
+ if (gnutls_fips140_context_init(&fips_context) < 0 ||
+ gnutls_fips140_push_context(fips_context) < 0) {
+ gnutls_fips140_context_deinit(fips_context);
+ fips_context = NULL;
+ }
+ }
/* Temporarily switch to LIB_STATE_SELFTEST as some of the
* algorithms are implemented using special constructs in
@@ -918,6 +928,15 @@ gnutls_fips140_run_self_tests(void)
/* Restore the previous library state */
_gnutls_switch_lib_state(prev_lib_state);
}
+
+ /* Restore the previous FIPS context */
+ if (gnutls_fips140_mode_enabled() != GNUTLS_FIPS140_DISABLED && fips_context) {
+ if (gnutls_fips140_pop_context() < 0) {
+ _gnutls_switch_lib_state(LIB_STATE_ERROR);
+ _gnutls_audit_log(NULL, "FIPS140-2 context restoration failed\n");
+ }
+ gnutls_fips140_context_deinit(fips_context);
+ }
return ret;
#else
return 0;
diff --git a/tests/fips-test.c b/tests/fips-test.c
index f9bd34586a..475b739197 100644
--- a/tests/fips-test.c
+++ b/tests/fips-test.c
@@ -457,8 +457,9 @@ void doit(void)
/* Verify a signature created with 2432-bit RSA and SHA-1; approved */
FIPS_PUSH_CONTEXT();
- ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1, 0,
- &data, &rsa2342_sha1_sig);
+ ret = gnutls_pubkey_verify_data2(pubkey, GNUTLS_SIGN_RSA_SHA1,
+ GNUTLS_VERIFY_ALLOW_SIGN_WITH_SHA1, &data,
+ &rsa2342_sha1_sig);
if (ret < 0) {
fail("gnutls_pubkey_verify_data2 failed\n");
}
@@ -501,6 +502,15 @@ void doit(void)
}
FIPS_POP_CONTEXT(APPROVED);
+ /* run self-tests manually */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_rnd(GNUTLS_RND_RANDOM, key16, sizeof(key16));
+ ret = gnutls_fips140_run_self_tests();
+ if (ret < 0) {
+ fail("gnutls_fips140_run_self_tests failed\n");
+ }
+ FIPS_POP_CONTEXT(APPROVED);
+
/* Test when FIPS140 is set to error state */
_gnutls_lib_simulate_error();
@@ -544,12 +554,6 @@ void doit(void)
gnutls_fips140_context_deinit(fips_context);
- /* run self-tests manually */
- ret = gnutls_fips140_run_self_tests();
- if (ret < 0) {
- fail("gnutls_fips140_run_self_tests failed\n");
- }
-
gnutls_global_deinit();
return;
}
--
2.37.3

View File

@ -0,0 +1,407 @@
From e8b35d31817d207d8b4b87ccf104d3b93aa446e0 Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Mon, 17 Oct 2022 11:11:43 +0900
Subject: [PATCH] tests: move FIPS service indicator functions to common file
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
tests/dh-compute.c | 36 +++++---------------------
tests/fips-rsa-sizes.c | 24 -----------------
tests/fips-test.c | 27 +++-----------------
tests/kdf-api.c | 27 +-------------------
tests/pkcs12_encode.c | 24 -----------------
tests/privkey-keygen.c | 24 -----------------
tests/utils.h | 58 ++++++++++++++++++++++++++++++++++++++++++
7 files changed, 69 insertions(+), 151 deletions(-)
diff --git a/tests/dh-compute.c b/tests/dh-compute.c
index 828fb05e9c..6c1d5328f6 100644
--- a/tests/dh-compute.c
+++ b/tests/dh-compute.c
@@ -156,34 +156,10 @@ void doit(void)
{ NULL }
};
-#define FIPS_PUSH_CONTEXT() do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_push_context(fips_context); \
- if (ret < 0) { \
- fail("gnutls_fips140_push_context failed\n"); \
- } \
- } \
-} while (0)
-
-#define FIPS_POP_CONTEXT(state) do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_pop_context(); \
- if (ret < 0) { \
- fail("gnutls_fips140_context_pop failed\n"); \
- } \
- fips_state = gnutls_fips140_get_operation_state(fips_context); \
- if (fips_state != state) { \
- fail("operation state is not %d (%d)\n", \
- state, fips_state); \
- } \
- } \
-} while (0)
-
for (int i = 0; test_data[i].name != NULL; i++) {
gnutls_datum_t priv_key, pub_key;
gnutls_dh_params_t dh_params;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
int ret;
if (gnutls_fips140_mode_enabled()) {
@@ -193,24 +169,24 @@ void doit(void)
}
}
- FIPS_PUSH_CONTEXT();
+ fips_push_context(fips_context);
params(&dh_params, &test_data[i].prime, &test_data[i].q,
&test_data[i].generator);
- FIPS_POP_CONTEXT(GNUTLS_FIPS140_OP_INITIAL);
+ fips_pop_context(fips_context, GNUTLS_FIPS140_OP_INITIAL);
success("%s genkey\n", test_data[i].name);
- FIPS_PUSH_CONTEXT();
+ fips_push_context(fips_context);
genkey(dh_params, &priv_key, &pub_key);
- FIPS_POP_CONTEXT(test_data[i].fips_state_genkey);
+ fips_pop_context(fips_context, test_data[i].fips_state_genkey);
success("%s compute_key\n", test_data[i].name);
- FIPS_PUSH_CONTEXT();
+ fips_push_context(fips_context);
compute_key(test_data[i].name, dh_params, &priv_key,
&pub_key, &test_data[i].peer_key,
test_data[i].expected_error, NULL, 0);
- FIPS_POP_CONTEXT(test_data[i].fips_state_compute_key);
+ fips_pop_context(fips_context, test_data[i].fips_state_compute_key);
gnutls_dh_params_deinit(dh_params);
gnutls_free(priv_key.data);
diff --git a/tests/fips-rsa-sizes.c b/tests/fips-rsa-sizes.c
index 84b9affabb..5feb284503 100644
--- a/tests/fips-rsa-sizes.c
+++ b/tests/fips-rsa-sizes.c
@@ -27,25 +27,6 @@
#include <gnutls/abstract.h>
#include <gnutls/x509.h>
-#define FIPS_PUSH_CONTEXT() do { \
- ret = gnutls_fips140_push_context(fips_context); \
- if (ret < 0) { \
- fail("gnutls_fips140_push_context failed\n"); \
- } \
-} while (0)
-
-#define FIPS_POP_CONTEXT(state) do { \
- ret = gnutls_fips140_pop_context(); \
- if (ret < 0) { \
- fail("gnutls_fips140_context_pop failed\n"); \
- } \
- fips_state = gnutls_fips140_get_operation_state(fips_context); \
- if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \
- fail("operation state is not " # state " (%d)\n", \
- fips_state); \
- } \
-} while (0)
-
void generate_successfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
unsigned int size);
@@ -63,7 +44,6 @@ void generate_successfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
int ret;
gnutls_x509_privkey_t xprivkey;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
assert(gnutls_fips140_context_init(&fips_context) == 0);
fprintf(stderr, "%d-bit\n", size);
@@ -102,7 +82,6 @@ void generate_unsuccessfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
int ret;
gnutls_x509_privkey_t xprivkey;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
assert(gnutls_fips140_context_init(&fips_context) == 0);
fprintf(stderr, "%d-bit\n", size);
@@ -156,7 +135,6 @@ void generate_unsuccessfully(gnutls_privkey_t* privkey, gnutls_pubkey_t* pubkey,
void sign_verify_successfully(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey) {
int ret;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
gnutls_datum_t signature;
gnutls_datum_t plaintext = {
@@ -190,7 +168,6 @@ void sign_verify_unsuccessfully(gnutls_privkey_t privkey,
gnutls_pubkey_t pubkey) {
int ret;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
gnutls_datum_t signature;
gnutls_datum_t plaintext = {
@@ -225,7 +202,6 @@ void sign_verify_unsuccessfully(gnutls_privkey_t privkey,
void nosign_verify(gnutls_privkey_t privkey, gnutls_pubkey_t pubkey) {
int ret;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
gnutls_datum_t signature;
gnutls_datum_t plaintext = {
diff --git a/tests/fips-test.c b/tests/fips-test.c
index f789afb107..b0bae4ef9f 100644
--- a/tests/fips-test.c
+++ b/tests/fips-test.c
@@ -12,25 +12,6 @@
/* This does check the FIPS140 support.
*/
-#define FIPS_PUSH_CONTEXT() do { \
- ret = gnutls_fips140_push_context(fips_context); \
- if (ret < 0) { \
- fail("gnutls_fips140_push_context failed\n"); \
- } \
-} while (0)
-
-#define FIPS_POP_CONTEXT(state) do { \
- ret = gnutls_fips140_pop_context(); \
- if (ret < 0) { \
- fail("gnutls_fips140_context_pop failed\n"); \
- } \
- fips_state = gnutls_fips140_get_operation_state(fips_context); \
- if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \
- fail("operation state is not " # state " (%d)\n", \
- fips_state); \
- } \
-} while (0)
-
void _gnutls_lib_simulate_error(void);
static void tls_log_func(int level, const char *str)
@@ -40,10 +21,9 @@ static void tls_log_func(int level, const char *str)
static uint8_t key16[16];
static uint8_t iv16[16];
-uint8_t key_data[64];
-uint8_t iv_data[16];
-gnutls_fips140_context_t fips_context;
-gnutls_fips140_operation_state_t fips_state;
+static uint8_t key_data[64];
+static uint8_t iv_data[16];
+static gnutls_fips140_context_t fips_context;
static const gnutls_datum_t data = { .data = (unsigned char *)"foo", 3 };
static const uint8_t rsa2342_sha1_sig_data[] = {
@@ -276,6 +256,7 @@ test_ciphers(void)
void doit(void)
{
int ret;
+ gnutls_fips140_operation_state_t fips_state;
unsigned int mode;
gnutls_cipher_hd_t ch;
gnutls_hmac_hd_t mh;
diff --git a/tests/kdf-api.c b/tests/kdf-api.c
index 9724502005..a28ce82a62 100644
--- a/tests/kdf-api.c
+++ b/tests/kdf-api.c
@@ -33,30 +33,7 @@
#define MAX_BUF 1024
static gnutls_fips140_context_t fips_context;
-static gnutls_fips140_operation_state_t fips_state;
-
-#define FIPS_PUSH_CONTEXT() do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_push_context(fips_context); \
- if (ret < 0) { \
- fail("gnutls_fips140_push_context failed\n"); \
- } \
- } \
-} while (0)
-
-#define FIPS_POP_CONTEXT(state) do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_pop_context(); \
- if (ret < 0) { \
- fail("gnutls_fips140_context_pop failed\n"); \
- } \
- fips_state = gnutls_fips140_get_operation_state(fips_context); \
- if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \
- fail("operation state is not " # state " (%d)\n", \
- fips_state); \
- } \
- } \
-} while (0)
+
static void
test_hkdf(gnutls_mac_algorithm_t mac,
@@ -74,7 +51,6 @@ test_hkdf(gnutls_mac_algorithm_t mac,
gnutls_datum_t prk;
gnutls_datum_t okm;
uint8_t buf[MAX_BUF];
- int ret;
success("HKDF test with %s\n", gnutls_mac_get_name(mac));
@@ -144,7 +120,6 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
gnutls_datum_t salt;
gnutls_datum_t okm;
uint8_t buf[MAX_BUF];
- int ret;
success("PBKDF2 test with %s\n", gnutls_mac_get_name(mac));
diff --git a/tests/pkcs12_encode.c b/tests/pkcs12_encode.c
index ea39f3d69e..dc55daccde 100644
--- a/tests/pkcs12_encode.c
+++ b/tests/pkcs12_encode.c
@@ -70,29 +70,6 @@ static void tls_log_func(int level, const char *str)
fprintf(stderr, "|<%d>| %s", level, str);
}
-#define FIPS_PUSH_CONTEXT() do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_push_context(fips_context); \
- if (ret < 0) { \
- fail("gnutls_fips140_push_context failed\n"); \
- } \
- } \
-} while (0)
-
-#define FIPS_POP_CONTEXT(state) do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_pop_context(); \
- if (ret < 0) { \
- fail("gnutls_fips140_context_pop failed\n"); \
- } \
- fips_state = gnutls_fips140_get_operation_state(fips_context); \
- if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \
- fail("operation state is not " # state " (%d)\n", \
- fips_state); \
- } \
- } \
-} while (0)
-
void doit(void)
{
gnutls_pkcs12_t pkcs12;
@@ -106,7 +83,6 @@ void doit(void)
size_t size;
unsigned i;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
size_t n_tests = 0;
struct tests {
const char *name;
diff --git a/tests/privkey-keygen.c b/tests/privkey-keygen.c
index 2766afee08..2531906d71 100644
--- a/tests/privkey-keygen.c
+++ b/tests/privkey-keygen.c
@@ -119,30 +119,6 @@ void doit(void)
gnutls_x509_privkey_t pkey, dst;
int ret, algorithm, i;
gnutls_fips140_context_t fips_context;
- gnutls_fips140_operation_state_t fips_state;
-
-#define FIPS_PUSH_CONTEXT() do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_push_context(fips_context); \
- if (ret < 0) { \
- fail("gnutls_fips140_push_context failed\n"); \
- } \
- } \
-} while (0)
-
-#define FIPS_POP_CONTEXT(state) do { \
- if (gnutls_fips140_mode_enabled()) { \
- ret = gnutls_fips140_pop_context(); \
- if (ret < 0) { \
- fail("gnutls_fips140_context_pop failed\n"); \
- } \
- fips_state = gnutls_fips140_get_operation_state(fips_context); \
- if (fips_state != GNUTLS_FIPS140_OP_ ## state) { \
- fail("operation state is not " # state " (%d)\n", \
- fips_state); \
- } \
- } \
-} while (0)
ret = global_init();
if (ret < 0)
diff --git a/tests/utils.h b/tests/utils.h
index d3a2ba8d16..4433a07057 100644
--- a/tests/utils.h
+++ b/tests/utils.h
@@ -210,4 +210,62 @@ inline static unsigned int get_dtls_retransmit_timeout(void) {
return (unsigned int) ul;
}
+static inline const char *
+fips_operation_state_to_string(gnutls_fips140_operation_state_t state)
+{
+ switch (state) {
+ case GNUTLS_FIPS140_OP_INITIAL:
+ return "INITIAL";
+ case GNUTLS_FIPS140_OP_APPROVED:
+ return "APPROVED";
+ case GNUTLS_FIPS140_OP_NOT_APPROVED:
+ return "NOT_APPROVED";
+ case GNUTLS_FIPS140_OP_ERROR:
+ return "ERROR";
+ default:
+ /*NOTREACHED*/
+ assert(0);
+ return NULL;
+ }
+}
+
+static inline void
+fips_push_context(gnutls_fips140_context_t context)
+{
+ if (gnutls_fips140_mode_enabled()) {
+ int ret;
+
+ ret = gnutls_fips140_push_context(context);
+ if (ret < 0) {
+ fail("gnutls_fips140_push_context failed\n");
+ }
+ }
+}
+
+static inline void
+fips_pop_context(gnutls_fips140_context_t context,
+ gnutls_fips140_operation_state_t expected_state)
+{
+ gnutls_fips140_operation_state_t state;
+
+ if (gnutls_fips140_mode_enabled()) {
+ int ret;
+
+ ret = gnutls_fips140_pop_context();
+ if (ret < 0) {
+ fail("gnutls_fips140_context_pop failed\n");
+ }
+ state = gnutls_fips140_get_operation_state(context);
+ if (state != expected_state) {
+ fail("operation state is not %s (%s)\n",
+ fips_operation_state_to_string(expected_state),
+ fips_operation_state_to_string(state));
+ }
+ }
+}
+
+/* To use those convenient macros, define fips_context variable. */
+#define FIPS_PUSH_CONTEXT() fips_push_context(fips_context)
+#define FIPS_POP_CONTEXT(state) fips_pop_context(fips_context, GNUTLS_FIPS140_OP_ ## state)
+
#endif /* GNUTLS_TESTS_UTILS_H */
--
2.38.1

View File

@ -0,0 +1,310 @@
From f8a8961cfa176fc74c153cb6e1e68aff5e2d42f2 Mon Sep 17 00:00:00 2001
From: rpm-build <rpm-build>
Date: Tue, 27 Sep 2022 10:52:19 +0900
Subject: [PATCH] gnutls-3.7.6-fips-symkey-limit.patch
---
lib/crypto-api.c | 26 ++++++++++++++++++++++---
tests/fips-test.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
tests/kdf-api.c | 9 ++++++++-
3 files changed, 80 insertions(+), 4 deletions(-)
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index b3e1eec..35200fb 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -896,6 +896,7 @@ gnutls_hash_hd_t gnutls_hash_copy(gnutls_hash_hd_t handle)
int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
{
int ret;
+ bool not_approved = false;
FAIL_IF_LIB_ERROR;
@@ -912,17 +913,31 @@ int gnutls_key_generate(gnutls_datum_t * key, unsigned int key_size)
key->data = gnutls_malloc(key->size);
if (!key->data) {
gnutls_assert();
- return GNUTLS_E_MEMORY_ERROR;
+ ret = GNUTLS_E_MEMORY_ERROR;
+ goto error;
+ }
+
+ /* Key lengths of less than 112 bits are not approved */
+ if (key_size < 14) {
+ not_approved = true;
}
ret = gnutls_rnd(GNUTLS_RND_RANDOM, key->data, key->size);
if (ret < 0) {
gnutls_assert();
_gnutls_free_datum(key);
- return ret;
+ goto error;
}
- return 0;
+ error:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else if (not_approved) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_NOT_APPROVED);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+ }
+ return ret;
}
/* AEAD API */
@@ -2058,6 +2073,11 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
not_approved = true;
}
+ /* Key lengths and output sizes of less than 112 bits are not approved */
+ if (key->size < 14 || length < 14) {
+ not_approved = true;
+ }
+
ret = _gnutls_kdf_ops.pbkdf2(mac, key->data, key->size,
salt->data, salt->size, iter_count,
output, length);
diff --git a/tests/fips-test.c b/tests/fips-test.c
index 31a5e26..27da414 100644
--- a/tests/fips-test.c
+++ b/tests/fips-test.c
@@ -274,6 +274,8 @@ void doit(void)
gnutls_datum_t signature;
unsigned int bits;
uint8_t hmac[64];
+ uint8_t pbkdf2[64];
+ gnutls_datum_t temp_key = { NULL, 0 };
fprintf(stderr,
"Please note that if in FIPS140 mode, you need to assure the library's integrity prior to running this test\n");
@@ -371,11 +373,58 @@ void doit(void)
}
FIPS_POP_CONTEXT(NOT_APPROVED);
+ /* PBKDF2 with key equal to or longer than 112 bits: approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
+ &pbkdf2, sizeof(pbkdf2));
+ if (ret < 0) {
+ fail("gnutls_pbkdf2 failed\n");
+ }
+ FIPS_POP_CONTEXT(APPROVED);
+
+ /* PBKDF2 with key shorter than 112 bits: not approved */
+ FIPS_PUSH_CONTEXT();
+ key.size = 13;
+ ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
+ &pbkdf2, sizeof(pbkdf2));
+ if (ret < 0) {
+ fail("gnutls_pbkdf2 failed\n");
+ }
+ key.size = sizeof(key16);
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+
+ /* PBKDF2 with output shorter than 112 bits: not approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_pbkdf2(GNUTLS_MAC_SHA256, &key, &iv, 100,
+ &pbkdf2, 13);
+ if (ret < 0) {
+ fail("gnutls_pbkdf2 failed\n");
+ }
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+
ret = gnutls_rnd(GNUTLS_RND_NONCE, key16, sizeof(key16));
if (ret < 0) {
fail("gnutls_rnd failed\n");
}
+ /* Symmetric key generation equal to or longer than 112 bits: approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_key_generate(&temp_key, 14);
+ if (ret < 0) {
+ fail("gnutls_key_generate failed\n");
+ }
+ gnutls_free(temp_key.data);
+ FIPS_POP_CONTEXT(APPROVED);
+
+ /* Symmetric key generation shorter than 112 bits: not approved */
+ FIPS_PUSH_CONTEXT();
+ ret = gnutls_key_generate(&temp_key, 13);
+ if (ret < 0) {
+ fail("gnutls_key_generate failed\n");
+ }
+ gnutls_free(temp_key.data);
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+
ret = gnutls_pubkey_init(&pubkey);
if (ret < 0) {
fail("gnutls_pubkey_init failed\n");
diff --git a/tests/kdf-api.c b/tests/kdf-api.c
index 25fbc6a..8a4677c 100644
--- a/tests/kdf-api.c
+++ b/tests/kdf-api.c
@@ -89,6 +89,7 @@ test_hkdf(gnutls_mac_algorithm_t mac,
FIPS_PUSH_CONTEXT();
assert(gnutls_hkdf_extract(mac, &ikm, &salt, buf) >= 0);
+ /* HKDF outside of TLS usage is not approved */
FIPS_POP_CONTEXT(NOT_APPROVED);
gnutls_free(ikm.data);
gnutls_free(salt.data);
@@ -110,6 +111,7 @@ test_hkdf(gnutls_mac_algorithm_t mac,
FIPS_PUSH_CONTEXT();
assert(gnutls_hkdf_expand(mac, &prk, &info, buf, length) >= 0);
+ /* HKDF outside of TLS usage is not approved */
FIPS_POP_CONTEXT(NOT_APPROVED);
gnutls_free(info.data);
@@ -151,7 +153,12 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
FIPS_PUSH_CONTEXT();
assert(gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length) >= 0);
- FIPS_POP_CONTEXT(APPROVED);
+ /* Key sizes and output sizes less than 112-bit are not approved. */
+ if (ikm.size < 14 || length < 14) {
+ FIPS_POP_CONTEXT(NOT_APPROVED);
+ } else {
+ FIPS_POP_CONTEXT(APPROVED);
+ }
gnutls_free(ikm.data);
gnutls_free(salt.data);
--
2.37.3
From 86eded166f77612c70201c0d85d3abe711edd77d Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org>
Date: Thu, 29 Sep 2022 21:19:26 +0900
Subject: [PATCH] fips: only mark HMAC as approved in PBKDF2
As ACVP only allows HMAC used with PBKDF2[1], this change marks other
hash algorithms not-approved.
1. https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
Signed-off-by: Daiki Ueno <ueno@gnu.org>
---
lib/crypto-api.c | 5 ++++-
lib/fips.h | 16 +++++++++++++++-
tests/kdf-api.c | 30 +++++++++++++++++++++++++++++-
3 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index d3e601ab3a..9f7e18db11 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -2229,7 +2229,10 @@ gnutls_pbkdf2(gnutls_mac_algorithm_t mac,
if (!is_mac_algo_allowed(mac)) {
_gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
return gnutls_assert_val(GNUTLS_E_UNWANTED_ALGORITHM);
- } else if (!is_mac_algo_approved_in_fips(mac)) {
+ } else if (!is_mac_algo_hmac_approved_in_fips(mac)) {
+ /* ACVP only allows HMAC used with PBKDF2:
+ * https://pages.nist.gov/ACVP/draft-celi-acvp-pbkdf.html
+ */
not_approved = true;
}
diff --git a/lib/fips.h b/lib/fips.h
index 3a74f254e7..bf61b36741 100644
--- a/lib/fips.h
+++ b/lib/fips.h
@@ -76,7 +76,7 @@ void _gnutls_lib_simulate_error(void);
void _gnutls_lib_force_operational(void);
inline static bool
-is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
+is_mac_algo_hmac_approved_in_fips(gnutls_mac_algorithm_t algo)
{
switch (algo) {
case GNUTLS_MAC_SHA1:
@@ -88,6 +88,20 @@ is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
case GNUTLS_MAC_SHA3_256:
case GNUTLS_MAC_SHA3_384:
case GNUTLS_MAC_SHA3_512:
+ return true;
+ default:
+ return false;
+ }
+}
+
+inline static bool
+is_mac_algo_approved_in_fips(gnutls_mac_algorithm_t algo)
+{
+ if (is_mac_algo_hmac_approved_in_fips(algo)) {
+ return true;
+ }
+
+ switch (algo) {
case GNUTLS_MAC_AES_CMAC_128:
case GNUTLS_MAC_AES_CMAC_256:
case GNUTLS_MAC_AES_GMAC_128:
diff --git a/tests/kdf-api.c b/tests/kdf-api.c
index 577cbf7a17..4feb22688b 100644
--- a/tests/kdf-api.c
+++ b/tests/kdf-api.c
@@ -26,6 +26,7 @@
#include <gnutls/crypto.h>
#include <assert.h>
+#include <stdbool.h>
#include <stdint.h>
#include "utils.h"
@@ -133,6 +134,25 @@ test_hkdf(gnutls_mac_algorithm_t mac,
gnutls_free(hex.data);
}
+inline static bool
+is_mac_algo_hmac_approved_in_fips(gnutls_mac_algorithm_t algo)
+{
+ switch (algo) {
+ case GNUTLS_MAC_SHA1:
+ case GNUTLS_MAC_SHA256:
+ case GNUTLS_MAC_SHA384:
+ case GNUTLS_MAC_SHA512:
+ case GNUTLS_MAC_SHA224:
+ case GNUTLS_MAC_SHA3_224:
+ case GNUTLS_MAC_SHA3_256:
+ case GNUTLS_MAC_SHA3_384:
+ case GNUTLS_MAC_SHA3_512:
+ return true;
+ default:
+ return false;
+ }
+}
+
static void
test_pbkdf2(gnutls_mac_algorithm_t mac,
const char *ikm_hex,
@@ -161,7 +181,8 @@ test_pbkdf2(gnutls_mac_algorithm_t mac,
FIPS_PUSH_CONTEXT();
assert(gnutls_pbkdf2(mac, &ikm, &salt, iter_count, buf, length) >= 0);
/* Key sizes and output sizes less than 112-bit are not approved. */
- if (ikm.size < 14 || length < 14) {
+ if (ikm.size < 14 || length < 14 ||
+ !is_mac_algo_hmac_approved_in_fips(mac)) {
FIPS_POP_CONTEXT(NOT_APPROVED);
} else {
FIPS_POP_CONTEXT(APPROVED);
@@ -208,5 +229,12 @@ doit(void)
20,
"4b007901b765489abead49d926f721d065a429c1");
+ test_pbkdf2(GNUTLS_MAC_AES_CMAC_128,
+ "70617373776f726470617373776f7264", /* "passwordpassword" */
+ "73616c74", /* "salt" */
+ 4096,
+ 20,
+ "c4c112c6e1e3b8757640603dec78825ff87605a7");
+
gnutls_fips140_context_deinit(fips_context);
}
--
2.37.3

View File

@ -1,4 +1,3 @@
From 88808f0b8906bdc32579c144a2c44401ee97798a Mon Sep 17 00:00:00 2001
From: Daiki Ueno <ueno@gnu.org> From: Daiki Ueno <ueno@gnu.org>
Date: Fri, 19 Aug 2022 12:32:27 +0900 Date: Fri, 19 Aug 2022 12:32:27 +0900
Subject: [PATCH] build: allow GMP to be statically linked Subject: [PATCH] build: allow GMP to be statically linked
@ -17,17 +16,10 @@ and libhogweed in Nettle is also linked to the static library of GMP.
Signed-off-by: Daiki Ueno <ueno@gnu.org> Signed-off-by: Daiki Ueno <ueno@gnu.org>
--- ---
configure.ac | 14 +++++++++++++- diff --color -ruNp a/configure.ac b/configure.ac
lib/fips.c | 10 ++++++++++ --- a/configure.ac 2022-12-15 11:06:16.782726043 +0100
lib/fipshmac.c | 5 ++++- +++ b/configure.ac 2022-12-15 11:08:35.603451427 +0100
lib/global.c | 2 ++ @@ -744,6 +744,8 @@ AC_CHECK_FUNCS(nettle_cmac_kuznyechik_up
4 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index 96894b0be3..e4cf5eab81 100644
--- a/configure.ac
+++ b/configure.ac
@@ -742,6 +742,8 @@ AC_CHECK_FUNCS(nettle_cmac_kuznyechik_update)
LIBS=$save_LIBS LIBS=$save_LIBS
# Check sonames of the linked libraries needed for FIPS selftests. # Check sonames of the linked libraries needed for FIPS selftests.
@ -36,7 +28,7 @@ index 96894b0be3..e4cf5eab81 100644
save_LIBS=$LIBS save_LIBS=$LIBS
LIBS="$LIBS $GMP_LIBS" LIBS="$LIBS $GMP_LIBS"
AC_MSG_CHECKING([gmp soname]) AC_MSG_CHECKING([gmp soname])
@@ -755,9 +757,14 @@ if test -z "$gmp_so"; then @@ -757,9 +759,14 @@ if test -z "$gmp_so"; then
gmp_so=none gmp_so=none
fi fi
AC_MSG_RESULT($gmp_so) AC_MSG_RESULT($gmp_so)
@ -52,7 +44,7 @@ index 96894b0be3..e4cf5eab81 100644
save_LIBS=$LIBS save_LIBS=$LIBS
LIBS="$LIBS $NETTLE_LIBS" LIBS="$LIBS $NETTLE_LIBS"
AC_MSG_CHECKING([nettle soname]) AC_MSG_CHECKING([nettle soname])
@@ -773,7 +780,11 @@ fi @@ -775,7 +782,11 @@ fi
AC_MSG_RESULT($nettle_so) AC_MSG_RESULT($nettle_so)
AC_DEFINE_UNQUOTED([NETTLE_LIBRARY_SONAME], ["$nettle_so"], [The soname of nettle library]) AC_DEFINE_UNQUOTED([NETTLE_LIBRARY_SONAME], ["$nettle_so"], [The soname of nettle library])
LIBS=$save_LIBS LIBS=$save_LIBS
@ -64,7 +56,7 @@ index 96894b0be3..e4cf5eab81 100644
save_LIBS=$LIBS save_LIBS=$LIBS
LIBS="$LIBS $HOGWEED_LIBS" LIBS="$LIBS $HOGWEED_LIBS"
AC_MSG_CHECKING([hogweed soname]) AC_MSG_CHECKING([hogweed soname])
@@ -789,6 +800,7 @@ fi @@ -791,6 +802,7 @@ fi
AC_MSG_RESULT($hogweed_so) AC_MSG_RESULT($hogweed_so)
AC_DEFINE_UNQUOTED([HOGWEED_LIBRARY_SONAME], ["$hogweed_so"], [The soname of hogweed library]) AC_DEFINE_UNQUOTED([HOGWEED_LIBRARY_SONAME], ["$hogweed_so"], [The soname of hogweed library])
LIBS=$save_LIBS LIBS=$save_LIBS
@ -72,33 +64,42 @@ index 96894b0be3..e4cf5eab81 100644
gnutls_so=libgnutls.so.`expr "$LT_CURRENT" - "$LT_AGE"` gnutls_so=libgnutls.so.`expr "$LT_CURRENT" - "$LT_AGE"`
AC_DEFINE_UNQUOTED([GNUTLS_LIBRARY_SONAME], ["$gnutls_so"], [The soname of gnutls library]) AC_DEFINE_UNQUOTED([GNUTLS_LIBRARY_SONAME], ["$gnutls_so"], [The soname of gnutls library])
diff --git a/lib/fips.c b/lib/fips.c diff --color -ruNp a/lib/fips.c b/lib/fips.c
index 54eb4a37d4..42124ecf4e 100644 --- a/lib/fips.c 2022-12-15 11:06:16.868727731 +0100
--- a/lib/fips.c +++ b/lib/fips.c 2022-12-15 11:12:42.744303409 +0100
+++ b/lib/fips.c @@ -155,7 +155,11 @@ void _gnutls_fips_mode_reset_zombie(void
@@ -149,7 +149,11 @@ void _gnutls_fips_mode_reset_zombie(void)
#define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME #define GNUTLS_LIBRARY_NAME GNUTLS_LIBRARY_SONAME
#define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME #define NETTLE_LIBRARY_NAME NETTLE_LIBRARY_SONAME
#define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME #define HOGWEED_LIBRARY_NAME HOGWEED_LIBRARY_SONAME
+ +
+/* GMP can be statically linked. */ +/* GMP can be statically linked */
+#ifdef GMP_LIBRARY_SONAME +#ifdef GMP_LIBRARY_SONAME
#define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME #define GMP_LIBRARY_NAME GMP_LIBRARY_SONAME
+#endif +#endif
#define HMAC_SIZE 32 #define HMAC_SIZE 32
#define HMAC_ALGO GNUTLS_MAC_SHA256 #define HMAC_ALGO GNUTLS_MAC_SHA256
@@ -168,7 +172,9 @@ typedef struct @@ -173,7 +177,9 @@ struct hmac_file
struct hmac_entry gnutls; struct hmac_entry gnutls;
struct hmac_entry nettle; struct hmac_entry nettle;
struct hmac_entry hogweed; struct hmac_entry hogweed;
+#ifdef GMP_LIBRARY_SONAME +#ifdef GMP_LIBRARY_SONAME
struct hmac_entry gmp; struct hmac_entry gmp;
+#endif +#endif
} hmac_file; };
static int get_library_path(const char* lib, const char* symbol, char* path, size_t path_size) struct lib_paths
@@ -259,8 +265,10 @@ static int handler(void *user, const char *section, const char *name, const char @@ -181,7 +187,9 @@ struct lib_paths
char gnutls[GNUTLS_PATH_MAX];
char nettle[GNUTLS_PATH_MAX];
char hogweed[GNUTLS_PATH_MAX];
+#ifdef GMP_LIBRARY_SONAME
char gmp[GNUTLS_PATH_MAX];
+#endif
};
/*
@@ -245,8 +253,10 @@ static int handler(void *user, const cha
return lib_handler(&p->nettle, section, name, value); return lib_handler(&p->nettle, section, name, value);
} else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) { } else if (!strcmp(section, HOGWEED_LIBRARY_NAME)) {
return lib_handler(&p->hogweed, section, name, value); return lib_handler(&p->hogweed, section, name, value);
@ -109,42 +110,60 @@ index 54eb4a37d4..42124ecf4e 100644
} else { } else {
return 0; return 0;
} }
@@ -408,9 +416,11 @@ static int check_binary_integrity(void) @@ -389,8 +399,10 @@ static int callback(struct dl_phdr_info
ret = check_lib_hmac(&file.hogweed, HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u"); _gnutls_str_cpy(paths->nettle, GNUTLS_PATH_MAX, path);
else if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
_gnutls_str_cpy(paths->hogweed, GNUTLS_PATH_MAX, path);
+#ifdef GMP_LIBRARY_SONAME
else if (!strcmp(soname, GMP_LIBRARY_SONAME))
_gnutls_str_cpy(paths->gmp, GNUTLS_PATH_MAX, path);
+#endif
return 0;
}
@@ -411,10 +423,12 @@ static int load_lib_paths(struct lib_pat
_gnutls_debug_log("Hogweed library path was not found\n");
return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
}
+#ifdef GMP_LIBRARY_SONAME
if (paths->gmp[0] == '\0') {
_gnutls_debug_log("Gmp library path was not found\n");
return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
}
+#endif
return GNUTLS_E_SUCCESS;
}
@@ -467,9 +481,11 @@ static int check_binary_integrity(void)
ret = check_lib_hmac(&hmac.hogweed, paths.hogweed);
if (ret < 0) if (ret < 0)
return ret; return ret;
+#ifdef GMP_LIBRARY_SONAME +#ifdef GMP_LIBRARY_SONAME
ret = check_lib_hmac(&file.gmp, GMP_LIBRARY_NAME, "__gmpz_init"); ret = check_lib_hmac(&hmac.gmp, paths.gmp);
if (ret < 0) if (ret < 0)
return ret; return ret;
+#endif +#endif
return 0; return 0;
} }
diff --git a/lib/fipshmac.c b/lib/fipshmac.c diff --color -ruNp a/lib/fipshmac.c b/lib/fipshmac.c
index b091572bdf..363077f3e2 100644 --- a/lib/fipshmac.c 2022-12-15 11:06:16.785726102 +0100
--- a/lib/fipshmac.c +++ b/lib/fipshmac.c 2022-12-15 11:13:34.533320156 +0100
+++ b/lib/fipshmac.c @@ -107,8 +107,10 @@ static int callback(struct dl_phdr_info
@@ -159,10 +159,13 @@ int main(int argc, char **argv) return print_lib(path, soname);
ret = print_lib_dl(HOGWEED_LIBRARY_SONAME, "nettle_mpz_sizeinbase_256_u"); if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
if (ret < 0) return print_lib(path, soname);
return EXIT_FAILURE;
-
+
+ /* GMP can be statically linked. */
+#ifdef GMP_LIBRARY_SONAME +#ifdef GMP_LIBRARY_SONAME
ret = print_lib_dl(GMP_LIBRARY_SONAME, "__gmpz_init"); if (!strcmp(soname, GMP_LIBRARY_SONAME))
if (ret < 0) return print_lib(path, soname);
return EXIT_FAILURE;
+#endif +#endif
return 0;
return EXIT_SUCCESS;
} }
diff --git a/lib/global.c b/lib/global.c
index 1b372c15bd..9f3c7b22bd 100644 diff --color -ruNp a/lib/global.c b/lib/global.c
--- a/lib/global.c --- a/lib/global.c 2022-12-15 11:06:16.061711888 +0100
+++ b/lib/global.c +++ b/lib/global.c 2022-12-15 11:08:35.604451446 +0100
@@ -548,7 +548,9 @@ static const struct gnutls_library_config_st _gnutls_library_config[] = { @@ -540,7 +540,9 @@ static const struct gnutls_library_confi
{ "libgnutls-soname", GNUTLS_LIBRARY_SONAME }, { "libgnutls-soname", GNUTLS_LIBRARY_SONAME },
{ "libnettle-soname", NETTLE_LIBRARY_SONAME }, { "libnettle-soname", NETTLE_LIBRARY_SONAME },
{ "libhogweed-soname", HOGWEED_LIBRARY_SONAME }, { "libhogweed-soname", HOGWEED_LIBRARY_SONAME },
@ -154,6 +173,3 @@ index 1b372c15bd..9f3c7b22bd 100644
{ "hardware-features", HW_FEATURES }, { "hardware-features", HW_FEATURES },
{ "tls-features", TLS_FEATURES }, { "tls-features", TLS_FEATURES },
{ NULL, NULL } { NULL, NULL }
--
2.37.1

View File

@ -0,0 +1,433 @@
diff --color -ruNp a/doc/Makefile.am b/doc/Makefile.am
--- a/doc/Makefile.am 2022-11-15 14:14:10.632725399 +0100
+++ b/doc/Makefile.am 2022-11-15 14:14:40.252300863 +0100
@@ -575,6 +575,7 @@ ENUMS += enums/gnutls_certificate_verifi
ENUMS += enums/gnutls_certificate_verify_flags
ENUMS += enums/gnutls_channel_binding_t
ENUMS += enums/gnutls_cipher_algorithm_t
+ENUMS += enums/gnutls_cipher_flags_t
ENUMS += enums/gnutls_close_request_t
ENUMS += enums/gnutls_compression_method_t
ENUMS += enums/gnutls_credentials_type_t
@@ -882,12 +883,16 @@ FUNCS += functions/gnutls_cipher_decrypt
FUNCS += functions/gnutls_cipher_decrypt.short
FUNCS += functions/gnutls_cipher_decrypt2
FUNCS += functions/gnutls_cipher_decrypt2.short
+FUNCS += functions/gnutls_cipher_decrypt3
+FUNCS += functions/gnutls_cipher_decrypt3.short
FUNCS += functions/gnutls_cipher_deinit
FUNCS += functions/gnutls_cipher_deinit.short
FUNCS += functions/gnutls_cipher_encrypt
FUNCS += functions/gnutls_cipher_encrypt.short
FUNCS += functions/gnutls_cipher_encrypt2
FUNCS += functions/gnutls_cipher_encrypt2.short
+FUNCS += functions/gnutls_cipher_encrypt3
+FUNCS += functions/gnutls_cipher_encrypt3.short
FUNCS += functions/gnutls_cipher_get
FUNCS += functions/gnutls_cipher_get.short
FUNCS += functions/gnutls_cipher_get_block_size
diff --color -ruNp a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
--- a/doc/manpages/Makefile.am 2022-11-15 14:14:10.634725438 +0100
+++ b/doc/manpages/Makefile.am 2022-11-15 14:14:40.254300902 +0100
@@ -273,9 +273,11 @@ APIMANS += gnutls_check_version.3
APIMANS += gnutls_cipher_add_auth.3
APIMANS += gnutls_cipher_decrypt.3
APIMANS += gnutls_cipher_decrypt2.3
+APIMANS += gnutls_cipher_decrypt3.3
APIMANS += gnutls_cipher_deinit.3
APIMANS += gnutls_cipher_encrypt.3
APIMANS += gnutls_cipher_encrypt2.3
+APIMANS += gnutls_cipher_encrypt3.3
APIMANS += gnutls_cipher_get.3
APIMANS += gnutls_cipher_get_block_size.3
APIMANS += gnutls_cipher_get_id.3
diff --color -ruNp a/lib/crypto-api.c b/lib/crypto-api.c
--- a/lib/crypto-api.c 2022-11-15 14:14:11.036733248 +0100
+++ b/lib/crypto-api.c 2022-11-15 14:14:40.255300921 +0100
@@ -413,6 +413,166 @@ gnutls_cipher_decrypt2(gnutls_cipher_hd_
}
/**
+ * gnutls_cipher_encrypt3:
+ * @handle: is a #gnutls_cipher_hd_t type
+ * @ptext: the data to encrypt
+ * @ptext_len: the length of data to encrypt
+ * @ctext: the encrypted data
+ * @ctext_len: the length of encrypted data (initially must hold the maximum available size)
+ * @flags: flags for padding
+ *
+ * This function will encrypt the given data using the algorithm
+ * specified by the context. For block ciphers, @ptext_len is
+ * typically a multiple of the block size. If not, the caller can
+ * instruct the function to pad the last block according to @flags.
+ * Currently, the only available padding scheme is
+ * %GNUTLS_CIPHER_PADDING_PKCS7.
+ *
+ * If @ctext is not %NULL, it must hold enough space to store
+ * resulting cipher text. To check the required size, this function
+ * can be called with @ctext set to %NULL. Then @ctext_len will be
+ * updated without performing actual encryption.
+ *
+ * Returns: Zero or a negative error code on error.
+ *
+ * Since: 3.7.7
+ **/
+int
+gnutls_cipher_encrypt3(gnutls_cipher_hd_t handle,
+ const void *ptext, size_t ptext_len,
+ void *ctext, size_t *ctext_len,
+ unsigned flags)
+{
+ api_cipher_hd_st *h = handle;
+ const cipher_entry_st *e = h->ctx_enc.e;
+ int block_size = _gnutls_cipher_get_block_size(e);
+ int ret = 0;
+
+ if (unlikely(ctext_len == NULL)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+
+ if (_gnutls_cipher_type(e) == CIPHER_BLOCK &&
+ (flags & GNUTLS_CIPHER_PADDING_PKCS7)) {
+ size_t n, r;
+ uint8_t last_block[MAX_CIPHER_BLOCK_SIZE];
+ const uint8_t *p = ptext;
+ uint8_t *c = ctext;
+
+ if (!INT_ADD_OK(ptext_len, block_size, &n)) {
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ }
+
+ n = (n / block_size) * block_size;
+
+ if (!ctext) {
+ *ctext_len = n;
+ return 0;
+ }
+
+ if (*ctext_len < n) {
+ return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
+ }
+
+ /* Encrypt up to the last complete block */
+ r = ptext_len % block_size;
+
+ ret = _gnutls_cipher_encrypt2(&h->ctx_enc,
+ ptext, ptext_len - r,
+ ctext, ptext_len - r);
+ if (ret < 0) {
+ goto error;
+ }
+
+ /* Encrypt the last block with padding */
+ gnutls_memset(last_block, block_size - r, sizeof(last_block));
+ if (r > 0) {
+ memcpy(last_block, &p[ptext_len - r], r);
+ }
+ ret = _gnutls_cipher_encrypt2(&h->ctx_enc,
+ last_block, block_size,
+ &c[ptext_len - r], block_size);
+ if (ret < 0) {
+ goto error;
+ }
+ *ctext_len = n;
+ } else {
+ if (!ctext) {
+ *ctext_len = ptext_len;
+ return 0;
+ }
+
+ ret = _gnutls_cipher_encrypt2(&h->ctx_enc, ptext, ptext_len,
+ ctext, *ctext_len);
+ if (ret < 0) {
+ goto error;
+ }
+ *ctext_len = ptext_len;
+ }
+
+ error:
+ if (ret < 0) {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_ERROR);
+ } else {
+ _gnutls_switch_fips_state(GNUTLS_FIPS140_OP_APPROVED);
+ }
+ return ret;
+}
+
+/**
+ * gnutls_cipher_decrypt3:
+ * @handle: is a #gnutls_cipher_hd_t type
+ * @ctext: the data to decrypt
+ * @ctext_len: the length of data to decrypt
+ * @ptext: the decrypted data
+ * @ptext_len: the available length for decrypted data
+ * @flags: flags for padding
+ *
+ * This function will decrypt the given data using the algorithm
+ * specified by the context. If @flags is specified, padding for the
+ * decrypted data will be removed accordingly and @ptext_len will be
+ * updated.
+ *
+ * Returns: Zero or a negative error code on error.
+ *
+ * Since: 3.7.7
+ **/
+int
+gnutls_cipher_decrypt3(gnutls_cipher_hd_t handle,
+ const void *ctext, size_t ctext_len,
+ void *ptext, size_t *ptext_len,
+ unsigned flags)
+{
+ api_cipher_hd_st *h = handle;
+ int ret;
+
+ ret = gnutls_cipher_decrypt2(handle,
+ ctext, ctext_len,
+ ptext, *ptext_len);
+ if (ret < 0) {
+ return ret;
+ }
+
+ if (_gnutls_cipher_type(h->ctx_enc.e) == CIPHER_BLOCK &&
+ (flags & GNUTLS_CIPHER_PADDING_PKCS7)) {
+ uint8_t *p = ptext;
+ uint8_t padding = p[*ptext_len - 1];
+ if (!padding || padding > _gnutls_cipher_get_block_size(h->ctx_enc.e)) {
+ return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
+ }
+ /* Check that the prior bytes are all PADDING */
+ for (size_t i = *ptext_len - padding; i < *ptext_len; i++) {
+ if (padding != p[*ptext_len - 1]) {
+ return gnutls_assert_val(GNUTLS_E_DECRYPTION_FAILED);
+ }
+ }
+ *ptext_len -= padding;
+ }
+
+ return 0;
+}
+
+/**
* gnutls_cipher_deinit:
* @handle: is a #gnutls_cipher_hd_t type
*
diff --color -ruNp a/lib/includes/gnutls/crypto.h b/lib/includes/gnutls/crypto.h
--- a/lib/includes/gnutls/crypto.h 2022-05-10 13:57:43.000000000 +0200
+++ b/lib/includes/gnutls/crypto.h 2022-11-15 14:14:40.256300941 +0100
@@ -49,6 +49,28 @@ int gnutls_cipher_encrypt2(gnutls_cipher
const void *text, size_t textlen,
void *ciphertext, size_t ciphertextlen);
+/**
+ * gnutls_cipher_flags_t:
+ * @GNUTLS_CIPHER_PADDING_PKCS7: Flag to indicate PKCS#7 padding
+ *
+ * Enumeration of flags to control block cipher padding, used by
+ * gnutls_cipher_encrypt3() and gnutls_cipher_decrypt3().
+ *
+ * Since: 3.7.7
+ */
+typedef enum gnutls_cipher_flags_t {
+ GNUTLS_CIPHER_PADDING_PKCS7 = 1
+} gnutls_cipher_flags_t;
+
+int gnutls_cipher_encrypt3(gnutls_cipher_hd_t handle,
+ const void *ptext, size_t ptext_len,
+ void *ctext, size_t *ctext_len,
+ unsigned flags);
+int gnutls_cipher_decrypt3(gnutls_cipher_hd_t handle,
+ const void *ctext, size_t ctext_len,
+ void *ptext, size_t *ptext_len,
+ unsigned flags);
+
void gnutls_cipher_set_iv(gnutls_cipher_hd_t handle, void *iv,
size_t ivlen);
diff --color -ruNp a/lib/libgnutls.map b/lib/libgnutls.map
--- a/lib/libgnutls.map 2022-11-15 14:14:11.142735308 +0100
+++ b/lib/libgnutls.map 2022-11-15 14:14:40.256300941 +0100
@@ -1403,6 +1403,8 @@ GNUTLS_3_7_7
{
global:
gnutls_fips140_run_self_tests;
+ gnutls_cipher_encrypt3;
+ gnutls_cipher_decrypt3;
local:
*;
} GNUTLS_3_7_5;
diff --color -ruNp a/tests/cipher-padding.c b/tests/cipher-padding.c
--- a/tests/cipher-padding.c 1970-01-01 01:00:00.000000000 +0100
+++ b/tests/cipher-padding.c 2022-11-15 14:14:40.258300980 +0100
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ *
+ */
+
+#include <config.h>
+
+#include <gnutls/crypto.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "utils.h"
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "<%d>| %s", level, str);
+}
+
+#define CLAMP(x, b) (((x) + (b)) / (b)) * (b)
+
+static void
+start(gnutls_cipher_algorithm_t algo, size_t plaintext_size, unsigned int flags)
+{
+ int ret;
+ gnutls_cipher_hd_t ch;
+ uint8_t key16[64];
+ uint8_t iv16[32];
+ uint8_t plaintext[128];
+ uint8_t ciphertext[128];
+ size_t block_size;
+ size_t size;
+ gnutls_datum_t key, iv;
+
+ success("%s %zu %u\n",
+ gnutls_cipher_get_name(algo), plaintext_size, flags);
+
+ block_size = gnutls_cipher_get_block_size(algo);
+
+ key.data = key16;
+ key.size = gnutls_cipher_get_key_size(algo);
+ assert(key.size <= sizeof(key16));
+
+ iv.data = iv16;
+ iv.size = gnutls_cipher_get_iv_size(algo);
+ assert(iv.size <= sizeof(iv16));
+
+ memset(iv.data, 0xff, iv.size);
+ memset(key.data, 0xfe, key.size);
+ memset(plaintext, 0xfa, sizeof(plaintext));
+
+ ret = gnutls_cipher_init(&ch, algo, &key, &iv);
+ if (ret < 0) {
+ fail("gnutls_cipher_init failed\n");
+ }
+
+ /* Check overflow if PKCS#7 is requested */
+ if (flags & GNUTLS_CIPHER_PADDING_PKCS7) {
+ ret = gnutls_cipher_encrypt3(ch,
+ plaintext, SIZE_MAX,
+ NULL, &size,
+ flags);
+ if (ret != GNUTLS_E_INVALID_REQUEST) {
+ fail("gnutls_cipher_encrypt3 succeeded\n");
+ }
+ }
+
+ /* Get the ciphertext size */
+ ret = gnutls_cipher_encrypt3(ch,
+ plaintext, plaintext_size,
+ NULL, &size,
+ flags);
+ if (ret < 0) {
+ fail("gnutls_cipher_encrypt3 failed\n");
+ }
+
+ if (flags & GNUTLS_CIPHER_PADDING_PKCS7) {
+ if (size <= plaintext_size) {
+ fail("no padding appended\n");
+ }
+ if (size != CLAMP(plaintext_size, block_size)) {
+ fail("size does not match: %zu (expected %zu)\n",
+ size, CLAMP(plaintext_size, block_size));
+ }
+ } else {
+ if (size != plaintext_size) {
+ fail("size does not match: %zu (expected %zu)\n",
+ size, plaintext_size);
+ }
+ }
+
+ /* Encrypt with padding */
+ ret = gnutls_cipher_encrypt3(ch,
+ plaintext, plaintext_size,
+ ciphertext, &size,
+ flags);
+ if (ret < 0) {
+ fail("gnutls_cipher_encrypt3 failed\n");
+ }
+
+ /* Decrypt with padding */
+ ret = gnutls_cipher_decrypt3(ch,
+ ciphertext, size,
+ ciphertext, &size,
+ flags);
+ if (ret < 0) {
+ fail("gnutls_cipher_encrypt3 failed\n");
+ }
+
+ if (size != plaintext_size) {
+ fail("size does not match: %zu (expected %zu)\n",
+ size, plaintext_size);
+ }
+
+ if (memcmp(ciphertext, plaintext, size) != 0) {
+ fail("plaintext does not match\n");
+ }
+
+ gnutls_cipher_deinit(ch);
+}
+
+void doit(void) {
+ int ret;
+
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug) {
+ gnutls_global_set_log_level(4711);
+ }
+
+ ret = global_init();
+ if (ret < 0) {
+ fail("Cannot initialize library\n");
+ }
+
+ start(GNUTLS_CIPHER_AES_128_CBC, 0, GNUTLS_CIPHER_PADDING_PKCS7);
+ start(GNUTLS_CIPHER_AES_128_CBC, 11, GNUTLS_CIPHER_PADDING_PKCS7);
+ start(GNUTLS_CIPHER_AES_128_CBC, 77, GNUTLS_CIPHER_PADDING_PKCS7);
+ start(GNUTLS_CIPHER_AES_128_CBC, 80, GNUTLS_CIPHER_PADDING_PKCS7);
+
+ start(GNUTLS_CIPHER_AES_128_CBC, 0, 0);
+ start(GNUTLS_CIPHER_AES_128_CBC, 80, 0);
+
+ gnutls_global_deinit();
+}
diff --color -ruNp a/tests/Makefile.am b/tests/Makefile.am
--- a/tests/Makefile.am 2022-11-15 14:14:11.144735347 +0100
+++ b/tests/Makefile.am 2022-11-15 14:14:40.257300960 +0100
@@ -233,7 +233,7 @@ ctests += mini-record-2 simple gnutls_hm
tls13-without-timeout-func buffer status-request-revoked \
set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
- x509-upnconstraint xts-key-check pkcs7-verify-double-free \
+ x509-upnconstraint cipher-padding xts-key-check pkcs7-verify-double-free \
fips-rsa-sizes tls12-rehandshake-ticket
ctests += tls-channel-binding

View File

@ -0,0 +1,215 @@
diff --color -ruNp a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
--- a/lib/ext/session_ticket.c 2022-05-10 13:55:00.000000000 +0200
+++ b/lib/ext/session_ticket.c 2022-11-15 13:30:20.491830382 +0100
@@ -624,6 +624,12 @@ gnutls_session_ticket_enable_server(gnut
return 0;
}
+void
+_gnutls_session_ticket_disable_server(gnutls_session_t session)
+{
+ session->internals.flags |= GNUTLS_NO_TICKETS;
+}
+
/*
* Return zero if session tickets haven't been enabled.
*/
diff --color -ruNp a/lib/ext/session_ticket.h b/lib/ext/session_ticket.h
--- a/lib/ext/session_ticket.h 2022-02-22 15:34:48.000000000 +0100
+++ b/lib/ext/session_ticket.h 2022-11-15 13:30:20.491830382 +0100
@@ -36,5 +36,6 @@ int _gnutls_encrypt_session_ticket(gnutl
int _gnutls_decrypt_session_ticket(gnutls_session_t session,
const gnutls_datum_t *ticket_data,
gnutls_datum_t *state);
+void _gnutls_session_ticket_disable_server(gnutls_session_t session);
#endif /* GNUTLS_LIB_EXT_SESSION_TICKET_H */
diff --color -ruNp a/lib/libgnutls.map b/lib/libgnutls.map
--- a/lib/libgnutls.map 2022-11-15 13:12:57.781688194 +0100
+++ b/lib/libgnutls.map 2022-11-15 13:30:20.492830401 +0100
@@ -1510,4 +1510,6 @@ GNUTLS_PRIVATE_3_4 {
_gnutls_buffer_clear;
# needed by tests/cipher-alignment
_gnutls_crypto_register_cipher;
+ # needed by tests/tls12-rehandshake-cert-ticket
+ _gnutls_session_ticket_disable_server;
} GNUTLS_3_4;
diff --color -ruNp a/lib/state.c b/lib/state.c
--- a/lib/state.c 2022-05-16 17:10:08.000000000 +0200
+++ b/lib/state.c 2022-11-15 13:30:20.493830420 +0100
@@ -545,6 +545,7 @@ void _gnutls_handshake_internal_state_cl
session->internals.tfo.connect_addrlen = 0;
session->internals.tfo.connect_only = 0;
session->internals.early_data_received = 0;
+ session->internals.session_ticket_renew = 0;
}
/**
diff --color -ruNp a/tests/Makefile.am b/tests/Makefile.am
--- a/tests/Makefile.am 2022-11-15 13:12:58.209696462 +0100
+++ b/tests/Makefile.am 2022-11-15 13:30:20.494830440 +0100
@@ -234,7 +234,7 @@ ctests += mini-record-2 simple gnutls_hm
set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
x509-upnconstraint xts-key-check pkcs7-verify-double-free \
- fips-rsa-sizes
+ fips-rsa-sizes tls12-rehandshake-ticket
ctests += tls-channel-binding
diff --color -ruNp a/tests/tls12-rehandshake-ticket.c b/tests/tls12-rehandshake-ticket.c
--- a/tests/tls12-rehandshake-ticket.c 1970-01-01 01:00:00.000000000 +0100
+++ b/tests/tls12-rehandshake-ticket.c 2022-11-15 13:30:20.495830459 +0100
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author: Daiki Ueno
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gnutls/gnutls.h>
+#include <assert.h>
+#include "cert-common.h"
+
+#include "utils.h"
+#include "eagain-common.h"
+
+const char *side = "";
+
+static void tls_log_func(int level, const char *str)
+{
+ fprintf(stderr, "%s|<%d>| %s", side, level, str);
+}
+
+#define MAX_BUF 1024
+
+void _gnutls_session_ticket_disable_server(gnutls_session_t session);
+
+static void run(void)
+{
+ char buffer[MAX_BUF + 1];
+ /* Server stuff. */
+ gnutls_certificate_credentials_t scred;
+ gnutls_session_t server;
+ gnutls_datum_t session_ticket_key = { NULL, 0 };
+ int sret;
+ /* Client stuff. */
+ gnutls_certificate_credentials_t ccred;
+ gnutls_session_t client;
+ int cret;
+
+ /* General init. */
+ global_init();
+ gnutls_global_set_log_function(tls_log_func);
+ if (debug)
+ gnutls_global_set_log_level(9);
+
+ /* Init server */
+ assert(gnutls_certificate_allocate_credentials(&scred) >= 0);
+ assert(gnutls_certificate_set_x509_key_mem(scred,
+ &server_ca3_localhost_cert,
+ &server_ca3_key,
+ GNUTLS_X509_FMT_PEM) >= 0);
+ assert(gnutls_certificate_set_x509_trust_mem(scred,
+ &ca3_cert,
+ GNUTLS_X509_FMT_PEM) >= 0);
+
+ assert(gnutls_init(&server, GNUTLS_SERVER) >= 0);
+ gnutls_certificate_server_set_request(server, GNUTLS_CERT_REQUEST);
+ assert(gnutls_priority_set_direct(server,
+ "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+VERS-TLS1.2",
+ NULL) >= 0);
+
+ gnutls_credentials_set(server, GNUTLS_CRD_CERTIFICATE, scred);
+ gnutls_transport_set_push_function(server, server_push);
+ gnutls_transport_set_pull_function(server, server_pull);
+ gnutls_transport_set_ptr(server, server);
+
+ gnutls_session_ticket_key_generate(&session_ticket_key);
+ gnutls_session_ticket_enable_server(server, &session_ticket_key);
+
+ /* Init client */
+ assert(gnutls_certificate_allocate_credentials(&ccred) >= 0);
+ assert(gnutls_certificate_set_x509_key_mem
+ (ccred, &cli_ca3_cert_chain, &cli_ca3_key, GNUTLS_X509_FMT_PEM) >= 0);
+ assert(gnutls_certificate_set_x509_trust_mem
+ (ccred, &ca3_cert, GNUTLS_X509_FMT_PEM) >= 0);
+
+ gnutls_init(&client, GNUTLS_CLIENT);
+ assert(gnutls_priority_set_direct(client,
+ "NORMAL:-VERS-TLS-ALL:+VERS-TLS1.1:+VERS-TLS1.2",
+ NULL) >= 0);
+
+ assert(gnutls_credentials_set(client, GNUTLS_CRD_CERTIFICATE, ccred) >= 0);
+
+ gnutls_transport_set_push_function(client, client_push);
+ gnutls_transport_set_pull_function(client, client_pull);
+ gnutls_transport_set_ptr(client, client);
+
+ HANDSHAKE(client, server);
+
+ /* Server initiates rehandshake */
+ switch_side("server");
+ sret = gnutls_rehandshake(server);
+ if (sret < 0) {
+ fail("Error sending %d byte packet: %s\n",
+ (int)sizeof(buffer), gnutls_strerror(sret));
+ } else if (debug)
+ success("server: starting rehandshake\n");
+
+ /* Stop sending session ticket */
+ _gnutls_session_ticket_disable_server(server);
+
+ /* Client gets notified with rehandshake */
+ switch_side("client");
+ do {
+ do {
+ cret = gnutls_record_recv(client, buffer, MAX_BUF);
+ } while (cret == GNUTLS_E_AGAIN || cret == GNUTLS_E_INTERRUPTED);
+ } while (cret > 0);
+
+ if (cret != GNUTLS_E_REHANDSHAKE) {
+ fail("client: Error receiving rehandshake: %s\n",
+ gnutls_strerror(cret));
+ }
+
+ HANDSHAKE(client, server);
+
+ gnutls_bye(client, GNUTLS_SHUT_WR);
+ gnutls_bye(server, GNUTLS_SHUT_WR);
+
+ gnutls_deinit(client);
+ gnutls_deinit(server);
+
+ gnutls_certificate_free_credentials(scred);
+ gnutls_certificate_free_credentials(ccred);
+
+ gnutls_free(session_ticket_key.data);
+
+ gnutls_global_deinit();
+ reset_buffers();
+}
+
+void doit(void)
+{
+ run();
+}

View File

@ -0,0 +1,58 @@
From 51b721b69fd08ef1c4c4989f5e12b643e170ff56 Mon Sep 17 00:00:00 2001
From: Pedro Monreal <pmgdeb@gmail.com>
Date: Thu, 16 Feb 2023 17:02:38 +0100
Subject: [PATCH] pk: extend pair-wise consistency to cover DH key generation
Perform SP800 56A (rev 3) 5.6.2.1.4 Owner Assurance of Pair-wise
Consistency check, even if we only support ephemeral DH, as it is
required by FIPS 140-3 IG 10.3.A.
Signed-off-by: Pedro Monreal <pmgdeb@gmail.com>
Co-authored-by: Daiki Ueno <ueno@gnu.org>
---
lib/nettle/pk.c | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index d30bca594f..bd9c1b4c74 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -2642,6 +2642,35 @@ static int pct_test(gnutls_pk_algorithm_t algo,
}
break;
case GNUTLS_PK_DH:
+ {
+ mpz_t y;
+
+ /* Perform SP800 56A (rev 3) 5.6.2.1.4 Owner Assurance
+ * of Pair-wise Consistency check, even if we only
+ * support ephemeral DH, as it is required by FIPS
+ * 140-3 IG 10.3.A.
+ *
+ * Use the private key, x, along with the generator g
+ * and prime modulus p included in the domain
+ * parameters associated with the key pair to compute
+ * g^x mod p. Compare the result to the public key, y.
+ */
+ mpz_init(y);
+ mpz_powm(y,
+ TOMPZ(params->params[DSA_G]),
+ TOMPZ(params->params[DSA_X]),
+ TOMPZ(params->params[DSA_P]));
+ if (unlikely
+ (mpz_cmp(y, TOMPZ(params->params[DSA_Y])) != 0)) {
+ ret =
+ gnutls_assert_val
+ (GNUTLS_E_PK_GENERATION_ERROR);
+ mpz_clear(y);
+ goto cleanup;
+ }
+ mpz_clear(y);
+ break;
+ }
case GNUTLS_PK_ECDH_X25519:
case GNUTLS_PK_ECDH_X448:
ret = 0;
--
2.39.2

View File

@ -0,0 +1,54 @@
diff --color -ruNp a/lib/fips.c b/lib/fips.c
--- a/lib/fips.c 2022-11-15 16:10:56.183185457 +0100
+++ b/lib/fips.c 2022-11-15 16:10:23.488530716 +0100
@@ -360,11 +360,6 @@ static int check_lib_hmac(struct hmac_en
return gnutls_assert_val(ret);
}
- if (strncmp(entry->path, path, GNUTLS_PATH_MAX)) {
- _gnutls_debug_log("Library path for %s does not match with HMAC file\n", lib);
- return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- }
-
_gnutls_debug_log("Loading: %s\n", path);
ret = gnutls_load_file(path, &data);
if (ret < 0) {
diff --color -ruNp a/lib/fipshmac.c b/lib/fipshmac.c
--- a/lib/fipshmac.c 2022-11-15 16:10:56.183185457 +0100
+++ b/lib/fipshmac.c 2022-11-15 16:10:23.489530737 +0100
@@ -102,20 +102,30 @@ static int get_hmac(const char *path, ch
static int print_lib_path(const char *path)
{
int ret;
+ char *real_path = NULL;
char hmac[HMAC_STR_SIZE];
- ret = get_hmac(path, hmac, sizeof(hmac));
+ real_path = canonicalize_file_name(path);
+ if (real_path == NULL) {
+ fprintf(stderr, "Could not get realpath from %s\n", path);
+ ret = GNUTLS_E_FILE_ERROR;
+ goto cleanup;
+ }
+
+ ret = get_hmac(real_path, hmac, sizeof(hmac));
if (ret < 0) {
fprintf(stderr, "Could not calculate HMAC for %s: %s\n",
- last_component(path), gnutls_strerror(ret));
- return ret;
+ last_component(real_path), gnutls_strerror(ret));
+ goto cleanup;
}
printf("[%s]\n", last_component(path));
- printf("path = %s\n", path);
+ printf("path = %s\n", real_path);
printf("hmac = %s\n", hmac);
- return 0;
+cleanup:
+ free(real_path);
+ return ret;
}
static int print_lib_dl(const char *lib, const char *sym)

View File

@ -0,0 +1,534 @@
diff --color -ruNp a/configure.ac b/configure.ac
--- a/configure.ac 2022-05-27 09:17:26.000000000 +0200
+++ b/configure.ac 2022-12-15 11:00:18.830698584 +0100
@@ -619,6 +619,8 @@ if [ test "$enable_fips" = "yes" ];then
if test "x$fips_module_version" != xnone; then
AC_DEFINE_UNQUOTED([FIPS_MODULE_VERSION], ["$fips_module_version"], [The FIPS140 module version])
fi
+
+ AC_CHECK_FUNCS(dl_iterate_phdr)
else
enable_fips=no
AC_MSG_WARN([[
diff --color -ruNp a/lib/fips.c b/lib/fips.c
--- a/lib/fips.c 2022-12-15 10:59:57.460279029 +0100
+++ b/lib/fips.c 2022-12-15 11:00:18.831698604 +0100
@@ -23,9 +23,11 @@
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <unistd.h>
+#include "dirname.h"
#include "errors.h"
#include "file.h"
#include "inih/ini.h"
+#include "str.h"
#include <fips.h>
#include <gnutls/self-test.h>
#include <stdio.h>
@@ -34,6 +36,10 @@
#include "gthreads.h"
+#ifdef HAVE_DL_ITERATE_PHDR
+#include <link.h>
+#endif
+
unsigned int _gnutls_lib_state = LIB_STATE_POWERON;
struct gnutls_fips140_context_st {
@@ -153,7 +159,6 @@ void _gnutls_fips_mode_reset_zombie(void
#define HMAC_SIZE 32
#define HMAC_ALGO GNUTLS_MAC_SHA256
-#define HMAC_FILE_NAME ".gnutls.hmac"
#define HMAC_FORMAT_VERSION 1
struct hmac_entry
@@ -162,51 +167,32 @@ struct hmac_entry
uint8_t hmac[HMAC_SIZE];
};
-typedef struct
+struct hmac_file
{
int version;
struct hmac_entry gnutls;
struct hmac_entry nettle;
struct hmac_entry hogweed;
struct hmac_entry gmp;
-} hmac_file;
+};
-static int get_library_path(const char* lib, const char* symbol, char* path, size_t path_size)
+struct lib_paths
{
- int ret;
- void *dl, *sym;
- Dl_info info;
-
- dl = dlopen(lib, RTLD_LAZY);
- if (dl == NULL)
- return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
-
- sym = dlsym(dl, symbol);
- if (sym == NULL) {
- ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
- goto cleanup;
- }
-
- ret = dladdr(sym, &info);
- if (ret == 0) {
- ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
- goto cleanup;
- }
-
- ret = snprintf(path, path_size, "%s", info.dli_fname);
- if ((size_t)ret >= path_size) {
- ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
- goto cleanup;
- }
-
- ret = 0;
-cleanup:
- dlclose(dl);
- return ret;
-}
+ char gnutls[GNUTLS_PATH_MAX];
+ char nettle[GNUTLS_PATH_MAX];
+ char hogweed[GNUTLS_PATH_MAX];
+ char gmp[GNUTLS_PATH_MAX];
+};
-/* Parses hmac data and copies hex value into dest.
+/*
+ * get_hmac:
+ * @dest: buffer for the hex value
+ * @value: hmac value
+ *
+ * Parses hmac data and copies hex value into dest.
* dest must point to at least HMAC_SIZE amount of memory
+ *
+ * Returns: 0 on success, a negative error code otherwise
*/
static int get_hmac(uint8_t *dest, const char *value)
{
@@ -245,7 +231,7 @@ lib_handler(struct hmac_entry *entry,
static int handler(void *user, const char *section, const char *name, const char *value)
{
- hmac_file *p = (hmac_file *)user;
+ struct hmac_file *p = (struct hmac_file *)user;
if (!strcmp(section, "global")) {
if (!strcmp(name, "format-version")) {
@@ -267,24 +253,29 @@ static int handler(void *user, const cha
return 1;
}
-static int get_hmac_path(char *mac_file, size_t mac_file_size)
+/*
+ * get_hmac_path:
+ * @mac_file: buffer where the hmac file path will be written to
+ * @mac_file_size: size of the mac_file buffer
+ * @gnutls_path: path to the gnutls library, used to deduce hmac file path
+ *
+ * Deduces hmac file path from the gnutls library path.
+ *
+ * Returns: 0 on success, a negative error code otherwise
+ */
+static int get_hmac_path(char *mac_file, size_t mac_file_size, const char *gnutls_path)
{
int ret;
char *p;
- char file[GNUTLS_PATH_MAX];
- ret = get_library_path(GNUTLS_LIBRARY_NAME, "gnutls_global_init",
- file, sizeof(file));
- if (ret < 0)
- return ret;
-
- p = strrchr(file, '/');
+ p = strrchr(gnutls_path, '/');
if (p == NULL)
- ret = snprintf(mac_file, mac_file_size, HMAC_FILE_NAME);
+ ret = snprintf(mac_file, mac_file_size, ".%s.hmac", gnutls_path);
else
- ret = snprintf(mac_file, mac_file_size,
- "%.*s/"HMAC_FILE_NAME, (int)(p - file), file);
+ ret = snprintf(mac_file, mac_file_size, "%.*s/.%s.hmac",
+ (int)(p - gnutls_path), gnutls_path, p + 1);
+
if ((size_t)ret >= mac_file_size)
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
@@ -293,10 +284,11 @@ static int get_hmac_path(char *mac_file,
return GNUTLS_E_SUCCESS;
if (p == NULL)
- ret = snprintf(mac_file, mac_file_size, "fipscheck/"HMAC_FILE_NAME);
+ ret = snprintf(mac_file, mac_file_size, "fipscheck/.%s.hmac", gnutls_path);
else
- ret = snprintf(mac_file, mac_file_size,
- "%.*s/fipscheck/"HMAC_FILE_NAME, (int)(p - file), file);
+ ret = snprintf(mac_file, mac_file_size, "%.*s/fipscheck/.%s.hmac",
+ (int)(p - gnutls_path), gnutls_path, p + 1);
+
if ((size_t)ret >= mac_file_size)
return gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
@@ -307,51 +299,52 @@ static int get_hmac_path(char *mac_file,
return GNUTLS_E_FILE_ERROR;
}
-static int load_hmac_file(hmac_file *p)
+/*
+ * load_hmac_file:
+ * @hmac_file: hmac file structure
+ * @hmac_path: path to the hmac file
+ *
+ * Loads the hmac file into the hmac file structure.
+ *
+ * Returns: 0 on success, a negative error code otherwise
+ */
+static int load_hmac_file(struct hmac_file *hmac_file, const char *hmac_path)
{
int ret;
FILE *stream;
- char hmac_path[GNUTLS_PATH_MAX];
-
- ret = get_hmac_path(hmac_path, sizeof(hmac_path));
- if (ret < 0)
- return gnutls_assert_val(ret);
stream = fopen(hmac_path, "r");
if (stream == NULL)
return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
- gnutls_memset(p, 0, sizeof(*p));
- ret = ini_parse_file(stream, handler, p);
+ gnutls_memset(hmac_file, 0, sizeof(*hmac_file));
+ ret = ini_parse_file(stream, handler, hmac_file);
fclose(stream);
if (ret < 0)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- if (p->version != HMAC_FORMAT_VERSION)
+ if (hmac_file->version != HMAC_FORMAT_VERSION)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
return 0;
}
-/* Run an HMAC using the key above on the library binary data.
- * Returns 0 on success and negative value on error.
+/*
+ * check_lib_hmac:
+ * @entry: hmac file entry
+ * @path: path to the library which hmac should be compared
+ *
+ * Verify that HMAC from hmac file entry matches HMAC of given library.
+ *
+ * Returns: 0 on successful HMAC verification, a negative error code otherwise
*/
-static int check_lib_hmac(struct hmac_entry *entry,
- const char *lib, const char *sym)
+static int check_lib_hmac(struct hmac_entry *entry, const char *path)
{
int ret;
unsigned prev;
- char path[GNUTLS_PATH_MAX];
uint8_t hmac[HMAC_SIZE];
gnutls_datum_t data;
- ret = get_library_path(lib, sym, path, sizeof(path));
- if (ret < 0) {
- _gnutls_debug_log("Could not get lib path for %s: %s\n",
- lib, gnutls_strerror(ret));
- return gnutls_assert_val(ret);
- }
-
_gnutls_debug_log("Loading: %s\n", path);
ret = gnutls_load_file(path, &data);
if (ret < 0) {
@@ -382,28 +375,99 @@ static int check_lib_hmac(struct hmac_en
return 0;
}
+#ifdef HAVE_DL_ITERATE_PHDR
+
+static int callback(struct dl_phdr_info *info, size_t size, void *data)
+{
+ const char *path = info->dlpi_name;
+ const char *soname = last_component(path);
+ struct lib_paths *paths = (struct lib_paths *)data;
+
+ if (!strcmp(soname, GNUTLS_LIBRARY_SONAME))
+ _gnutls_str_cpy(paths->gnutls, GNUTLS_PATH_MAX, path);
+ else if (!strcmp(soname, NETTLE_LIBRARY_SONAME))
+ _gnutls_str_cpy(paths->nettle, GNUTLS_PATH_MAX, path);
+ else if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
+ _gnutls_str_cpy(paths->hogweed, GNUTLS_PATH_MAX, path);
+ else if (!strcmp(soname, GMP_LIBRARY_SONAME))
+ _gnutls_str_cpy(paths->gmp, GNUTLS_PATH_MAX, path);
+ return 0;
+}
+
+static int load_lib_paths(struct lib_paths *paths)
+{
+ memset(paths, 0, sizeof(*paths));
+ dl_iterate_phdr(callback, paths);
+
+ if (paths->gnutls[0] == '\0') {
+ _gnutls_debug_log("Gnutls library path was not found\n");
+ return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
+ }
+ if (paths->nettle[0] == '\0') {
+ _gnutls_debug_log("Nettle library path was not found\n");
+ return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
+ }
+ if (paths->hogweed[0] == '\0') {
+ _gnutls_debug_log("Hogweed library path was not found\n");
+ return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
+ }
+ if (paths->gmp[0] == '\0') {
+ _gnutls_debug_log("Gmp library path was not found\n");
+ return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
+ }
+
+ return GNUTLS_E_SUCCESS;
+}
+
+#else
+
+static int load_lib_paths(struct lib_paths *paths)
+{
+ (void)paths;
+ _gnutls_debug_log("Function dl_iterate_phdr is missing\n");
+ return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+}
+
+#endif /* HAVE_DL_ITERATE_PHDR */
+
static int check_binary_integrity(void)
{
int ret;
- hmac_file file;
+ struct lib_paths paths;
+ struct hmac_file hmac;
+ char hmac_path[GNUTLS_PATH_MAX];
+
+ ret = load_lib_paths(&paths);
+ if (ret < 0) {
+ _gnutls_debug_log("Could not load library paths: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
+
+ ret = get_hmac_path(hmac_path, sizeof(hmac_path), paths.gnutls);
+ if (ret < 0) {
+ _gnutls_debug_log("Could not get hmac file path: %s\n",
+ gnutls_strerror(ret));
+ return ret;
+ }
- ret = load_hmac_file(&file);
+ ret = load_hmac_file(&hmac, hmac_path);
if (ret < 0) {
_gnutls_debug_log("Could not load hmac file: %s\n",
gnutls_strerror(ret));
return ret;
}
- ret = check_lib_hmac(&file.gnutls, GNUTLS_LIBRARY_NAME, "gnutls_global_init");
+ ret = check_lib_hmac(&hmac.gnutls, paths.gnutls);
if (ret < 0)
return ret;
- ret = check_lib_hmac(&file.nettle, NETTLE_LIBRARY_NAME, "nettle_aes_set_encrypt_key");
+ ret = check_lib_hmac(&hmac.nettle, paths.nettle);
if (ret < 0)
return ret;
- ret = check_lib_hmac(&file.hogweed, HOGWEED_LIBRARY_NAME, "nettle_mpz_sizeinbase_256_u");
+ ret = check_lib_hmac(&hmac.hogweed, paths.hogweed);
if (ret < 0)
return ret;
- ret = check_lib_hmac(&file.gmp, GMP_LIBRARY_NAME, "__gmpz_init");
+ ret = check_lib_hmac(&hmac.gmp, paths.gmp);
if (ret < 0)
return ret;
diff --color -ruNp a/lib/fipshmac.c b/lib/fipshmac.c
--- a/lib/fipshmac.c 2022-12-15 10:59:57.461279049 +0100
+++ b/lib/fipshmac.c 2022-12-15 11:00:18.832698623 +0100
@@ -22,12 +22,14 @@
#include "config.h"
-#include <gnutls/gnutls.h>
-#include <gnutls/crypto.h>
-#include <dlfcn.h>
-#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
+
+#ifdef HAVE_DL_ITERATE_PHDR
+
+#include <gnutls/gnutls.h>
+#include <gnutls/crypto.h>
+#include <link.h>
#include "dirname.h"
#include "errors.h"
@@ -36,40 +38,6 @@
#define HMAC_ALGO GNUTLS_MAC_SHA256
#define HMAC_STR_SIZE (2 * HMAC_SIZE + 1)
-static int get_path(const char *lib, const char *symbol, char *path, size_t path_size)
-{
- int ret;
- void *dl, *sym;
- Dl_info info;
-
- dl = dlopen(lib, RTLD_LAZY);
- if (dl == NULL)
- return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
-
- sym = dlsym(dl, symbol);
- if (sym == NULL) {
- ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
- goto cleanup;
- }
-
- ret = dladdr(sym, &info);
- if (ret == 0) {
- ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
- goto cleanup;
- }
-
- ret = snprintf(path, path_size, "%s", info.dli_fname);
- if ((size_t)ret >= path_size) {
- ret = gnutls_assert_val(GNUTLS_E_SHORT_MEMORY_BUFFER);
- goto cleanup;
- }
-
- ret = 0;
-cleanup:
- dlclose(dl);
- return ret;
-}
-
static int get_hmac(const char *path, char *hmac, size_t hmac_size)
{
int ret;
@@ -99,7 +67,7 @@ static int get_hmac(const char *path, ch
return 0;
}
-static int print_lib_path(const char *path)
+static int print_lib(const char *path, const char *soname)
{
int ret;
char *real_path = NULL;
@@ -119,7 +87,7 @@ static int print_lib_path(const char *pa
goto cleanup;
}
- printf("[%s]\n", last_component(path));
+ printf("[%s]\n", soname);
printf("path = %s\n", real_path);
printf("hmac = %s\n", hmac);
@@ -128,25 +96,24 @@ cleanup:
return ret;
}
-static int print_lib_dl(const char *lib, const char *sym)
+static int callback(struct dl_phdr_info *info, size_t size, void *data)
{
- int ret;
- char path[GNUTLS_PATH_MAX];
-
- ret = get_path(lib, sym, path, sizeof(path));
- if (ret < 0) {
- fprintf(stderr, "Could not get lib path for %s: %s\n",
- lib, gnutls_strerror(ret));
- return ret;
- }
+ const char *path = info->dlpi_name;
+ const char *soname = last_component(path);
- return print_lib_path(path);
+ if (!strcmp(soname, GNUTLS_LIBRARY_SONAME))
+ return print_lib(data ? data : path, soname);
+ if (!strcmp(soname, NETTLE_LIBRARY_SONAME))
+ return print_lib(path, soname);
+ if (!strcmp(soname, HOGWEED_LIBRARY_SONAME))
+ return print_lib(path, soname);
+ if (!strcmp(soname, GMP_LIBRARY_SONAME))
+ return print_lib(path, soname);
+ return 0;
}
int main(int argc, char **argv)
{
- int ret;
-
if (argc != 1 && argc != 2) {
fprintf(stderr, "Usage: %s [gnutls_so_path]\n", last_component(argv[0]));
return EXIT_FAILURE;
@@ -155,24 +122,15 @@ int main(int argc, char **argv)
printf("[global]\n");
printf("format-version = %d\n", FORMAT_VERSION);
- if (argc == 2)
- ret = print_lib_path(argv[1]);
- else
- ret = print_lib_dl(GNUTLS_LIBRARY_SONAME, "gnutls_global_init");
- if (ret < 0)
- return EXIT_FAILURE;
+ return dl_iterate_phdr(callback, argc == 2 ? argv[1] : NULL);
+}
- ret = print_lib_dl(NETTLE_LIBRARY_SONAME, "nettle_aes_set_encrypt_key");
- if (ret < 0)
- return EXIT_FAILURE;
-
- ret = print_lib_dl(HOGWEED_LIBRARY_SONAME, "nettle_mpz_sizeinbase_256_u");
- if (ret < 0)
- return EXIT_FAILURE;
-
- ret = print_lib_dl(GMP_LIBRARY_SONAME, "__gmpz_init");
- if (ret < 0)
- return EXIT_FAILURE;
+#else
- return EXIT_SUCCESS;
+int main(void)
+{
+ fprintf(stderr, "Function dl_iterate_phdr is missing\n");
+ return EXIT_FAILURE;
}
+
+#endif /* HAVE_DL_ITERATE_PHDR */
diff --color -ruNp a/lib/Makefile.am b/lib/Makefile.am
--- a/lib/Makefile.am 2022-05-18 16:46:00.000000000 +0200
+++ b/lib/Makefile.am 2022-12-15 11:00:18.789697779 +0100
@@ -202,14 +202,14 @@ noinst_PROGRAMS = fipshmac
fipshmac_SOURCES = fipshmac.c
fipshmac_LDADD = libgnutls.la ../gl/libgnu.la
-hmac_files = .libs/.gnutls.hmac
+hmac_file = .libs/.$(gnutls_so).hmac
-all-local: $(hmac_files)
+all-local: $(hmac_file)
-.libs/.gnutls.hmac: libgnutls.la fipshmac
+$(hmac_file): libgnutls.la fipshmac
$(AM_V_GEN) $(builddir)/fipshmac > $@-t && mv $@-t $@
-CLEANFILES = $(hmac_files)
+CLEANFILES = $(hmac_file)
endif
if NEED_LTLIBDL

View File

@ -0,0 +1,114 @@
From c149dd0767f32789e391280cb1eb06b7eb7c6bce Mon Sep 17 00:00:00 2001
From: Alexander Sosedkin <asosedkin@redhat.com>
Date: Tue, 9 Aug 2022 16:05:53 +0200
Subject: [PATCH 1/2] auth/rsa: side-step potential side-channel
Remove branching that depends on secret data.
Signed-off-by: Alexander Sosedkin <asosedkin@redhat.com>
Signed-off-by: Hubert Kario <hkario@redhat.com>
Tested-by: Hubert Kario <hkario@redhat.com>
---
lib/auth/rsa.c | 10 ----------
1 file changed, 10 deletions(-)
diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c
index 8108ee841d..6b158bacb2 100644
--- a/lib/auth/rsa.c
+++ b/lib/auth/rsa.c
@@ -155,7 +155,6 @@ static int
proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
size_t _data_size)
{
- const char attack_error[] = "auth_rsa: Possible PKCS #1 attack\n";
gnutls_datum_t ciphertext;
int ret, dsize;
ssize_t data_size = _data_size;
@@ -235,15 +234,6 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
ok &= CONSTCHECK_NOT_EQUAL(check_ver_min, 0) &
CONSTCHECK_EQUAL(session->key.key.data[1], ver_min);
- if (ok) {
- /* call logging function unconditionally so all branches are
- * indistinguishable for timing and cache access when debug
- * logging is disabled */
- _gnutls_no_log("%s", attack_error);
- } else {
- _gnutls_debug_log("%s", attack_error);
- }
-
/* This is here to avoid the version check attack
* discussed above.
*/
--
2.39.1
From 7c963102ec2119eecc1789b993aabe5edfd75f3b Mon Sep 17 00:00:00 2001
From: Hubert Kario <hkario@redhat.com>
Date: Wed, 8 Feb 2023 14:32:09 +0100
Subject: [PATCH 2/2] rsa: remove dead code
since the `ok` variable isn't used any more, we can remove all code
used to calculate it
Signed-off-by: Hubert Kario <hkario@redhat.com>
---
lib/auth/rsa.c | 20 +++-----------------
1 file changed, 3 insertions(+), 17 deletions(-)
diff --git a/lib/auth/rsa.c b/lib/auth/rsa.c
index 6b158bacb2..858701fe6e 100644
--- a/lib/auth/rsa.c
+++ b/lib/auth/rsa.c
@@ -159,8 +159,6 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
int ret, dsize;
ssize_t data_size = _data_size;
volatile uint8_t ver_maj, ver_min;
- volatile uint8_t check_ver_min;
- volatile uint32_t ok;
#ifdef ENABLE_SSL3
if (get_num_version(session) == GNUTLS_SSL3) {
@@ -186,7 +184,6 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
ver_maj = _gnutls_get_adv_version_major(session);
ver_min = _gnutls_get_adv_version_minor(session);
- check_ver_min = (session->internals.allow_wrong_pms == 0);
session->key.key.data = gnutls_malloc(GNUTLS_MASTER_SIZE);
if (session->key.key.data == NULL) {
@@ -205,10 +202,9 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
return ret;
}
- ret =
- gnutls_privkey_decrypt_data2(session->internals.selected_key,
- 0, &ciphertext, session->key.key.data,
- session->key.key.size);
+ gnutls_privkey_decrypt_data2(session->internals.selected_key,
+ 0, &ciphertext, session->key.key.data,
+ session->key.key.size);
/* After this point, any conditional on failure that cause differences
* in execution may create a timing or cache access pattern side
* channel that can be used as an oracle, so treat very carefully */
@@ -224,16 +220,6 @@ proc_rsa_client_kx(gnutls_session_t session, uint8_t * data,
* Vlastimil Klima, Ondej Pokorny and Tomas Rosa.
*/
- /* ok is 0 in case of error and 1 in case of success. */
-
- /* if ret < 0 */
- ok = CONSTCHECK_EQUAL(ret, 0);
- /* session->key.key.data[0] must equal ver_maj */
- ok &= CONSTCHECK_EQUAL(session->key.key.data[0], ver_maj);
- /* if check_ver_min then session->key.key.data[1] must equal ver_min */
- ok &= CONSTCHECK_NOT_EQUAL(check_ver_min, 0) &
- CONSTCHECK_EQUAL(session->key.key.data[1], ver_min);
-
/* This is here to avoid the version check attack
* discussed above.
*/
--
2.39.1

View File

@ -0,0 +1,220 @@
diff --color -ruNp a/lib/accelerated/x86/aes-xts-x86-aesni.c b/lib/accelerated/x86/aes-xts-x86-aesni.c
--- a/lib/accelerated/x86/aes-xts-x86-aesni.c 2022-03-02 12:38:09.000000000 +0100
+++ b/lib/accelerated/x86/aes-xts-x86-aesni.c 2022-11-07 14:12:38.476982750 +0100
@@ -73,7 +73,6 @@ x86_aes_xts_cipher_setkey(void *_ctx, co
/* Check key block according to FIPS-140-2 IG A.9 */
if (_gnutls_fips_mode_enabled()){
if (gnutls_memcmp(key, key + (keysize / 2), keysize / 2) == 0) {
- _gnutls_switch_lib_state(LIB_STATE_ERROR);
return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
}
}
diff --color -ruNp a/lib/nettle/cipher.c b/lib/nettle/cipher.c
--- a/lib/nettle/cipher.c 2022-11-07 14:10:13.672085930 +0100
+++ b/lib/nettle/cipher.c 2022-11-07 14:12:38.477982770 +0100
@@ -448,12 +448,14 @@ _gcm_decrypt(struct nettle_cipher_ctx *c
length, dst, src);
}
-static void _des_set_key(struct des_ctx *ctx, const uint8_t *key)
+static void
+_des_set_key(struct des_ctx *ctx, const uint8_t *key)
{
des_set_key(ctx, key);
}
-static void _des3_set_key(struct des3_ctx *ctx, const uint8_t *key)
+static void
+_des3_set_key(struct des3_ctx *ctx, const uint8_t *key)
{
des3_set_key(ctx, key);
}
@@ -477,50 +479,6 @@ _cfb8_decrypt(struct nettle_cipher_ctx *
}
static void
-_xts_aes128_set_encrypt_key(struct xts_aes128_key *xts_key,
- const uint8_t *key)
-{
- if (_gnutls_fips_mode_enabled() &&
- gnutls_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0)
- _gnutls_switch_lib_state(LIB_STATE_ERROR);
-
- xts_aes128_set_encrypt_key(xts_key, key);
-}
-
-static void
-_xts_aes128_set_decrypt_key(struct xts_aes128_key *xts_key,
- const uint8_t *key)
-{
- if (_gnutls_fips_mode_enabled() &&
- gnutls_memcmp(key, key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0)
- _gnutls_switch_lib_state(LIB_STATE_ERROR);
-
- xts_aes128_set_decrypt_key(xts_key, key);
-}
-
-static void
-_xts_aes256_set_encrypt_key(struct xts_aes256_key *xts_key,
- const uint8_t *key)
-{
- if (_gnutls_fips_mode_enabled() &&
- gnutls_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0)
- _gnutls_switch_lib_state(LIB_STATE_ERROR);
-
- xts_aes256_set_encrypt_key(xts_key, key);
-}
-
-static void
-_xts_aes256_set_decrypt_key(struct xts_aes256_key *xts_key,
- const uint8_t *key)
-{
- if (_gnutls_fips_mode_enabled() &&
- gnutls_memcmp(key, key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0)
- _gnutls_switch_lib_state(LIB_STATE_ERROR);
-
- xts_aes256_set_decrypt_key(xts_key, key);
-}
-
-static void
_xts_aes128_encrypt(struct nettle_cipher_ctx *ctx, size_t length, uint8_t * dst,
const uint8_t * src)
{
@@ -1041,8 +999,8 @@ static const struct nettle_cipher_st bui
.ctx_size = sizeof(struct xts_aes128_key),
.encrypt = _xts_aes128_encrypt,
.decrypt = _xts_aes128_decrypt,
- .set_encrypt_key = (nettle_set_key_func*)_xts_aes128_set_encrypt_key,
- .set_decrypt_key = (nettle_set_key_func*)_xts_aes128_set_decrypt_key,
+ .set_encrypt_key = (nettle_set_key_func*)xts_aes128_set_encrypt_key,
+ .set_decrypt_key = (nettle_set_key_func*)xts_aes128_set_decrypt_key,
.max_iv_size = AES_BLOCK_SIZE,
},
{ .algo = GNUTLS_CIPHER_AES_256_XTS,
@@ -1052,8 +1010,8 @@ static const struct nettle_cipher_st bui
.ctx_size = sizeof(struct xts_aes256_key),
.encrypt = _xts_aes256_encrypt,
.decrypt = _xts_aes256_decrypt,
- .set_encrypt_key = (nettle_set_key_func*)_xts_aes256_set_encrypt_key,
- .set_decrypt_key = (nettle_set_key_func*)_xts_aes256_set_decrypt_key,
+ .set_encrypt_key = (nettle_set_key_func*)xts_aes256_set_encrypt_key,
+ .set_decrypt_key = (nettle_set_key_func*)xts_aes256_set_decrypt_key,
.max_iv_size = AES_BLOCK_SIZE,
},
{ .algo = GNUTLS_CIPHER_AES_128_SIV,
@@ -1144,6 +1102,21 @@ wrap_nettle_cipher_setkey(void *_ctx, co
return 0;
}
+ switch (ctx->cipher->algo) {
+ case GNUTLS_CIPHER_AES_128_XTS:
+ if (_gnutls_fips_mode_enabled() &&
+ gnutls_memcmp(key, (char *)key + AES128_KEY_SIZE, AES128_KEY_SIZE) == 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ break;
+ case GNUTLS_CIPHER_AES_256_XTS:
+ if (_gnutls_fips_mode_enabled() &&
+ gnutls_memcmp(key, (char *)key + AES256_KEY_SIZE, AES256_KEY_SIZE) == 0)
+ return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+ break;
+ default:
+ break;
+ }
+
if (ctx->enc)
ctx->cipher->set_encrypt_key(ctx->ctx_ptr, key);
else
diff --color -ruNp a/tests/Makefile.am b/tests/Makefile.am
--- a/tests/Makefile.am 2022-11-07 14:10:13.836089211 +0100
+++ b/tests/Makefile.am 2022-11-07 14:12:38.478982790 +0100
@@ -233,7 +233,7 @@ ctests += mini-record-2 simple gnutls_hm
tls13-without-timeout-func buffer status-request-revoked \
set_x509_ocsp_multi_cli kdf-api keylog-func handshake-write \
x509cert-dntypes id-on-xmppAddr tls13-compat-mode ciphersuite-name \
- x509-upnconstraint pkcs7-verify-double-free \
+ x509-upnconstraint xts-key-check pkcs7-verify-double-free \
fips-rsa-sizes
ctests += tls-channel-binding
diff --color -ruNp a/tests/xts-key-check.c b/tests/xts-key-check.c
--- a/tests/xts-key-check.c 1970-01-01 01:00:00.000000000 +0100
+++ b/tests/xts-key-check.c 2022-11-07 14:12:38.478982790 +0100
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2022 Red Hat, Inc.
+ *
+ * Author: Zoltan Fridrich
+ *
+ * This file is part of GnuTLS.
+ *
+ * GnuTLS is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuTLS is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GnuTLS. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gnutls/crypto.h>
+
+#include "utils.h"
+
+static void test_xts_check(gnutls_cipher_algorithm_t alg)
+{
+ int ret;
+ gnutls_cipher_hd_t ctx;
+ gnutls_datum_t key, iv;
+
+ iv.size = gnutls_cipher_get_iv_size(alg);
+ iv.data = gnutls_malloc(iv.size);
+ if (iv.data == NULL)
+ fail("Error: %s\n", gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
+ gnutls_memset(iv.data, 0xf0, iv.size);
+
+ key.size = gnutls_cipher_get_key_size(alg);
+ key.data = gnutls_malloc(key.size);
+ if (key.data == NULL) {
+ gnutls_free(iv.data);
+ fail("Error: %s\n", gnutls_strerror(GNUTLS_E_MEMORY_ERROR));
+ }
+ gnutls_memset(key.data, 0xf0, key.size);
+
+ ret = gnutls_cipher_init(&ctx, alg, &key, &iv);
+ if (ret == GNUTLS_E_SUCCESS) {
+ gnutls_cipher_deinit(ctx);
+ gnutls_free(iv.data);
+ gnutls_free(key.data);
+ fail("cipher initialization should fail for key1 == key2\n");
+ }
+
+ key.data[0] = 0xff;
+
+ ret = gnutls_cipher_init(&ctx, alg, &key, &iv);
+ gnutls_free(iv.data);
+ gnutls_free(key.data);
+
+ if (ret == GNUTLS_E_SUCCESS)
+ gnutls_cipher_deinit(ctx);
+ else
+ fail("cipher initialization should succeed with key1 != key2"
+ "\n%s\n", gnutls_strerror(ret));
+}
+
+void doit(void)
+{
+ if (!gnutls_fips140_mode_enabled())
+ exit(77);
+
+ test_xts_check(GNUTLS_CIPHER_AES_128_XTS);
+ test_xts_check(GNUTLS_CIPHER_AES_256_XTS);
+}

View File

@ -13,7 +13,7 @@ print(string.sub(hash, 0, 16))
} }
Version: 3.7.6 Version: 3.7.6
Release: 11%{?dist} Release: 18%{?dist}
# not upstreamed # not upstreamed
Patch: gnutls-3.6.7-no-now-guile.patch Patch: gnutls-3.6.7-no-now-guile.patch
Patch: gnutls-3.2.7-rpath.patch Patch: gnutls-3.2.7-rpath.patch
@ -28,6 +28,18 @@ Patch: gnutls-3.7.6-aes-gcm-pt-limit.patch
Patch: gnutls-3.7.6-pkcs7-verify.patch Patch: gnutls-3.7.6-pkcs7-verify.patch
Patch: gnutls-3.7.6-fips-pkcs12-des-cbc.patch Patch: gnutls-3.7.6-fips-pkcs12-des-cbc.patch
Patch: gnutls-3.7.6-fips-rsa-key-sizes.patch Patch: gnutls-3.7.6-fips-rsa-key-sizes.patch
Patch: gnutls-3.7.6-fips-symkey-limit.patch
Patch: gnutls-3.7.6-fips-ecdsa-hash-check.patch
Patch: gnutls-3.7.8-xts-key-check.patch
Patch: gnutls-3.7.8-clear-session-ticket.patch
Patch: gnutls-3.7.7-aes-cbc-padding-support.patch
Patch: gnutls-3.7.8-integrity-check.patch
Patch: gnutls-3.7.6-fips-service-indicator-test-functions.patch
Patch: gnutls-3.7.6-fips-ccm-taglen.patch
Patch: gnutls-3.7.6-fips-rsa-pss-saltlen.patch
Patch: gnutls-3.7.8-revert-hmac-name.patch
Patch: gnutls-3.7.8-rsa-kx-timing.patch
Patch: gnutls-3.7.8-fips-pct-dh.patch
# not upstreamed # not upstreamed
Patch: gnutls-3.7.3-disable-config-reload.patch Patch: gnutls-3.7.3-disable-config-reload.patch
@ -194,10 +206,7 @@ This package contains Guile bindings for the library.
%endif %endif
%prep %prep
# Workaround: to allow building the package under FIPS, do not treat %{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}'
# errors in the GPG check as fatal, where EdDSA signature verification
# is not allowed:
%{gpgverify} --keyring='%{SOURCE2}' --signature='%{SOURCE1}' --data='%{SOURCE0}' || :
%autosetup -p1 -S git %autosetup -p1 -S git
@ -325,8 +334,10 @@ rm -f $RPM_BUILD_ROOT%{_libdir}/pkgconfig/gnutls-dane.pc
# doing it twice should be a no-op the second time, # doing it twice should be a no-op the second time,
# and this way we avoid redefining it and missing a future change # and this way we avoid redefining it and missing a future change
%{__spec_install_post} %{__spec_install_post}
./lib/fipshmac "$RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30" > $RPM_BUILD_ROOT%{_libdir}/.gnutls.hmac fname=`basename $RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30.*.*`
sed -i "s^$RPM_BUILD_ROOT/usr^^" $RPM_BUILD_ROOT%{_libdir}/.gnutls.hmac ./lib/fipshmac "$RPM_BUILD_ROOT%{_libdir}/libgnutls.so.30" > "$RPM_BUILD_ROOT%{_libdir}/.$fname.hmac"
sed -i "s^$RPM_BUILD_ROOT/usr^^" "$RPM_BUILD_ROOT%{_libdir}/.$fname.hmac"
ln -s ".$fname.hmac" "$RPM_BUILD_ROOT%{_libdir}/.libgnutls.so.30.hmac"
%endif %endif
%if %{with fips} %if %{with fips}
@ -347,7 +358,7 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
%files -f gnutls.lang %files -f gnutls.lang
%{_libdir}/libgnutls.so.30* %{_libdir}/libgnutls.so.30*
%if %{with fips} %if %{with fips}
%{_libdir}/.gnutls.hmac %{_libdir}/.libgnutls.so.30*.hmac
%endif %endif
%doc README.md AUTHORS NEWS THANKS %doc README.md AUTHORS NEWS THANKS
%license LICENSE doc/COPYING doc/COPYING.LESSER %license LICENSE doc/COPYING doc/COPYING.LESSER
@ -395,6 +406,36 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
%endif %endif
%changelog %changelog
* Tue Feb 28 2023 Daiki Ueno <dueno@redhat.com> - 3.7.6-18
- Update gnutls-3.7.8-fips-pct-dh.patch to the upstream version (#2168143)
* Fri Feb 10 2023 Daiki Ueno <dueno@redhat.com> - 3.7.6-17
- Fix timing side-channel in TLS RSA key exchange (#2162601)
* Fri Feb 10 2023 Daiki Ueno <dueno@redhat.com> - 3.7.6-16
- fips: extend PCT to DH key generation (#2168143)
* Thu Dec 15 2022 Zoltan Fridrich <zfridric@redhat.com> - 3.7.6-15
- fips: rename hmac file to its previous name (#2148269)
* Tue Nov 22 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-14
- cipher: add restriction on CCM tag length under FIPS mode (#2137807)
- nettle: mark non-compliant RSA-PSS salt length to be not-approved (#2143266)
* Tue Nov 15 2022 Zoltan Fridrich <zfridric@redhat.com> - 3.7.6-13
- fips: make XTS key check failure not fatal (#2130971)
- enable source archive verification again (#2127094)
- clear server's session ticket indication at rehandshake (#2136072)
- crypto-api: add block cipher API with automatic padding (#2084161)
- fips: remove library path checking from FIPS integrity check (#2140908)
* Tue Sep 27 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-12
- fips: mark PBKDF2 with short key and output sizes non-approved
- fips: only mark HMAC as approved in PBKDF2
- fips: mark gnutls_key_generate with short key sizes non-approved
- fips: fix checking on hash algorithm used in ECDSA
- fips: preserve operation context around FIPS selftests API
* Fri Aug 26 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-11 * Fri Aug 26 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-11
- Supply --with{,out}-{zlib,brotli,zstd} explicitly - Supply --with{,out}-{zlib,brotli,zstd} explicitly
@ -412,31 +453,31 @@ make check %{?_smp_mflags} GNUTLS_SYSTEM_PRIORITY_FILE=/dev/null
- Update gnutls-3.7.6-cpuid-fixes.patch - Update gnutls-3.7.6-cpuid-fixes.patch
* Sat Aug 20 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-6 * Sat Aug 20 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-6
- Mark RSA SigVer operation approved for known modulus sizes (#2119770) - Mark RSA SigVer operation approved for known modulus sizes (#2091903)
- accelerated: clear AVX bits if it cannot be queried through XSAVE - accelerated: clear AVX bits if it cannot be queried through XSAVE
* Thu Aug 4 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-5 * Thu Aug 4 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-5
- Block DES-CBC usage in decrypting PKCS#12 bag under FIPS (#2115314) - Block DES-CBC usage in decrypting PKCS#12 bag under FIPS (#2115244)
- sysrng: reseed source DRBG for prediction resistance - sysrng: reseed source DRBG for prediction resistance
* Fri Jul 29 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-4 * Fri Jul 29 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-4
- Make gnutls-cli work with KTLS for testing - Make gnutls-cli work with KTLS for testing
- Fix double-free in gnutls_pkcs7_verify (#2109789) - Fix double-free in gnutls_pkcs7_verify (#2109790)
* Mon Jul 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-3 * Mon Jul 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-3
- Limit input size for AES-GCM according to SP800-38D (#2108635) - Limit input size for AES-GCM according to SP800-38D (#2095251)
- Do not treat GPG verification errors as fatal - Do not treat GPG verification errors as fatal
- Remove gnutls-3.7.6-libgnutlsxx-const.patch - Remove gnutls-3.7.6-libgnutlsxx-const.patch
* Tue Jul 19 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-2 * Tue Jul 19 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-2
- Allow enabling KTLS with config file (#2108532) - Allow enabling KTLS with config file (#2042009)
* Fri Jul 1 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-1 * Fri Jul 1 2022 Daiki Ueno <dueno@redhat.com> - 3.7.6-1
- Update to gnutls 3.7.6 (#2102591) - Update to gnutls 3.7.6 (#2097327)
* Thu Mar 31 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-10 * Thu Mar 31 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-10
- Use only the first component of VERSION from /etc/os-release (#2076626) - Use only the first component of VERSION from /etc/os-release (#2070249)
- Don't run power-on self-tests on DSA (#2076627) - Don't run power-on self-tests on DSA (#2061325)
* Fri Feb 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-9 * Fri Feb 25 2022 Daiki Ueno <dueno@redhat.com> - 3.7.3-9
- Stop using typeof keyword for tss2 function prototypes (#2057490) - Stop using typeof keyword for tss2 function prototypes (#2057490)