From: Tomas Mraz Date: Tue, 30 Jul 2024 07:31:11 +0000 (+0200) Subject: ssl_evp_cipher_fetch(): Avoid using 3DES from the FIPS provider X-Git-Tag: openssl-3.4.0-alpha1~246 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ed7a8bfd7409ac4a516581f1711d98a9362a70d5;p=thirdparty%2Fopenssl.git ssl_evp_cipher_fetch(): Avoid using 3DES from the FIPS provider Avoid using a fetched cipher that is decrypt-only which is the case for 3DES from the fips provider. Add a decrypt-only parameter to the EVP_CIPHER and test it in libssl when fetching. Reviewed-by: Neil Horman Reviewed-by: Matt Caswell (Merged from https://github.com/openssl/openssl/pull/25028) --- diff --git a/doc/man3/EVP_EncryptInit.pod b/doc/man3/EVP_EncryptInit.pod index 41b5e107772..0bad8d48738 100644 --- a/doc/man3/EVP_EncryptInit.pod +++ b/doc/man3/EVP_EncryptInit.pod @@ -733,6 +733,12 @@ Gets 1 if the cipher algorithm I supports the gettable EVP_CIPHER_CTX parameter B. Only DES and 3DES set this to 1, all other OpenSSL ciphers return 0. +=item "decrypt-only" (B + +Gets 1 if the cipher algorithm I implementation supports only +the decryption operation such as the 3DES ciphers in the fips provider. +Otherwise gets 0 or the parameter might not be present at all. + =back =head2 Gettable and Settable EVP_CIPHER_CTX parameters diff --git a/providers/implementations/ciphers/cipher_tdes.h b/providers/implementations/ciphers/cipher_tdes.h index 765ec8b5e13..d0bd79b7118 100644 --- a/providers/implementations/ciphers/cipher_tdes.h +++ b/providers/implementations/ciphers/cipher_tdes.h @@ -42,8 +42,8 @@ static void *tdes_##type##_##lcmode##_newctx(void *provctx) \ static OSSL_FUNC_cipher_get_params_fn tdes_##type##_##lcmode##_get_params; \ static int tdes_##type##_##lcmode##_get_params(OSSL_PARAM params[]) \ { \ - return ossl_cipher_generic_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ - flags, kbits, blkbits, ivbits); \ + return ossl_tdes_get_params(params, EVP_CIPH_##UCMODE##_MODE, \ + flags, kbits, blkbits, ivbits); \ } \ const OSSL_DISPATCH ossl_tdes_##type##_##lcmode##_functions[] = { \ { OSSL_FUNC_CIPHER_ENCRYPT_INIT, (void (*)(void))ossl_tdes_einit }, \ @@ -74,6 +74,9 @@ const OSSL_DISPATCH ossl_tdes_##type##_##lcmode##_functions[] = { \ void *ossl_tdes_newctx(void *provctx, int mode, size_t kbits, size_t blkbits, size_t ivbits, uint64_t flags, const PROV_CIPHER_HW *hw); +int ossl_tdes_get_params(OSSL_PARAM params[], unsigned int md, uint64_t flags, + size_t kbits, size_t blkbits, size_t ivbits); + OSSL_FUNC_cipher_dupctx_fn ossl_tdes_dupctx; OSSL_FUNC_cipher_freectx_fn ossl_tdes_freectx; OSSL_FUNC_cipher_encrypt_init_fn ossl_tdes_einit; diff --git a/providers/implementations/ciphers/cipher_tdes_common.c b/providers/implementations/ciphers/cipher_tdes_common.c index 1c7572c77d8..60f0707951d 100644 --- a/providers/implementations/ciphers/cipher_tdes_common.c +++ b/providers/implementations/ciphers/cipher_tdes_common.c @@ -185,3 +185,23 @@ int ossl_tdes_set_ctx_params(void *vctx, const OSSL_PARAM params[]) return 0; return ossl_cipher_generic_set_ctx_params(vctx, params); } + +int ossl_tdes_get_params(OSSL_PARAM params[], unsigned int md, uint64_t flags, + size_t kbits, size_t blkbits, size_t ivbits) +{ +#ifdef FIPS_MODULE + const int decrypt_only = 1; +#else + const int decrypt_only = 0; +#endif + OSSL_PARAM *p; + + p = OSSL_PARAM_locate(params, OSSL_CIPHER_PARAM_DECRYPT_ONLY); + if (p != NULL && !OSSL_PARAM_set_int(p, decrypt_only)) { + ERR_raise(ERR_LIB_PROV, PROV_R_FAILED_TO_SET_PARAMETER); + return 0; + } + + return ossl_cipher_generic_get_params(params, md, flags, + kbits, blkbits, ivbits); +} diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c index ccb9ac1dd1c..f1fe7186601 100644 --- a/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "internal/cryptlib.h" #include "internal/nelem.h" #include "internal/refcount.h" @@ -7235,6 +7236,20 @@ const EVP_CIPHER *ssl_evp_cipher_fetch(OSSL_LIB_CTX *libctx, */ ERR_set_mark(); ciph = EVP_CIPHER_fetch(libctx, OBJ_nid2sn(nid), properties); + if (ciph != NULL) { + OSSL_PARAM params[2]; + int decrypt_only = 0; + + params[0] = OSSL_PARAM_construct_int(OSSL_CIPHER_PARAM_DECRYPT_ONLY, + &decrypt_only); + params[1] = OSSL_PARAM_construct_end(); + if (EVP_CIPHER_get_params((EVP_CIPHER *)ciph, params) + && decrypt_only) { + /* If a cipher is decrypt-only, it is unusable */ + EVP_CIPHER_free((EVP_CIPHER *)ciph); + ciph = NULL; + } + } ERR_pop_to_mark(); return ciph; } diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm index 5fdeea4b885..223181652da 100644 --- a/util/perl/OpenSSL/paramnames.pm +++ b/util/perl/OpenSSL/paramnames.pm @@ -117,6 +117,7 @@ my %params = ( 'CIPHER_PARAM_RC2_KEYBITS' => "keybits", # size_t 'CIPHER_PARAM_SPEED' => "speed", # uint 'CIPHER_PARAM_CTS_MODE' => "cts_mode", # utf8_string + 'CIPHER_PARAM_DECRYPT_ONLY' => "decrypt-only", # int, 0 or 1 'CIPHER_PARAM_FIPS_ENCRYPT_CHECK' => "encrypt-check", # int 'CIPHER_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # For passing the AlgorithmIdentifier parameter in DER form