import gnutls-3.7.6-18.el9
This commit is contained in:
		
							parent
							
								
									c046ee914f
								
							
						
					
					
						commit
						a80d0f7f8e
					
				
							
								
								
									
										331
									
								
								SOURCES/gnutls-3.7.6-fips-ccm-taglen.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										331
									
								
								SOURCES/gnutls-3.7.6-fips-ccm-taglen.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										427
									
								
								SOURCES/gnutls-3.7.6-fips-ecdsa-hash-check.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										427
									
								
								SOURCES/gnutls-3.7.6-fips-ecdsa-hash-check.patch
									
									
									
									
									
										Normal 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, ¶ms); | ||||||
|  |  	if (ret < 0) { | ||||||
|  |  		gnutls_assert(); | ||||||
|  | -		return ret;
 | ||||||
|  | +		goto cleanup;
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ret = _gnutls_privkey_update_spki_params(signer, se->pk, se->hash, | ||||||
|  |  					         flags, ¶ms); | ||||||
|  |  	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, ¶ms);
 | ||||||
|  | +	ret = privkey_sign_prehashed(signer, se, hash_data, signature, ¶ms);
 | ||||||
|  | +
 | ||||||
|  | + 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, ¶ms); | ||||||
|  |  	if (ret < 0) { | ||||||
|  |  		gnutls_assert(); | ||||||
|  | -		return ret;
 | ||||||
|  | +		goto cleanup;
 | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	ret = _gnutls_privkey_update_spki_params(signer, signer->pk_algorithm, | ||||||
|  |  					       hash_algo, flags, ¶ms); | ||||||
|  |  	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, ¶ms);
 | ||||||
|  | +	ret = privkey_sign_prehashed(signer, se,
 | ||||||
|  | +				     hash_data, signature, ¶ms);
 | ||||||
|  | + 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										163
									
								
								SOURCES/gnutls-3.7.6-fips-rsa-pss-saltlen.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								SOURCES/gnutls-3.7.6-fips-rsa-pss-saltlen.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
| @ -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 | ||||||
|  | 
 | ||||||
|  | |||||||
							
								
								
									
										407
									
								
								SOURCES/gnutls-3.7.6-fips-service-indicator-test-functions.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										407
									
								
								SOURCES/gnutls-3.7.6-fips-service-indicator-test-functions.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										310
									
								
								SOURCES/gnutls-3.7.6-fips-symkey-limit.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										310
									
								
								SOURCES/gnutls-3.7.6-fips-symkey-limit.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
| @ -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 |  | ||||||
| 
 |  | ||||||
|  | |||||||
							
								
								
									
										433
									
								
								SOURCES/gnutls-3.7.7-aes-cbc-padding-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										433
									
								
								SOURCES/gnutls-3.7.7-aes-cbc-padding-support.patch
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										215
									
								
								SOURCES/gnutls-3.7.8-clear-session-ticket.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								SOURCES/gnutls-3.7.8-clear-session-ticket.patch
									
									
									
									
									
										Normal 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();
 | ||||||
|  | +}
 | ||||||
							
								
								
									
										58
									
								
								SOURCES/gnutls-3.7.8-fips-pct-dh.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								SOURCES/gnutls-3.7.8-fips-pct-dh.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										54
									
								
								SOURCES/gnutls-3.7.8-integrity-check.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								SOURCES/gnutls-3.7.8-integrity-check.patch
									
									
									
									
									
										Normal 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) | ||||||
							
								
								
									
										534
									
								
								SOURCES/gnutls-3.7.8-revert-hmac-name.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										534
									
								
								SOURCES/gnutls-3.7.8-revert-hmac-name.patch
									
									
									
									
									
										Normal 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 | ||||||
							
								
								
									
										114
									
								
								SOURCES/gnutls-3.7.8-rsa-kx-timing.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								SOURCES/gnutls-3.7.8-rsa-kx-timing.patch
									
									
									
									
									
										Normal 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 | ||||||
|  | 
 | ||||||
							
								
								
									
										220
									
								
								SOURCES/gnutls-3.7.8-xts-key-check.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										220
									
								
								SOURCES/gnutls-3.7.8-xts-key-check.patch
									
									
									
									
									
										Normal 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);
 | ||||||
|  | +}
 | ||||||
| @ -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) | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user