diff options
author | slontis <shane.lontis@oracle.com> | 2024-07-01 11:36:58 +1000 |
---|---|---|
committer | Pauli <ppzgs1@gmail.com> | 2024-07-11 08:29:43 +1000 |
commit | c13ddf0a6c71efac8ef546f0d3632341afab3f07 (patch) | |
tree | 8c87439328e16479f39457c639d5128b3c7bee02 | |
parent | d4848934a61a668d16078f3118786c9a741b7efd (diff) | |
download | openssl-c13ddf0a6c71efac8ef546f0d3632341afab3f07.tar.gz |
Change all existing FIPS configurable checks to use FIPS indicators.
This changes the logic to always do the security checks and then decide
what to do based on if this passes or not. Failure of a check causes
either a failure OR the FIPS indicator callback to be triggered.
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Paul Dale <pauli@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/24623)
32 files changed, 882 insertions, 342 deletions
diff --git a/doc/man7/EVP_ASYM_CIPHER-RSA.pod b/doc/man7/EVP_ASYM_CIPHER-RSA.pod index c68cad6c42..b36927082d 100644 --- a/doc/man7/EVP_ASYM_CIPHER-RSA.pod +++ b/doc/man7/EVP_ASYM_CIPHER-RSA.pod @@ -57,6 +57,10 @@ See L<EVP_PKEY_CTX_set_rsa_padding(3)> for further details. =item "oaep-label" (B<OSSL_ASYM_CIPHER_PARAM_OAEP_LABEL>) <octet string> +=item "fips-indicator" (B<OSSL_ASYM_CIPHER_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +=item "key-check" (B<OSSL_ASYM_CIPHER_PARAM_FIPS_KEY_CHECK>) <int> + =item "tls-client-version" (B<OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION>) <unsigned integer> See B<RSA_PKCS1_WITH_TLS_PADDING> on the page L<EVP_PKEY_CTX_set_rsa_padding(3)>. diff --git a/doc/man7/EVP_KDF-TLS1_PRF.pod b/doc/man7/EVP_KDF-TLS1_PRF.pod index 8a60e97315..1c0bf750ba 100644 --- a/doc/man7/EVP_KDF-TLS1_PRF.pod +++ b/doc/man7/EVP_KDF-TLS1_PRF.pod @@ -44,6 +44,22 @@ This parameter sets the context seed. The length of the context seed cannot exceed 1024 bytes; this should be more than enough for any normal use of the TLS PRF. +=item "fips-indicator" (B<OSSL_KDF_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling EVP_KDF_derive. It returns 0 if the "ems_check" +is set to 0 and the "extended master secret" test fails. +This option is used by the OpenSSL FIPS provider. + +=item "ems_check" (B<OSSL_KDF_PARAM_FIPS_EMS_CHECK>) <int> + +The default value of 1 causes an error during EVP_KDF_derive() if +"master secret" is used instead of "extended master secret" Setting this to zero +will ignore the error and set the approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + + =back =head1 NOTES diff --git a/doc/man7/EVP_KEM-RSA.pod b/doc/man7/EVP_KEM-RSA.pod index 3a89f5db39..2733be6a6c 100644 --- a/doc/man7/EVP_KEM-RSA.pod +++ b/doc/man7/EVP_KEM-RSA.pod @@ -31,8 +31,13 @@ The decapsulate function recovers the secret using the RSA private key. This can be set using EVP_PKEY_CTX_set_kem_op(). -=back +=item "fips-indicator" (B<OSSL_KEM_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +=item "key-check" (B<OSSL_KEM_PARAM_FIPS_KEY_CHECK>) <int> +These parameters are described in L<provider-kem(7)>. + +=back =head1 CONFORMING TO diff --git a/doc/man7/EVP_KEYEXCH-DH.pod b/doc/man7/EVP_KEYEXCH-DH.pod index a6927afefb..1ccc469318 100644 --- a/doc/man7/EVP_KEYEXCH-DH.pod +++ b/doc/man7/EVP_KEYEXCH-DH.pod @@ -28,22 +28,20 @@ the KDF type is set to "X942KDF-ASN1" (B<OSSL_KDF_NAME_X942KDF_ASN1>). =item "kdf-type" (B<OSSL_EXCHANGE_PARAM_KDF_TYPE>) <UTF8 string> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-digest" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST>) <UTF8 string> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-digest-props" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS>) <UTF8 string> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-outlen" (B<OSSL_EXCHANGE_PARAM_KDF_OUTLEN>) <unsigned integer> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-ukm" (B<OSSL_EXCHANGE_PARAM_KDF_UKM>) <octet string> +=item "fips-indicator" (B<OSSL_EXCHANGE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +=item "key-check" (B<OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK>) <int> + +=item "digest-check" (B<OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK>) <int> + See L<provider-keyexch(7)/Common Key Exchange parameters>. =item "cekalg" (B<OSSL_KDF_PARAM_CEK_ALG>) <octet string ptr> diff --git a/doc/man7/EVP_KEYEXCH-ECDH.pod b/doc/man7/EVP_KEYEXCH-ECDH.pod index f9579dab2f..28e8d2a760 100644 --- a/doc/man7/EVP_KEYEXCH-ECDH.pod +++ b/doc/man7/EVP_KEYEXCH-ECDH.pod @@ -33,22 +33,20 @@ per-key basis. =item "kdf-type" (B<OSSL_EXCHANGE_PARAM_KDF_TYPE>) <UTF8 string> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-digest" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST>) <UTF8 string> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-digest-props" (B<OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS>) <UTF8 string> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-outlen" (B<OSSL_EXCHANGE_PARAM_KDF_OUTLEN>) <unsigned integer> -See L<provider-keyexch(7)/Common Key Exchange parameters>. - =item "kdf-ukm" (B<OSSL_EXCHANGE_PARAM_KDF_UKM>) <octet string> +=item "fips-indicator" (B<OSSL_EXCHANGE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +=item "key-check" (B<OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK>) <int> + +=item "digest-check" (B<OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK>) <int> + See L<provider-keyexch(7)/Common Key Exchange parameters>. =back diff --git a/doc/man7/EVP_SIGNATURE-DSA.pod b/doc/man7/EVP_SIGNATURE-DSA.pod index 290041a2dd..2e761cb667 100644 --- a/doc/man7/EVP_SIGNATURE-DSA.pod +++ b/doc/man7/EVP_SIGNATURE-DSA.pod @@ -14,7 +14,8 @@ See L<EVP_PKEY-DSA(7)> for information related to DSA keys. The following signature parameters can be set using EVP_PKEY_CTX_set_params(). This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(), -and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). +and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). They may also be set +using EVP_PKEY_sign_init_ex() or EVP_PKEY_verify_init_ex(). =over 4 @@ -24,6 +25,10 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). =item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer> +=item "key-check" (B<OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK>) <int> + +=item "digest-check" (B<OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK>) <int> + The settable parameters are described in L<provider-signature(7)>. =back @@ -39,6 +44,8 @@ EVP_PKEY_CTX_get_params(). =item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer> +=item "fips-indicator" (B<OSSL_SIGNATURE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + The gettable parameters are described in L<provider-signature(7)>. =back diff --git a/doc/man7/EVP_SIGNATURE-ECDSA.pod b/doc/man7/EVP_SIGNATURE-ECDSA.pod index a19d467c0d..4d47b8c9bf 100644 --- a/doc/man7/EVP_SIGNATURE-ECDSA.pod +++ b/doc/man7/EVP_SIGNATURE-ECDSA.pod @@ -23,6 +23,10 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). =item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer> +=item "key-check" (B<OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK>) <int> + +=item "digest-check" (B<OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK>) <int> + These parameters are described in L<provider-signature(7)>. =back @@ -38,6 +42,8 @@ EVP_PKEY_CTX_get_params(). =item "nonce-type" (B<OSSL_SIGNATURE_PARAM_NONCE_TYPE>) <unsigned integer> +=item "fips-indicator" (B<OSSL_SIGNATURE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + The parameters are described in L<provider-signature(7)>. =back diff --git a/doc/man7/EVP_SIGNATURE-RSA.pod b/doc/man7/EVP_SIGNATURE-RSA.pod index de6869786c..9398e77019 100644 --- a/doc/man7/EVP_SIGNATURE-RSA.pod +++ b/doc/man7/EVP_SIGNATURE-RSA.pod @@ -14,7 +14,8 @@ See L<EVP_PKEY-RSA(7)> for information related to RSA keys. The following signature parameters can be set using EVP_PKEY_CTX_set_params(). This may be called after EVP_PKEY_sign_init() or EVP_PKEY_verify_init(), -and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). +and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). They may also be set +using EVP_PKEY_sign_init_ex() or EVP_PKEY_verify_init_ex(). =over 4 @@ -22,6 +23,10 @@ and before calling EVP_PKEY_sign() or EVP_PKEY_verify(). =item "properties" (B<OSSL_SIGNATURE_PARAM_PROPERTIES>) <UTF8 string> +=item "key-check" (B<OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK>) <int> + +=item "digest-check" (B<OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK>) <int> + These common parameters are described in L<provider-signature(7)>. =item "pad-mode" (B<OSSL_SIGNATURE_PARAM_PAD_MODE>) <UTF8 string> @@ -84,7 +89,9 @@ EVP_PKEY_CTX_get_params(). =item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string> -This common parameter is described in L<provider-signature(7)>. +=item "fips-indicator" (B<OSSL_SIGNATURE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +These common parameter are described in L<provider-signature(7)>. =item "digest" (B<OSSL_SIGNATURE_PARAM_DIGEST>) <UTF8 string> diff --git a/doc/man7/provider-asym_cipher.pod b/doc/man7/provider-asym_cipher.pod index 24fe160bf7..9602367da8 100644 --- a/doc/man7/provider-asym_cipher.pod +++ b/doc/man7/provider-asym_cipher.pod @@ -243,6 +243,23 @@ This makes exploitation of the Bleichenbacher significantly harder, even if the code using the RSA decryption API is not implemented in side-channel free manner. Set by default. Requires provider support. +=item "fips-indicator" (B<OSSL_ASYM_CIPHER_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling either OSSL_FUNC_asym_cipher_encrypt() or +OSSL_FUNC_asym_cipher_decrypt(). It may return 0 if "key-check" is set to 0. +This option is used by the OpenSSL FIPS provider. + +=item "key-check" (B<OSSL_ASYM_CIPHER_PARAM_FIPS_KEY_CHECK>) <int> + +If required this parameter should be set using either +OSSL_FUNC_asym_cipher_encrypt_init() or OSSL_FUNC_asym_cipher_decrypt_init(). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). Setting +this to 0 will ignore the error and set the approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + =back OSSL_FUNC_asym_cipher_gettable_ctx_params() and OSSL_FUNC_asym_cipher_settable_ctx_params() @@ -264,6 +281,8 @@ L<provider(7)> =head1 HISTORY The provider ASYM_CIPHER interface was introduced in OpenSSL 3.0. +The Asymmetric Cipher Parameters "fips-indicator" and "key-check" +were added in OpenSSL 3.4. =head1 COPYRIGHT diff --git a/doc/man7/provider-kem.pod b/doc/man7/provider-kem.pod index 970105a269..eb04beb429 100644 --- a/doc/man7/provider-kem.pod +++ b/doc/man7/provider-kem.pod @@ -186,12 +186,36 @@ See L<OSSL_PARAM(3)> for further details on the parameters structure used by the OSSL_FUNC_kem_get_ctx_params() and OSSL_FUNC_kem_set_ctx_params() functions. -OSSL_FUNC_kem_get_ctx_params() gets asymmetric kem parameters associated +Common parameters currently recognised by built-in key encapsulation algorithms +are as follows. + +=over 4 + +=item "fips-indicator" (B<OSSL_KEM_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling either OSSL_FUNC_kem_encapsulate() or +OSSL_FUNC_kem_decapsulate(). It may return 0 if the "key-check" is set to 0. +This option is used by the OpenSSL FIPS provider. + +=item "key-check" (B<OSSL_KEM_PARAM_FIPS_KEY_CHECK>) <int> + +If required this parameter should be set using OSSL_FUNC_kem_encapsulate_init() +or OSSL_FUNC_kem_decapsulate_init(). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). Setting +this to 0 will ignore the error and set the approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + +=back + +OSSL_FUNC_kem_get_ctx_params() gets asymmetric KEM parameters associated with the given provider side asymmetric kem context I<ctx> and stores them in I<params>. Passing NULL for I<params> should return true. -OSSL_FUNC_kem_set_ctx_params() sets the asymmetric kem parameters associated +OSSL_FUNC_kem_set_ctx_params() sets the asymmetric KEM parameters associated with the given provider side asymmetric kem context I<ctx> to I<params>. Any parameter settings are additional to any that were previously set. Passing NULL for I<params> should return true. @@ -221,6 +245,9 @@ The provider KEM interface was introduced in OpenSSL 3.0. OSSL_FUNC_kem_auth_encapsulate_init() and OSSL_FUNC_kem_auth_decapsulate_init() were added in OpenSSL 3.2. +The Asymmetric Key Encapsulation Parameters "fips-indicator" and "key-check" +were added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man7/provider-keyexch.pod b/doc/man7/provider-keyexch.pod index 9e146d31c7..702bfb01f6 100644 --- a/doc/man7/provider-keyexch.pod +++ b/doc/man7/provider-keyexch.pod @@ -204,6 +204,31 @@ usually do not need to support this gettable parameter as its sole purpose is to support functionality of the deprecated EVP_PKEY_CTX_get0_ecdh_kdf_ukm() and EVP_PKEY_CTX_get0_dh_kdf_ukm() functions. +=item "fips-indicator" (B<OSSL_EXCHANGE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling OSSL_FUNC_keyexch_derive(). It may +return 0 if either the "digest-check" or the "key-check" are set to 0. +This option is used by the OpenSSL FIPS provider. + +=item "key-check" (B<OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK>) <int> + +If required this parameter should be set using OSSL_FUNC_keyexch_init(). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). Setting +this to 0 will ignore the error and set the approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + +=item "digest-check" (B<OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK>) <int> + +If required this parameter should be set before any optional digest is set. +The default value of 1 causes an error when the digest is set if the digest is +not FIPS approved. Setting this to 0 will ignore the error and set the +approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + =back =head1 RETURN VALUES @@ -226,6 +251,9 @@ L<provider(7)> The provider KEYEXCH interface was introduced in OpenSSL 3.0. +The Key Exchange Parameters "fips-indicator", "key-check" and "digest-check" +were added in OpenSSL 3.4. + =head1 COPYRIGHT Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. diff --git a/doc/man7/provider-rand.pod b/doc/man7/provider-rand.pod index e115d845dc..aa1df965f6 100644 --- a/doc/man7/provider-rand.pod +++ b/doc/man7/provider-rand.pod @@ -254,6 +254,22 @@ Sets the properties to be queried when trying to fetch an underlying algorithm. This must be given together with the algorithm naming parameter to be considered valid. +=item "fips-indicator" (B<OSSL_DRBG_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling OSSL_FUNC_rand_generate(). It may +return 0 if the "digest-check" is set to 0. +This option is used by the OpenSSL FIPS provider. + +=item "digest-check" (B<OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK>) <int> + +If required this parameter should be set before the digest is set. +The default value of 1 causes an error when the digest is set if the digest is +not FIPS approved (e.g. truncated digests). Setting this to 0 will ignore +the error and set the approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + =back =head1 RETURN VALUES @@ -289,6 +305,8 @@ L<EVP_RAND(3)> =head1 HISTORY The provider RAND interface was introduced in OpenSSL 3.0. +The Rand Parameters "fips-indicator" and "digest-check" were added in +OpenSSL 3.4. =head1 COPYRIGHT diff --git a/doc/man7/provider-signature.pod b/doc/man7/provider-signature.pod index b26b8b6a5b..7763112d06 100644 --- a/doc/man7/provider-signature.pod +++ b/doc/man7/provider-signature.pod @@ -257,7 +257,7 @@ the I<routlen> parameter. =head2 Digest Sign Functions -OSSL_FUNC_signature_digeset_sign_init() initialises a context for signing given a +OSSL_FUNC_signature_digest_sign_init() initialises a context for signing given a provider side signature context in the I<ctx> parameter, and a pointer to a provider key object in the I<provkey> parameter. The I<params>, if not NULL, should be set on the context in a manner similar to @@ -388,6 +388,32 @@ was successful. Known answer tests can be performed if the random generator is overridden to supply known values that either pass or fail. +=item "fips-indicator" (B<OSSL_SIGNATURE_PARAM_FIPS_APPROVED_INDICATOR>) <int> + +A getter that returns 1 if the operation is FIPS approved, or 0 otherwise. +This may be used after calling either the sign or verify final functions. It may +return 0 if either the "digest-check" or the "key-check" are set to 0. +This option is used by the OpenSSL FIPS provider. + +=item "key-check" (B<OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK>) <int> + +If required this parameter should be set early via an init function +(e.g. OSSL_FUNC_signature_sign_init() or OSSL_FUNC_signature_verify_init()). +The default value of 1 causes an error during the init if the key is not FIPS +approved (e.g. The key has a security strength of less than 112 bits). +Setting this to 0 will ignore the error and set the approved "indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + +=item "digest-check" (B<OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK>) <int> + +If required this parameter should be set before the signature digest is set. +The default value of 1 causes an error when the digest is set if the digest is +not FIPS approved (e.g. SHA1 is used for signing). Setting this to 0 will ignore +the error and set the approved "fips-indicator" to 0. +This option is used by the OpenSSL FIPS provider, and breaks FIPS compliance if +set to 0. + =back OSSL_FUNC_signature_gettable_ctx_params() and OSSL_FUNC_signature_settable_ctx_params() get a @@ -438,6 +464,8 @@ L<provider(7)> =head1 HISTORY The provider SIGNATURE interface was introduced in OpenSSL 3.0. +The Signature Parameters "fips-indicator", "key-check" and "digest-check" +were added in OpenSSL 3.4. =head1 COPYRIGHT diff --git a/providers/common/include/prov/fipsindicator.h b/providers/common/include/prov/fipsindicator.h index fbfa7e0790..0b6c52ed8c 100644 --- a/providers/common/include/prov/fipsindicator.h +++ b/providers/common/include/prov/fipsindicator.h @@ -116,6 +116,20 @@ void ossl_FIPS_IND_copy(OSSL_FIPS_IND *dst, const OSSL_FIPS_IND *src); #define OSSL_FIPS_IND_GET(ctx) &((ctx)->indicator) +int ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx, + const RSA *rsa, const char *desc, int protect); +# ifndef OPENSSL_NO_EC +int ossl_fips_ind_ec_key_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx, + const EC_GROUP *group, const char *desc, + int protect); +# endif +int ossl_fips_ind_digest_check(OSSL_FIPS_IND *ind, int id, OSSL_LIB_CTX *libctx, + const EVP_MD *md, const char *desc); +int ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND *ind, int id, + OSSL_LIB_CTX *libctx, + int nid, int sha1_allowed, + const char *desc); + #else # define OSSL_FIPS_IND_DECLARE # define OSSL_FIPS_IND_INIT(ctx) diff --git a/providers/common/include/prov/securitycheck.h b/providers/common/include/prov/securitycheck.h index 611c6d531b..4db5202c59 100644 --- a/providers/common/include/prov/securitycheck.h +++ b/providers/common/include/prov/securitycheck.h @@ -1,5 +1,5 @@ /* - * Copyright 2019-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2019-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -8,24 +8,24 @@ */ #include "crypto/types.h" +#include <openssl/ec.h> /* Functions that are common */ -int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation); -int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect); -int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign); -int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh); +int ossl_rsa_key_op_get_protect(const RSA *rsa, int operation, int *outprotect); +int ossl_rsa_check_key_size(const RSA *rsa, int protect); -int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md); -/* With security check enabled it can return -1 to indicate disallowed md */ -int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md, - int sha1_allowed); +#ifndef OPENSSL_NO_EC +int ossl_ec_check_curve_allowed(const EC_GROUP *group); +int ossl_ec_check_security_strength(const EC_GROUP *group, int protect); +#endif + +int ossl_dsa_check_key(const DSA *dsa, int sign); +int ossl_dh_check_key(const DH *dh); -/* Functions that are common */ int ossl_digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len); int ossl_digest_get_approved_nid(const EVP_MD *md); /* Functions that have different implementations for the FIPS_MODULE */ -int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, - int sha1_allowed); +int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md); int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx); int ossl_tls1_prf_ems_check_enabled(OSSL_LIB_CTX *libctx); diff --git a/providers/common/securitycheck.c b/providers/common/securitycheck.c index 0d3acdbe56..e8e1c2400a 100644 --- a/providers/common/securitycheck.c +++ b/providers/common/securitycheck.c @@ -19,14 +19,9 @@ #include <openssl/core_names.h> #include <openssl/obj_mac.h> #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" -/* - * FIPS requires a minimum security strength of 112 bits (for encryption or - * signing), and for legacy purposes 80 bits (for decryption or verifying). - * Set protect = 1 for encryption or signing operations, or 0 otherwise. See - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf. - */ -int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation) +int ossl_rsa_key_op_get_protect(const RSA *rsa, int operation, int *outprotect) { int protect = 0; @@ -56,25 +51,42 @@ int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation) "invalid operation: %d", operation); return 0; } + *outprotect = protect; + return 1; +} -#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) { - int sz = RSA_bits(rsa); +/* + * FIPS requires a minimum security strength of 112 bits (for encryption or + * signing), and for legacy purposes 80 bits (for decryption or verifying). + * Set protect = 1 for encryption or signing operations, or 0 otherwise. See + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf. + */ +int ossl_rsa_check_key_size(const RSA *rsa, int protect) +{ + int sz = RSA_bits(rsa); - if (protect ? (sz < 2048) : (sz < 1024)) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH, - "operation: %d", operation); - return 0; - } - } -#else - /* make protect used */ - (void)protect; -#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + if (protect ? (sz < 2048) : (sz < 1024)) + return 0; return 1; } #ifndef OPENSSL_NO_EC + +int ossl_ec_check_curve_allowed(const EC_GROUP *group) +{ + const char *curve_name; + int nid = EC_GROUP_get_curve_name(group); + + /* Explict curves are not FIPS approved */ + if (nid == NID_undef) + return 0; + /* Only NIST curves are FIPS approved */ + curve_name = EC_curve_nid2nist(nid); + if (curve_name == NULL) + return 0; + return 1; +} + /* * In FIPS mode: * protect should be 1 for any operations that need 112 bits of security @@ -89,56 +101,25 @@ int ossl_rsa_check_key(OSSL_LIB_CTX *ctx, const RSA *rsa, int operation) * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf * "Table 2" */ -int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) +int ossl_ec_check_security_strength(const EC_GROUP *group, int protect) { -# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) { - int nid, strength; - const char *curve_name; - const EC_GROUP *group = EC_KEY_get0_group(ec); - - if (group == NULL) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE, "No group"); - return 0; - } - nid = EC_GROUP_get_curve_name(group); - if (nid == NID_undef) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE, - "Explicit curves are not allowed in fips mode"); - return 0; - } - - curve_name = EC_curve_nid2nist(nid); - if (curve_name == NULL) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE, - "Curve %s is not approved in FIPS mode", curve_name); - return 0; - } - - /* - * For EC the security strength is the (order_bits / 2) - * e.g. P-224 is 112 bits. - */ - strength = EC_GROUP_order_bits(group) / 2; - /* The min security strength allowed for legacy verification is 80 bits */ - if (strength < 80) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE); - return 0; - } - - /* - * For signing or key agreement only allow curves with at least 112 bits of - * security strength - */ - if (protect && strength < 112) { - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_CURVE, - "Curve %s cannot be used for signing", curve_name); - return 0; - } - } -# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + /* + * For EC the security strength is the (order_bits / 2) + * e.g. P-224 is 112 bits. + */ + int strength = EC_GROUP_order_bits(group) / 2; + /* The min security strength allowed for legacy verification is 80 bits */ + if (strength < 80) + return 0; + /* + * For signing or key agreement only allow curves with at least 112 bits of + * security strength + */ + if (protect && strength < 112) + return 0; return 1; } + #endif /* OPENSSL_NO_EC */ #ifndef OPENSSL_NO_DSA @@ -147,48 +128,43 @@ int ossl_ec_check_key(OSSL_LIB_CTX *ctx, const EC_KEY *ec, int protect) * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf * "Table 2" */ -int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign) +int ossl_dsa_check_key(const DSA *dsa, int sign) { -# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) { - size_t L, N; - const BIGNUM *p, *q; - - if (dsa == NULL) - return 0; - - p = DSA_get0_p(dsa); - q = DSA_get0_q(dsa); - if (p == NULL || q == NULL) + size_t L, N; + const BIGNUM *p, *q; + + if (dsa == NULL) + return 0; + + p = DSA_get0_p(dsa); + q = DSA_get0_q(dsa); + if (p == NULL || q == NULL) + return 0; + + L = BN_num_bits(p); + N = BN_num_bits(q); + + /* + * For Digital signature verification DSA keys with < 112 bits of + * security strength, are still allowed for legacy + * use. The bounds given in SP 800-131Ar2 - Table 2 are + * (512 <= L < 2048 or 160 <= N < 224). + * + * We are a little stricter and insist that both minimums are met. + * For example a L = 256, N = 160 key *would* be allowed by SP 800-131Ar2 + * but we don't. + */ + if (!sign) { + if (L < 512 || N < 160) return 0; - - L = BN_num_bits(p); - N = BN_num_bits(q); - - /* - * For Digital signature verification DSA keys with < 112 bits of - * security strength, are still allowed for legacy - * use. The bounds given in SP 800-131Ar2 - Table 2 are - * (512 <= L < 2048 or 160 <= N < 224). - * - * We are a little stricter and insist that both minimums are met. - * For example a L = 256, N = 160 key *would* be allowed by SP 800-131Ar2 - * but we don't. - */ - if (!sign) { - if (L < 512 || N < 160) - return 0; - if (L < 2048 || N < 224) - return 1; - } - - /* Valid sizes for both sign and verify */ - if (L == 2048 && (N == 224 || N == 256)) /* 112 bits */ + if (L < 2048 || N < 224) return 1; - return (L == 3072 && N == 256); /* 128 bits */ } -# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ - return 1; + + /* Valid sizes for both sign and verify */ + if (L == 2048 && (N == 224 || N == 256)) /* 112 bits */ + return 1; + return (L == 3072 && N == 256); /* 128 bits */ } #endif /* OPENSSL_NO_DSA */ @@ -199,58 +175,30 @@ int ossl_dsa_check_key(OSSL_LIB_CTX *ctx, const DSA *dsa, int sign) * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and * "Appendix D" FFC Safe-prime Groups */ -int ossl_dh_check_key(OSSL_LIB_CTX *ctx, const DH *dh) +int ossl_dh_check_key(const DH *dh) { -# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) { - size_t L, N; - const BIGNUM *p, *q; + size_t L, N; + const BIGNUM *p, *q; - if (dh == NULL) - return 0; + if (dh == NULL) + return 0; - p = DH_get0_p(dh); - q = DH_get0_q(dh); - if (p == NULL || q == NULL) - return 0; + p = DH_get0_p(dh); + q = DH_get0_q(dh); + if (p == NULL || q == NULL) + return 0; - L = BN_num_bits(p); - if (L < 2048) - return 0; + L = BN_num_bits(p); + if (L < 2048) + return 0; - /* If it is a safe prime group then it is ok */ - if (DH_get_nid(dh)) - return 1; + /* If it is a safe prime group then it is ok */ + if (DH_get_nid(dh)) + return 1; - /* If not then it must be FFC, which only allows certain sizes. */ - N = BN_num_bits(q); + /* If not then it must be FFC, which only allows certain sizes. */ + N = BN_num_bits(q); - return (L == 2048 && (N == 224 || N == 256)); - } -# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ - return 1; + return (L == 2048 && (N == 224 || N == 256)); } #endif /* OPENSSL_NO_DH */ - -int ossl_digest_get_approved_nid_with_sha1(OSSL_LIB_CTX *ctx, const EVP_MD *md, - int sha1_allowed) -{ - int mdnid = ossl_digest_get_approved_nid(md); - -# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) { - if (mdnid == NID_undef || (mdnid == NID_sha1 && !sha1_allowed)) - mdnid = -1; /* disallowed by security checks */ - } -# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ - return mdnid; -} - -int ossl_digest_is_allowed(OSSL_LIB_CTX *ctx, const EVP_MD *md) -{ -# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) - return ossl_digest_get_approved_nid(md) != NID_undef; -# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ - return 1; -} diff --git a/providers/common/securitycheck_default.c b/providers/common/securitycheck_default.c index 246323493e..85e5fddd5a 100644 --- a/providers/common/securitycheck_default.c +++ b/providers/common/securitycheck_default.c @@ -28,8 +28,7 @@ int ossl_tls1_prf_ems_check_enabled(OSSL_LIB_CTX *libctx) return 0; } -int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, - ossl_unused int sha1_allowed) +int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md) { int mdnid; @@ -42,7 +41,7 @@ int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 }, }; - mdnid = ossl_digest_get_approved_nid_with_sha1(ctx, md, 1); + mdnid = ossl_digest_get_approved_nid(md); if (mdnid == NID_undef) mdnid = ossl_digest_md_to_nid(md, name_to_nid, OSSL_NELEM(name_to_nid)); return mdnid; diff --git a/providers/common/securitycheck_fips.c b/providers/common/securitycheck_fips.c index d1262d8795..84579dc7b3 100644 --- a/providers/common/securitycheck_fips.c +++ b/providers/common/securitycheck_fips.c @@ -18,6 +18,7 @@ #include <openssl/core_names.h> #include <openssl/obj_mac.h> #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include "prov/fipscommon.h" int ossl_securitycheck_enabled(OSSL_LIB_CTX *libctx) @@ -34,12 +35,90 @@ int ossl_tls1_prf_ems_check_enabled(OSSL_LIB_CTX *libctx) return FIPS_tls_prf_ems_check(libctx); } -int ossl_digest_rsa_sign_get_md_nid(OSSL_LIB_CTX *ctx, const EVP_MD *md, - int sha1_allowed) +int ossl_digest_rsa_sign_get_md_nid(const EVP_MD *md) { -#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) - if (ossl_securitycheck_enabled(ctx)) - return ossl_digest_get_approved_nid_with_sha1(ctx, md, sha1_allowed); -#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ return ossl_digest_get_approved_nid(md); } + +int ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND *ind, int id, + OSSL_LIB_CTX *libctx, + const RSA *rsa, const char *desc, int protect) +{ + int key_approved = ossl_rsa_check_key_size(rsa, protect); + + if (!key_approved) { + if (!ossl_FIPS_IND_on_unapproved(ind, id, libctx, desc, "Key size", + ossl_securitycheck_enabled)) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH, + "operation: %s", desc); + return 0; + } + } + return 1; +} + +# ifndef OPENSSL_NO_EC +int ossl_fips_ind_ec_key_check(OSSL_FIPS_IND *ind, int id, + OSSL_LIB_CTX *libctx, + const EC_GROUP *group, const char *desc, + int protect) +{ + int curve_allowed, strength_allowed; + + if (group == NULL) + return 0; + + curve_allowed = ossl_ec_check_curve_allowed(group); + strength_allowed = ossl_ec_check_security_strength(group, protect); + + if (!strength_allowed || !curve_allowed) { + if (!ossl_FIPS_IND_on_unapproved(ind, id, libctx, desc, "EC Key", + ossl_securitycheck_enabled)) { + if (!curve_allowed) + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_CURVE); + if (!strength_allowed) + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return 1; +} +#endif + +int ossl_fips_ind_digest_check(OSSL_FIPS_IND *ind, int id, + OSSL_LIB_CTX *libctx, + const EVP_MD *md, const char *desc) +{ + int approved = (ossl_digest_get_approved_nid(md) != NID_undef); + + if (!approved) { + if (!ossl_FIPS_IND_on_unapproved(ind, id, libctx, desc, "Digest", + ossl_securitycheck_enabled)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + return 0; + } + } + return 1; +} + +int ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND *ind, int id, + OSSL_LIB_CTX *libctx, + int nid, int sha1_allowed, + const char *desc) +{ + int approved; + + if (nid == NID_undef) + approved = 0; + else + approved = sha1_allowed || nid != NID_sha1; + + if (!approved) { + if (!ossl_FIPS_IND_on_unapproved(ind, id, libctx, desc, "Digest SHA1", + ossl_securitycheck_enabled)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_DIGEST); + return 0; + } + } + return 1; +} diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c index 71bfa344d4..f88cc96a75 100644 --- a/providers/implementations/asymciphers/rsa_enc.c +++ b/providers/implementations/asymciphers/rsa_enc.c @@ -30,6 +30,7 @@ #include "prov/implementations.h" #include "prov/providercommon.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include <stdlib.h> @@ -77,6 +78,7 @@ typedef struct { unsigned int alt_version; /* PKCS#1 v1.5 decryption mode */ unsigned int implicit_rejection; + OSSL_FIPS_IND_DECLARE } PROV_RSA_CTX; static void *rsa_newctx(void *provctx) @@ -89,21 +91,22 @@ static void *rsa_newctx(void *provctx) if (prsactx == NULL) return NULL; prsactx->libctx = PROV_LIBCTX_OF(provctx); + OSSL_FIPS_IND_INIT(prsactx) return prsactx; } static int rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[], - int operation) + int operation, const char *desc) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + int protect = 0; if (!ossl_prov_is_running() || prsactx == NULL || vrsa == NULL) return 0; - if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation)) + if (!ossl_rsa_key_op_get_protect(vrsa, operation, &protect)) return 0; - if (!RSA_up_ref(vrsa)) return 0; RSA_free(prsactx->rsa); @@ -120,19 +123,31 @@ static int rsa_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[], ERR_raise(ERR_LIB_PROV, ERR_R_INTERNAL_ERROR); return 0; } - return rsa_set_ctx_params(prsactx, params); + + OSSL_FIPS_IND_SET_APPROVED(prsactx) + if (!rsa_set_ctx_params(prsactx, params)) + return 0; +#ifdef FIPS_MODULE + if (!ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND_GET(prsactx), + OSSL_FIPS_IND_SETTABLE0, prsactx->libctx, + prsactx->rsa, desc, protect)) + return 0; +#endif + return 1; } static int rsa_encrypt_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) { - return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCRYPT); + return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCRYPT, + "RSA Encrypt Init"); } static int rsa_decrypt_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) { - return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT); + return rsa_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECRYPT, + "RSA Decrypt Init"); } static int rsa_encrypt(void *vprsactx, unsigned char *out, size_t *outlen, @@ -408,7 +423,8 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) p = OSSL_PARAM_locate(params, OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION); if (p != NULL && !OSSL_PARAM_set_uint(p, prsactx->implicit_rejection)) return 0; - + if (!OSSL_FIPS_IND_GET_CTX_PARAM(prsactx, params)) + return 0; return 1; } @@ -421,6 +437,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, NULL), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -443,6 +460,10 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(prsactx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_ASYM_CIPHER_PARAM_FIPS_KEY_CHECK)) + return 0; + p = OSSL_PARAM_locate_const(params, OSSL_ASYM_CIPHER_PARAM_OAEP_DIGEST); if (p != NULL) { str = mdname; @@ -566,7 +587,6 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) return 0; prsactx->implicit_rejection = implicit_rejection; } - return 1; } @@ -580,6 +600,7 @@ static const OSSL_PARAM known_settable_ctx_params[] = { OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION, NULL), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION, NULL), OSSL_PARAM_uint(OSSL_ASYM_CIPHER_PARAM_IMPLICIT_REJECTION, NULL), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_ASYM_CIPHER_PARAM_FIPS_KEY_CHECK) OSSL_PARAM_END }; diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c index 20b8fa0078..717706a174 100644 --- a/providers/implementations/exchange/dh_exch.c +++ b/providers/implementations/exchange/dh_exch.c @@ -25,6 +25,7 @@ #include "prov/implementations.h" #include "prov/provider_ctx.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include "crypto/dh.h" static OSSL_FUNC_keyexch_newctx_fn dh_newctx; @@ -76,6 +77,7 @@ typedef struct { /* KDF output length */ size_t kdf_outlen; char *kdf_cekalg; + OSSL_FIPS_IND_DECLARE } PROV_DH_CTX; static void *dh_newctx(void *provctx) @@ -88,11 +90,36 @@ static void *dh_newctx(void *provctx) pdhctx = OPENSSL_zalloc(sizeof(PROV_DH_CTX)); if (pdhctx == NULL) return NULL; + OSSL_FIPS_IND_INIT(pdhctx) pdhctx->libctx = PROV_LIBCTX_OF(provctx); pdhctx->kdf_type = PROV_DH_KDF_NONE; return pdhctx; } +#ifdef FIPS_MODULE +static int dh_check_key(PROV_DH_CTX *ctx) +{ + int key_approved = ossl_dh_check_key(ctx->dh); + + if (!key_approved) { + if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0, + ctx->libctx, "DH Init", "DH Key", + ossl_securitycheck_enabled)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return 1; +} + +static int digest_check(PROV_DH_CTX *ctx, const EVP_MD *md) +{ + return ossl_fips_ind_digest_check(OSSL_FIPS_IND_GET(ctx), + OSSL_FIPS_IND_SETTABLE1, ctx->libctx, + md, "DH Set Ctx"); +} +#endif + static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[]) { PROV_DH_CTX *pdhctx = (PROV_DH_CTX *)vpdhctx; @@ -105,8 +132,15 @@ static int dh_init(void *vpdhctx, void *vdh, const OSSL_PARAM params[]) DH_free(pdhctx->dh); pdhctx->dh = vdh; pdhctx->kdf_type = PROV_DH_KDF_NONE; - return dh_set_ctx_params(pdhctx, params) - && ossl_dh_check_key(pdhctx->libctx, vdh); + + OSSL_FIPS_IND_SET_APPROVED(pdhctx) + if (!dh_set_ctx_params(pdhctx, params)) + return 0; +#ifdef FIPS_MODULE + if (!dh_check_key(pdhctx)) + return 0; +#endif + return 1; } /* The 2 parties must share the same domain parameters */ @@ -317,6 +351,13 @@ static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdhctx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK)) + return 0; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdhctx, OSSL_FIPS_IND_SETTABLE1, params, + OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK)) + return 0; + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_TYPE); if (p != NULL) { str = name; @@ -351,11 +392,13 @@ static int dh_set_ctx_params(void *vpdhctx, const OSSL_PARAM params[]) pdhctx->kdf_md = EVP_MD_fetch(pdhctx->libctx, name, mdprops); if (pdhctx->kdf_md == NULL) return 0; - if (!ossl_digest_is_allowed(pdhctx->libctx, pdhctx->kdf_md)) { +#ifdef FIPS_MODULE + if (!digest_check(pdhctx, pdhctx->kdf_md)) { EVP_MD_free(pdhctx->kdf_md); pdhctx->kdf_md = NULL; return 0; } +#endif } p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); @@ -416,6 +459,8 @@ static const OSSL_PARAM known_settable_ctx_params[] = { OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK) + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; @@ -432,6 +477,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL, 0), OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_CEK_ALG, NULL, 0), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -490,7 +536,8 @@ static int dh_get_ctx_params(void *vpdhctx, OSSL_PARAM params[]) && !OSSL_PARAM_set_utf8_string(p, pdhctx->kdf_cekalg == NULL ? "" : pdhctx->kdf_cekalg)) return 0; - + if (!OSSL_FIPS_IND_GET_CTX_PARAM(pdhctx, params)) + return 0; return 1; } diff --git a/providers/implementations/exchange/ecdh_exch.c b/providers/implementations/exchange/ecdh_exch.c index 5b8412aba1..85b782a39d 100644 --- a/providers/implementations/exchange/ecdh_exch.c +++ b/providers/implementations/exchange/ecdh_exch.c @@ -26,6 +26,7 @@ #include "prov/providercommon.h" #include "prov/implementations.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include "crypto/ec.h" /* ossl_ecdh_kdf_X9_63() */ static OSSL_FUNC_keyexch_newctx_fn ecdh_newctx; @@ -77,6 +78,7 @@ typedef struct { size_t kdf_ukmlen; /* KDF output length */ size_t kdf_outlen; + OSSL_FIPS_IND_DECLARE } PROV_ECDH_CTX; static @@ -94,6 +96,7 @@ void *ecdh_newctx(void *provctx) pectx->libctx = PROV_LIBCTX_OF(provctx); pectx->cofactor_mode = -1; pectx->kdf_type = PROV_ECDH_KDF_NONE; + OSSL_FIPS_IND_INIT(pectx) return (void *)pectx; } @@ -106,14 +109,24 @@ int ecdh_init(void *vpecdhctx, void *vecdh, const OSSL_PARAM params[]) if (!ossl_prov_is_running() || pecdhctx == NULL || vecdh == NULL + || (EC_KEY_get0_group(vecdh) == NULL) || !EC_KEY_up_ref(vecdh)) return 0; EC_KEY_free(pecdhctx->k); pecdhctx->k = vecdh; pecdhctx->cofactor_mode = -1; pecdhctx->kdf_type = PROV_ECDH_KDF_NONE; - return ecdh_set_ctx_params(pecdhctx, params) - && ossl_ec_check_key(pecdhctx->libctx, vecdh, 1); + + OSSL_FIPS_IND_SET_APPROVED(pecdhctx) + if (!ecdh_set_ctx_params(pecdhctx, params)) + return 0; +#ifdef FIPS_MODULE + if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(pecdhctx), + OSSL_FIPS_IND_SETTABLE0, pecdhctx->libctx, + EC_KEY_get0_group(vecdh), "ECDH Init", 1)) + return 0; +#endif + return 1; } static @@ -146,9 +159,16 @@ int ecdh_set_peer(void *vpecdhctx, void *vecdh) if (!ossl_prov_is_running() || pecdhctx == NULL || vecdh == NULL - || !ecdh_match_params(pecdhctx->k, vecdh) - || !ossl_ec_check_key(pecdhctx->libctx, vecdh, 1) - || !EC_KEY_up_ref(vecdh)) + || !ecdh_match_params(pecdhctx->k, vecdh)) + return 0; +#ifdef FIPS_MODULE + if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(pecdhctx), + OSSL_FIPS_IND_SETTABLE0, pecdhctx->libctx, + EC_KEY_get0_group(vecdh), "ECDH Set Peer", + 1)) + return 0; +#endif + if (!EC_KEY_up_ref(vecdh)) return 0; EC_KEY_free(pecdhctx->peerk); @@ -237,6 +257,13 @@ int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pectx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK)) + return 0; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pectx, OSSL_FIPS_IND_SETTABLE1, params, + OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK)) + return 0; + p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_EC_ECDH_COFACTOR_MODE); if (p != NULL) { int mode; @@ -285,11 +312,15 @@ int ecdh_set_ctx_params(void *vpecdhctx, const OSSL_PARAM params[]) pectx->kdf_md = EVP_MD_fetch(pectx->libctx, name, mdprops); if (pectx->kdf_md == NULL) return 0; - if (!ossl_digest_is_allowed(pectx->libctx, pectx->kdf_md)) { +#ifdef FIPS_MODULE + if (!ossl_fips_ind_digest_check(OSSL_FIPS_IND_GET(pectx), + OSSL_FIPS_IND_SETTABLE1, pectx->libctx, + pectx->kdf_md, "ECDH Set Ctx")) { EVP_MD_free(pectx->kdf_md); pectx->kdf_md = NULL; return 0; } +#endif } p = OSSL_PARAM_locate_const(params, OSSL_EXCHANGE_PARAM_KDF_OUTLEN); @@ -323,6 +354,8 @@ static const OSSL_PARAM known_settable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_EXCHANGE_PARAM_KDF_DIGEST_PROPS, NULL, 0), OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_octet_string(OSSL_EXCHANGE_PARAM_KDF_UKM, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_EXCHANGE_PARAM_FIPS_KEY_CHECK) + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_EXCHANGE_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; @@ -390,7 +423,8 @@ int ecdh_get_ctx_params(void *vpecdhctx, OSSL_PARAM params[]) if (p != NULL && !OSSL_PARAM_set_octet_ptr(p, pectx->kdf_ukm, pectx->kdf_ukmlen)) return 0; - + if (!OSSL_FIPS_IND_GET_CTX_PARAM(pectx, params)) + return 0; return 1; } @@ -401,6 +435,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_size_t(OSSL_EXCHANGE_PARAM_KDF_OUTLEN, NULL), OSSL_PARAM_DEFN(OSSL_EXCHANGE_PARAM_KDF_UKM, OSSL_PARAM_OCTET_PTR, NULL, 0), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; diff --git a/providers/implementations/kdfs/tls1_prf.c b/providers/implementations/kdfs/tls1_prf.c index 2792486924..cf4b656546 100644 --- a/providers/implementations/kdfs/tls1_prf.c +++ b/providers/implementations/kdfs/tls1_prf.c @@ -1,5 +1,5 @@ /* - * Copyright 2016-2023 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the "License"). You may not use * this file except in compliance with the License. You can obtain a copy @@ -68,6 +68,7 @@ #include "prov/implementations.h" #include "prov/provider_util.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include "internal/e_os.h" #include "internal/safe_math.h" @@ -106,6 +107,7 @@ typedef struct { /* Concatenated seed data */ unsigned char *seed; size_t seedlen; + OSSL_FIPS_IND_DECLARE } TLS1_PRF; static void *kdf_tls1_prf_new(void *provctx) @@ -115,8 +117,10 @@ static void *kdf_tls1_prf_new(void *provctx) if (!ossl_prov_is_running()) return NULL; - if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) + if ((ctx = OPENSSL_zalloc(sizeof(*ctx))) != NULL) { ctx->provctx = provctx; + OSSL_FIPS_IND_INIT(ctx) + } return ctx; } @@ -161,6 +165,7 @@ static void *kdf_tls1_prf_dup(void *vctx) if (!ossl_prov_memdup(src->seed, src->seedlen, &dest->seed, &dest->seedlen)) goto err; + OSSL_FIPS_IND_COPY(dest, src) } return dest; @@ -169,11 +174,39 @@ static void *kdf_tls1_prf_dup(void *vctx) return NULL; } +#ifdef FIPS_MODULE + +static int fips_ems_check_passed(TLS1_PRF *ctx) +{ + OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); + /* + * Check that TLS is using EMS. + * + * The seed buffer is prepended with a label. + * If EMS mode is enforced then the label "master secret" is not allowed, + * We do the check this way since the PRF is used for other purposes, as well + * as "extended master secret". + */ + int ems_approved = (ctx->seedlen < TLS_MD_MASTER_SECRET_CONST_SIZE + || memcmp(ctx->seed, TLS_MD_MASTER_SECRET_CONST, + TLS_MD_MASTER_SECRET_CONST_SIZE) != 0); + + if (!ems_approved) { + if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0, + libctx, "TLS_PRF", "EMS", + ossl_tls1_prf_ems_check_enabled)) { + ERR_raise(ERR_LIB_PROV, PROV_R_EMS_NOT_ENABLED); + return 0; + } + } + return 1; +} +#endif + static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen, const OSSL_PARAM params[]) { TLS1_PRF *ctx = (TLS1_PRF *)vctx; - OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(ctx->provctx); if (!ossl_prov_is_running() || !kdf_tls1_prf_set_ctx_params(ctx, params)) return 0; @@ -195,20 +228,10 @@ static int kdf_tls1_prf_derive(void *vctx, unsigned char *key, size_t keylen, return 0; } - /* - * The seed buffer is prepended with a label. - * If EMS mode is enforced then the label "master secret" is not allowed, - * We do the check this way since the PRF is used for other purposes, as well - * as "extended master secret". - */ - if (ossl_tls1_prf_ems_check_enabled(libctx)) { - if (ctx->seedlen >= TLS_MD_MASTER_SECRET_CONST_SIZE - && memcmp(ctx->seed, TLS_MD_MASTER_SECRET_CONST, - TLS_MD_MASTER_SECRET_CONST_SIZE) == 0) { - ERR_raise(ERR_LIB_PROV, PROV_R_EMS_NOT_ENABLED); - return 0; - } - } +#ifdef FIPS_MODULE + if (!fips_ems_check_passed(ctx)) + return 0; +#endif return tls1_prf_alg(ctx->P_hash, ctx->P_sha1, ctx->sec, ctx->seclen, @@ -225,6 +248,10 @@ static int kdf_tls1_prf_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_KDF_PARAM_FIPS_EMS_CHECK)) + return 0; + if ((p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_DIGEST)) != NULL) { if (OPENSSL_strcasecmp(p->data, SN_md5_sha1) == 0) { if (!ossl_prov_macctx_load_from_params(&ctx->P_hash, params, @@ -289,6 +316,7 @@ static const OSSL_PARAM *kdf_tls1_prf_settable_ctx_params( OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_DIGEST, NULL, 0), OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SECRET, NULL, 0), OSSL_PARAM_octet_string(OSSL_KDF_PARAM_SEED, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KDF_PARAM_FIPS_EMS_CHECK) OSSL_PARAM_END }; return known_settable_ctx_params; @@ -300,7 +328,9 @@ static int kdf_tls1_prf_get_ctx_params(void *vctx, OSSL_PARAM params[]) if ((p = OSSL_PARAM_locate(params, OSSL_KDF_PARAM_SIZE)) != NULL) return OSSL_PARAM_set_size_t(p, SIZE_MAX); - return -2; + if (!OSSL_FIPS_IND_GET_CTX_PARAM(((TLS1_PRF *)vctx), params)) + return 0; + return 1; } static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params( @@ -308,6 +338,7 @@ static const OSSL_PARAM *kdf_tls1_prf_gettable_ctx_params( { static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_size_t(OSSL_KDF_PARAM_SIZE, NULL), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; return known_gettable_ctx_params; diff --git a/providers/implementations/kem/rsa_kem.c b/providers/implementations/kem/rsa_kem.c index ff22ddffcf..28925b7d13 100644 --- a/providers/implementations/kem/rsa_kem.c +++ b/providers/implementations/kem/rsa_kem.c @@ -27,6 +27,7 @@ #include "prov/provider_ctx.h" #include "prov/implementations.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" static OSSL_FUNC_kem_newctx_fn rsakem_newctx; static OSSL_FUNC_kem_encapsulate_init_fn rsakem_encapsulate_init; @@ -56,6 +57,7 @@ typedef struct { OSSL_LIB_CTX *libctx; RSA *rsa; int op; + OSSL_FIPS_IND_DECLARE } PROV_RSA_CTX; static const OSSL_ITEM rsakem_opname_id_map[] = { @@ -89,6 +91,7 @@ static void *rsakem_newctx(void *provctx) return NULL; prsactx->libctx = PROV_LIBCTX_OF(provctx); prsactx->op = KEM_OP_UNDEFINED; + OSSL_FIPS_IND_INIT(prsactx) return prsactx; } @@ -119,44 +122,62 @@ static void *rsakem_dupctx(void *vprsactx) } static int rsakem_init(void *vprsactx, void *vrsa, - const OSSL_PARAM params[], int operation) + const OSSL_PARAM params[], int operation, + const char *desc) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + int protect = 0; if (prsactx == NULL || vrsa == NULL) return 0; - if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation)) + if (!ossl_rsa_key_op_get_protect(vrsa, operation, &protect)) return 0; - if (!RSA_up_ref(vrsa)) return 0; RSA_free(prsactx->rsa); prsactx->rsa = vrsa; - return rsakem_set_ctx_params(prsactx, params); + OSSL_FIPS_IND_SET_APPROVED(prsactx) + if (!rsakem_set_ctx_params(prsactx, params)) + return 0; +#ifdef FIPS_MODULE + if (!ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND_GET(prsactx), + OSSL_FIPS_IND_SETTABLE0, prsactx->libctx, + prsactx->rsa, desc, protect)) + return 0; +#endif + return 1; } static int rsakem_encapsulate_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) { - return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCAPSULATE); + return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_ENCAPSULATE, + "RSA Encapsulate Init"); } static int rsakem_decapsulate_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) { - return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECAPSULATE); + return rsakem_init(vprsactx, vrsa, params, EVP_PKEY_OP_DECAPSULATE, + "RSA Decapsulate Init"); } static int rsakem_get_ctx_params(void *vprsactx, OSSL_PARAM *params) { PROV_RSA_CTX *ctx = (PROV_RSA_CTX *)vprsactx; - return ctx != NULL; + if (ctx == NULL) + return 0; + + if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params)) + return 0; + return 1; } static const OSSL_PARAM known_gettable_rsakem_ctx_params[] = { + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -177,7 +198,9 @@ static int rsakem_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) if (params == NULL) return 1; - + if (!OSSL_FIPS_IND_SET_CTX_PARAM(prsactx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_KEM_PARAM_FIPS_KEY_CHECK)) + return 0; p = OSSL_PARAM_locate_const(params, OSSL_KEM_PARAM_OPERATION); if (p != NULL) { if (p->data_type != OSSL_PARAM_UTF8_STRING) @@ -192,6 +215,7 @@ static int rsakem_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) static const OSSL_PARAM known_settable_rsakem_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_KEM_PARAM_OPERATION, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_KEM_PARAM_FIPS_KEY_CHECK) OSSL_PARAM_END }; diff --git a/providers/implementations/rands/drbg.c b/providers/implementations/rands/drbg.c index 253131b10d..230bba8ae6 100644 --- a/providers/implementations/rands/drbg.c +++ b/providers/implementations/rands/drbg.c @@ -935,7 +935,8 @@ int ossl_drbg_get_ctx_params(PROV_DRBG *drbg, OSSL_PARAM params[]) p = OSSL_PARAM_locate(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL); if (p != NULL && !OSSL_PARAM_set_time_t(p, drbg->reseed_time_interval)) return 0; - + if (!OSSL_FIPS_IND_GET_CTX_PARAM(drbg, params)) + return 0; return 1; } @@ -990,13 +991,13 @@ int ossl_drbg_set_ctx_params(PROV_DRBG *drbg, const OSSL_PARAM params[]) p = OSSL_PARAM_locate_const(params, OSSL_DRBG_PARAM_RESEED_TIME_INTERVAL); if (p != NULL && !OSSL_PARAM_get_time_t(p, &drbg->reseed_time_interval)) return 0; + return 1; } -/* Confirm digest is allowed to be used with a DRBG */ -int ossl_drbg_verify_digest(ossl_unused OSSL_LIB_CTX *libctx, const EVP_MD *md) -{ #ifdef FIPS_MODULE +static int digest_allowed(const EVP_MD *md) +{ /* FIPS 140-3 IG D.R limited DRBG digests to a specific set */ static const char *const allowed_digests[] = { "SHA1", /* SHA 1 allowed */ @@ -1005,12 +1006,28 @@ int ossl_drbg_verify_digest(ossl_unused OSSL_LIB_CTX *libctx, const EVP_MD *md) }; size_t i; - if (FIPS_restricted_drbg_digests_enabled(libctx)) { - for (i = 0; i < OSSL_NELEM(allowed_digests); i++) - if (EVP_MD_is_a(md, allowed_digests[i])) - return 1; - ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED); - return 0; + for (i = 0; i < OSSL_NELEM(allowed_digests); i++) { + if (EVP_MD_is_a(md, allowed_digests[i])) + return 1; + } + return 0; +} +#endif + +/* Confirm digest is allowed to be used with a DRBG */ +int ossl_drbg_verify_digest(PROV_DRBG *drbg, OSSL_LIB_CTX *libctx, + const EVP_MD *md) +{ +#ifdef FIPS_MODULE + int approved = digest_allowed(md); + + if (!approved) { + if (!OSSL_FIPS_IND_ON_UNAPPROVED(drbg, OSSL_FIPS_IND_SETTABLE0, + libctx, "DRBG", "Digest", + FIPS_restricted_drbg_digests_enabled)) { + ERR_raise(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED); + return 0; + } } #endif /* Outside of FIPS, any digests that are not XOF are allowed */ diff --git a/providers/implementations/rands/drbg_ctr.c b/providers/implementations/rands/drbg_ctr.c index 0c4553ad58..abd0b1a1c8 100644 --- a/providers/implementations/rands/drbg_ctr.c +++ b/providers/implementations/rands/drbg_ctr.c @@ -625,6 +625,7 @@ static int drbg_ctr_new(PROV_DRBG *drbg) ctr->use_df = 1; drbg->data = ctr; + OSSL_FIPS_IND_INIT(drbg) return drbg_ctr_init_lengths(drbg); } @@ -697,6 +698,7 @@ static const OSSL_PARAM *drbg_ctr_gettable_ctx_params(ossl_unused void *vctx, OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_CIPHER, NULL, 0), OSSL_PARAM_int(OSSL_DRBG_PARAM_USE_DF, NULL), OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON, + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; return known_gettable_ctx_params; diff --git a/providers/implementations/rands/drbg_hash.c b/providers/implementations/rands/drbg_hash.c index bc401b72a2..458b356b82 100644 --- a/providers/implementations/rands/drbg_hash.c +++ b/providers/implementations/rands/drbg_hash.c @@ -424,6 +424,8 @@ static int drbg_hash_new(PROV_DRBG *ctx) if (hash == NULL) return 0; + OSSL_FIPS_IND_INIT(ctx) + ctx->data = hash; ctx->seedlen = HASH_PRNG_MAX_SEEDLEN; ctx->max_entropylen = DRBG_MAX_LENGTH; @@ -496,6 +498,7 @@ static const OSSL_PARAM *drbg_hash_gettable_ctx_params(ossl_unused void *vctx, static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0), OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON, + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; return known_gettable_ctx_params; @@ -509,12 +512,16 @@ static int drbg_hash_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[] const EVP_MD *md; int md_size; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)) + return 0; + if (!ossl_prov_digest_load_from_params(&hash->digest, params, libctx)) return 0; md = ossl_prov_digest_md(&hash->digest); if (md != NULL) { - if (!ossl_drbg_verify_digest(libctx, md)) + if (!ossl_drbg_verify_digest(ctx, libctx, md)) return 0; /* Error already raised for us */ /* These are taken from SP 800-90 10.1 Table 2 */ @@ -561,6 +568,7 @@ static const OSSL_PARAM *drbg_hash_settable_ctx_params(ossl_unused void *vctx, OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_PROPERTIES, NULL, 0), OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0), OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON, + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; return known_settable_ctx_params; diff --git a/providers/implementations/rands/drbg_hmac.c b/providers/implementations/rands/drbg_hmac.c index 5ebbe52e61..43c75bf434 100644 --- a/providers/implementations/rands/drbg_hmac.c +++ b/providers/implementations/rands/drbg_hmac.c @@ -316,6 +316,8 @@ static int drbg_hmac_new(PROV_DRBG *drbg) if (hmac == NULL) return 0; + OSSL_FIPS_IND_INIT(drbg) + drbg->data = hmac; /* See SP800-57 Part1 Rev4 5.6.1 Table 3 */ drbg->max_entropylen = DRBG_MAX_LENGTH; @@ -399,6 +401,7 @@ static const OSSL_PARAM *drbg_hmac_gettable_ctx_params(ossl_unused void *vctx, OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0), OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0), OSSL_PARAM_DRBG_GETTABLE_CTX_COMMON, + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; return known_gettable_ctx_params; @@ -412,11 +415,15 @@ static int drbg_hmac_set_ctx_params_locked(void *vctx, const OSSL_PARAM params[] const EVP_MD *md; int md_size; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK)) + return 0; + if (!ossl_prov_digest_load_from_params(&hmac->digest, params, libctx)) return 0; md = ossl_prov_digest_md(&hmac->digest); - if (md != NULL && !ossl_drbg_verify_digest(libctx, md)) + if (md != NULL && !ossl_drbg_verify_digest(ctx, libctx, md)) return 0; /* Error already raised for us */ if (!ossl_prov_macctx_load_from_params(&hmac->ctx, params, @@ -465,6 +472,7 @@ static const OSSL_PARAM *drbg_hmac_settable_ctx_params(ossl_unused void *vctx, OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_DRBG_PARAM_MAC, NULL, 0), OSSL_PARAM_DRBG_SETTABLE_CTX_COMMON, + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_DRBG_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; return known_settable_ctx_params; diff --git a/providers/implementations/rands/drbg_local.h b/providers/implementations/rands/drbg_local.h index 902dfc937d..f8907a3193 100644 --- a/providers/implementations/rands/drbg_local.h +++ b/providers/implementations/rands/drbg_local.h @@ -18,6 +18,7 @@ # include "internal/nelem.h" # include "internal/numbers.h" # include "prov/provider_ctx.h" +# include "prov/fipsindicator.h" /* How many times to read the TSC as a randomness source. */ # define TSC_READ_COUNT 4 @@ -171,6 +172,8 @@ struct prov_drbg_st { OSSL_CALLBACK *cleanup_entropy_fn; OSSL_INOUT_CALLBACK *get_nonce_fn; OSSL_CALLBACK *cleanup_nonce_fn; + + OSSL_FIPS_IND_DECLARE }; PROV_DRBG *ossl_rand_drbg_new @@ -255,6 +258,6 @@ void ossl_crngt_cleanup_entropy(PROV_DRBG *drbg, unsigned char *out, size_t outlen); /* Confirm digest is allowed to be used with a DRBG */ -int ossl_drbg_verify_digest(ossl_unused OSSL_LIB_CTX *libctx, const EVP_MD *md); +int ossl_drbg_verify_digest(PROV_DRBG *drbg, OSSL_LIB_CTX *libctx, const EVP_MD *md); #endif diff --git a/providers/implementations/signature/dsa_sig.c b/providers/implementations/signature/dsa_sig.c index 12cbdb4356..7df8adfdd5 100644 --- a/providers/implementations/signature/dsa_sig.c +++ b/providers/implementations/signature/dsa_sig.c @@ -30,6 +30,7 @@ #include "prov/implementations.h" #include "prov/provider_ctx.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include "crypto/dsa.h" #include "prov/der_dsa.h" @@ -88,6 +89,7 @@ typedef struct { EVP_MD *md; EVP_MD_CTX *mdctx; int operation; + OSSL_FIPS_IND_DECLARE } PROV_DSA_CTX; @@ -117,6 +119,7 @@ static void *dsa_newctx(void *provctx, const char *propq) pdsactx->libctx = PROV_LIBCTX_OF(provctx); pdsactx->flag_allow_md = 1; + OSSL_FIPS_IND_INIT(pdsactx) if (propq != NULL && (pdsactx->propq = OPENSSL_strdup(propq)) == NULL) { OPENSSL_free(pdsactx); pdsactx = NULL; @@ -125,19 +128,22 @@ static void *dsa_newctx(void *provctx, const char *propq) } static int dsa_setup_md(PROV_DSA_CTX *ctx, - const char *mdname, const char *mdprops) + const char *mdname, const char *mdprops, + const char *desc) { + EVP_MD *md = NULL; + if (mdprops == NULL) mdprops = ctx->propq; if (mdname != NULL) { - int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); WPACKET pkt; - EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); - int md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md, - sha1_allowed); + int md_nid; size_t mdname_len = strlen(mdname); + md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); + md_nid = ossl_digest_get_approved_nid(md); + if (md == NULL || md_nid < 0) { if (md == NULL) ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, @@ -148,16 +154,25 @@ static int dsa_setup_md(PROV_DSA_CTX *ctx, if (mdname_len >= sizeof(ctx->mdname)) ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, "%s exceeds name buffer length", mdname); - EVP_MD_free(md); - return 0; + goto err; + } +#ifdef FIPS_MODULE + { + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + + if (!ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND_GET(ctx), + OSSL_FIPS_IND_SETTABLE1, + ctx->libctx, md_nid, sha1_allowed, + desc)) + goto err; } +#endif if (!ctx->flag_allow_md) { if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest %s != %s", mdname, ctx->mdname); - EVP_MD_free(md); - return 0; + goto err; } EVP_MD_free(md); return 1; @@ -188,10 +203,31 @@ static int dsa_setup_md(PROV_DSA_CTX *ctx, OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); } return 1; +err: + EVP_MD_free(md); + return 0; +} + +#ifdef FIPS_MODULE +static int dsa_check_key(PROV_DSA_CTX *ctx, int sign, const char *desc) +{ + int approved = ossl_dsa_check_key(ctx->dsa, sign); + + if (!approved) { + if (!OSSL_FIPS_IND_ON_UNAPPROVED(ctx, OSSL_FIPS_IND_SETTABLE0, + ctx->libctx, desc, "DSA Key", + ossl_securitycheck_enabled)) { + ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); + return 0; + } + } + return 1; } +#endif static int dsa_signverify_init(void *vpdsactx, void *vdsa, - const OSSL_PARAM params[], int operation) + const OSSL_PARAM params[], int operation, + const char *desc) { PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; @@ -205,11 +241,6 @@ static int dsa_signverify_init(void *vpdsactx, void *vdsa, } if (vdsa != NULL) { - if (!ossl_dsa_check_key(pdsactx->libctx, vdsa, - operation == EVP_PKEY_OP_SIGN)) { - ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); - return 0; - } if (!DSA_up_ref(vdsa)) return 0; DSA_free(pdsactx->dsa); @@ -218,21 +249,27 @@ static int dsa_signverify_init(void *vpdsactx, void *vdsa, pdsactx->operation = operation; + OSSL_FIPS_IND_SET_APPROVED(pdsactx) if (!dsa_set_ctx_params(pdsactx, params)) return 0; - +#ifdef FIPS_MODULE + if (!dsa_check_key(pdsactx, operation == EVP_PKEY_OP_SIGN, desc)) + return 0; +#endif return 1; } static int dsa_sign_init(void *vpdsactx, void *vdsa, const OSSL_PARAM params[]) { - return dsa_signverify_init(vpdsactx, vdsa, params, EVP_PKEY_OP_SIGN); + return dsa_signverify_init(vpdsactx, vdsa, params, EVP_PKEY_OP_SIGN, + "DSA Sign Init"); } static int dsa_verify_init(void *vpdsactx, void *vdsa, const OSSL_PARAM params[]) { - return dsa_signverify_init(vpdsactx, vdsa, params, EVP_PKEY_OP_VERIFY); + return dsa_signverify_init(vpdsactx, vdsa, params, EVP_PKEY_OP_VERIFY, + "DSA Verify Init"); } static int dsa_sign(void *vpdsactx, unsigned char *sig, size_t *siglen, @@ -282,17 +319,17 @@ static int dsa_verify(void *vpdsactx, const unsigned char *sig, size_t siglen, static int dsa_digest_signverify_init(void *vpdsactx, const char *mdname, void *vdsa, const OSSL_PARAM params[], - int operation) + int operation, const char *desc) { PROV_DSA_CTX *pdsactx = (PROV_DSA_CTX *)vpdsactx; if (!ossl_prov_is_running()) return 0; - if (!dsa_signverify_init(vpdsactx, vdsa, params, operation)) + if (!dsa_signverify_init(vpdsactx, vdsa, params, operation, desc)) return 0; - if (!dsa_setup_md(pdsactx, mdname, NULL)) + if (!dsa_setup_md(pdsactx, mdname, NULL, desc)) return 0; pdsactx->flag_allow_md = 0; @@ -318,14 +355,16 @@ static int dsa_digest_sign_init(void *vpdsactx, const char *mdname, void *vdsa, const OSSL_PARAM params[]) { return dsa_digest_signverify_init(vpdsactx, mdname, vdsa, params, - EVP_PKEY_OP_SIGN); + EVP_PKEY_OP_SIGN, + "DSA Digest Sign Init"); } static int dsa_digest_verify_init(void *vpdsactx, const char *mdname, void *vdsa, const OSSL_PARAM params[]) { return dsa_digest_signverify_init(vpdsactx, mdname, vdsa, params, - EVP_PKEY_OP_VERIFY); + EVP_PKEY_OP_VERIFY, + "DSA Digest Verify Init"); } int dsa_digest_signverify_update(void *vpdsactx, const unsigned char *data, @@ -470,6 +509,8 @@ static int dsa_get_ctx_params(void *vpdsactx, OSSL_PARAM *params) p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE); if (p != NULL && !OSSL_PARAM_set_uint(p, pdsactx->nonce_type)) return 0; + if (!OSSL_FIPS_IND_GET_CTX_PARAM(pdsactx, params)) + return 0; return 1; } @@ -478,6 +519,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -497,6 +539,13 @@ static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdsactx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)) + return 0; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(pdsactx, OSSL_FIPS_IND_SETTABLE1, params, + OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)) + return 0; + p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_DIGEST); if (p != NULL) { char mdname[OSSL_MAX_NAME_SIZE] = "", *pmdname = mdname; @@ -510,14 +559,13 @@ static int dsa_set_ctx_params(void *vpdsactx, const OSSL_PARAM params[]) if (propsp != NULL && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops))) return 0; - if (!dsa_setup_md(pdsactx, mdname, mdprops)) + if (!dsa_setup_md(pdsactx, mdname, mdprops, "DSA Set Ctx")) return 0; } p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE); if (p != NULL && !OSSL_PARAM_get_uint(p, &pdsactx->nonce_type)) return 0; - return 1; } @@ -525,6 +573,8 @@ static const OSSL_PARAM settable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK) + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; diff --git a/providers/implementations/signature/ecdsa_sig.c b/providers/implementations/signature/ecdsa_sig.c index 7cf1f08381..28e102bd0f 100644 --- a/providers/implementations/signature/ecdsa_sig.c +++ b/providers/implementations/signature/ecdsa_sig.c @@ -30,6 +30,7 @@ #include "prov/implementations.h" #include "prov/provider_ctx.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #include "crypto/ec.h" #include "prov/der_ec.h" @@ -105,6 +106,7 @@ typedef struct { #endif /* If this is set then the generated k is not random */ unsigned int nonce_type; + OSSL_FIPS_IND_DECLARE } PROV_ECDSA_CTX; static void *ecdsa_newctx(void *provctx, const char *propq) @@ -118,6 +120,7 @@ static void *ecdsa_newctx(void *provctx, const char *propq) if (ctx == NULL) return NULL; + OSSL_FIPS_IND_INIT(ctx) ctx->flag_allow_md = 1; ctx->libctx = PROV_LIBCTX_OF(provctx); if (propq != NULL && (ctx->propq = OPENSSL_strdup(propq)) == NULL) { @@ -128,7 +131,8 @@ static void *ecdsa_newctx(void *provctx, const char *propq) } static int ecdsa_signverify_init(void *vctx, void *ec, - const OSSL_PARAM params[], int operation) + const OSSL_PARAM params[], int operation, + const char *desc) { PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx; @@ -142,8 +146,6 @@ static int ecdsa_signverify_init(void *vctx, void *ec, } if (ec != NULL) { - if (!ossl_ec_check_key(ctx->libctx, ec, operation == EVP_PKEY_OP_SIGN)) - return 0; if (!EC_KEY_up_ref(ec)) return 0; EC_KEY_free(ctx->ec); @@ -152,20 +154,29 @@ static int ecdsa_signverify_init(void *vctx, void *ec, ctx->operation = operation; + OSSL_FIPS_IND_SET_APPROVED(ctx) if (!ecdsa_set_ctx_params(ctx, params)) return 0; - +#ifdef FIPS_MODULE + if (!ossl_fips_ind_ec_key_check(OSSL_FIPS_IND_GET(ctx), + OSSL_FIPS_IND_SETTABLE0, ctx->libctx, + EC_KEY_get0_group(ctx->ec), desc, + operation == EVP_PKEY_OP_SIGN)) + return 0; +#endif return 1; } static int ecdsa_sign_init(void *vctx, void *ec, const OSSL_PARAM params[]) { - return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_SIGN); + return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_SIGN, + "ECDSA Sign Init"); } static int ecdsa_verify_init(void *vctx, void *ec, const OSSL_PARAM params[]) { - return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_VERIFY); + return ecdsa_signverify_init(vctx, ec, params, EVP_PKEY_OP_VERIFY, + "ECDSA Verify Init"); } static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen, @@ -223,11 +234,11 @@ static int ecdsa_verify(void *vctx, const unsigned char *sig, size_t siglen, } static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx, const char *mdname, - const char *mdprops) + const char *mdprops, const char *desc) { EVP_MD *md = NULL; size_t mdname_len; - int md_nid, sha1_allowed, md_size; + int md_nid, md_size; WPACKET pkt; if (mdname == NULL) @@ -251,25 +262,31 @@ static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx, const char *mdname, if (md_size <= 0) { ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, "%s has invalid md size %d", mdname, md_size); - EVP_MD_free(md); - return 0; + goto err; } - sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); - md_nid = ossl_digest_get_approved_nid_with_sha1(ctx->libctx, md, - sha1_allowed); + md_nid = ossl_digest_get_approved_nid(md); if (md_nid < 0) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest=%s", mdname); - EVP_MD_free(md); - return 0; + goto err; + } + +#ifdef FIPS_MODULE + { + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + + if (!ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND_GET(ctx), + OSSL_FIPS_IND_SETTABLE1, ctx->libctx, + md_nid, sha1_allowed, desc)) + goto err; } +#endif if (!ctx->flag_allow_md) { if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest %s != %s", mdname, ctx->mdname); - EVP_MD_free(md); - return 0; + goto err; } EVP_MD_free(md); return 1; @@ -293,19 +310,22 @@ static int ecdsa_setup_md(PROV_ECDSA_CTX *ctx, const char *mdname, OPENSSL_strlcpy(ctx->mdname, mdname, sizeof(ctx->mdname)); return 1; +err: + EVP_MD_free(md); + return 0; } static int ecdsa_digest_signverify_init(void *vctx, const char *mdname, void *ec, const OSSL_PARAM params[], - int operation) + int operation, const char *desc) { PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx; if (!ossl_prov_is_running()) return 0; - if (!ecdsa_signverify_init(vctx, ec, params, operation) - || !ecdsa_setup_md(ctx, mdname, NULL)) + if (!ecdsa_signverify_init(vctx, ec, params, operation, desc) + || !ecdsa_setup_md(ctx, mdname, NULL, desc)) return 0; ctx->flag_allow_md = 0; @@ -329,14 +349,16 @@ static int ecdsa_digest_sign_init(void *vctx, const char *mdname, void *ec, const OSSL_PARAM params[]) { return ecdsa_digest_signverify_init(vctx, mdname, ec, params, - EVP_PKEY_OP_SIGN); + EVP_PKEY_OP_SIGN, + "ECDSA Digest Sign Init"); } static int ecdsa_digest_verify_init(void *vctx, const char *mdname, void *ec, const OSSL_PARAM params[]) { return ecdsa_digest_signverify_init(vctx, mdname, ec, params, - EVP_PKEY_OP_VERIFY); + EVP_PKEY_OP_VERIFY, + "ECDSA Digest Verify Init"); } int ecdsa_digest_signverify_update(void *vctx, const unsigned char *data, @@ -477,7 +499,8 @@ static int ecdsa_get_ctx_params(void *vctx, OSSL_PARAM *params) p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_NONCE_TYPE); if (p != NULL && !OSSL_PARAM_set_uint(p, ctx->nonce_type)) return 0; - + if (!OSSL_FIPS_IND_GET_CTX_PARAM(ctx, params)) + return 0; return 1; } @@ -486,6 +509,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_size_t(OSSL_SIGNATURE_PARAM_DIGEST_SIZE, NULL), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -506,6 +530,13 @@ static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)) + return 0; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(ctx, OSSL_FIPS_IND_SETTABLE1, params, + OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)) + return 0; + #if !defined(OPENSSL_NO_ACVP_TESTS) p = OSSL_PARAM_locate_const(params, OSSL_SIGNATURE_PARAM_KAT); if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->kattest)) @@ -525,7 +556,7 @@ static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (propsp != NULL && !OSSL_PARAM_get_utf8_string(propsp, &pmdprops, sizeof(mdprops))) return 0; - if (!ecdsa_setup_md(ctx, mdname, mdprops)) + if (!ecdsa_setup_md(ctx, mdname, mdprops, "ECDSA Set Ctx")) return 0; } @@ -540,7 +571,6 @@ static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) if (p != NULL && !OSSL_PARAM_get_uint(p, &ctx->nonce_type)) return 0; - return 1; } @@ -550,6 +580,8 @@ static const OSSL_PARAM settable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PROPERTIES, NULL, 0), OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_KAT, NULL), OSSL_PARAM_uint(OSSL_SIGNATURE_PARAM_NONCE_TYPE, NULL), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK) + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; diff --git a/providers/implementations/signature/rsa_sig.c b/providers/implementations/signature/rsa_sig.c index cc7353bbca..569c106869 100644 --- a/providers/implementations/signature/rsa_sig.c +++ b/providers/implementations/signature/rsa_sig.c @@ -31,6 +31,7 @@ #include "prov/provider_ctx.h" #include "prov/der_rsa.h" #include "prov/securitycheck.h" +#include "prov/fipsindicator.h" #define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1 @@ -106,6 +107,7 @@ typedef struct { /* Temp buffer */ unsigned char *tbuf; + OSSL_FIPS_IND_DECLARE } PROV_RSA_CTX; @@ -191,6 +193,7 @@ static void *rsa_newctx(void *provctx, const char *propq) return NULL; } + OSSL_FIPS_IND_INIT(prsactx) prsactx->libctx = PROV_LIBCTX_OF(provctx); prsactx->flag_allow_md = 1; prsactx->propq = propq_copy; @@ -300,41 +303,55 @@ static unsigned char *rsa_generate_signature_aid(PROV_RSA_CTX *ctx, } static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, - const char *mdprops) + const char *mdprops, const char *desc) { + EVP_MD *md = NULL; + if (mdprops == NULL) mdprops = ctx->propq; if (mdname != NULL) { - EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); - int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); - int md_nid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, - sha1_allowed); + int md_nid; size_t mdname_len = strlen(mdname); - if (md == NULL - || md_nid <= 0 - || !rsa_check_padding(ctx, mdname, NULL, md_nid) - || mdname_len >= sizeof(ctx->mdname)) { - if (md == NULL) - ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, - "%s could not be fetched", mdname); - if (md_nid <= 0) - ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, - "digest=%s", mdname); - if (mdname_len >= sizeof(ctx->mdname)) + md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); + + if (md == NULL) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, + "%s could not be fetched", mdname); + goto err; + } + md_nid = ossl_digest_rsa_sign_get_md_nid(md); + if (md_nid <= 0) { + ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, + "digest=%s", mdname); + goto err; + } +#ifdef FIPS_MODULE + { + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + + if (!ossl_fips_ind_digest_sign_check(OSSL_FIPS_IND_GET(ctx), + OSSL_FIPS_IND_SETTABLE1, + ctx->libctx, + md_nid, sha1_allowed, desc)) + goto err; + } +#endif + + if (!rsa_check_padding(ctx, mdname, NULL, md_nid)) + goto err; + if (mdname_len >= sizeof(ctx->mdname)) { ERR_raise_data(ERR_LIB_PROV, PROV_R_INVALID_DIGEST, "%s exceeds name buffer length", mdname); - EVP_MD_free(md); - return 0; + goto err; } if (!ctx->flag_allow_md) { if (ctx->mdname[0] != '\0' && !EVP_MD_is_a(md, ctx->mdname)) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest %s != %s", mdname, ctx->mdname); - EVP_MD_free(md); - return 0; + goto err; } EVP_MD_free(md); return 1; @@ -342,8 +359,7 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, if (!ctx->mgf1_md_set) { if (!EVP_MD_up_ref(md)) { - EVP_MD_free(md); - return 0; + goto err; } EVP_MD_free(ctx->mgf1_md); ctx->mgf1_md = md; @@ -361,6 +377,9 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, } return 1; +err: + EVP_MD_free(md); + return 0; } static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname, @@ -379,7 +398,7 @@ static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname, return 0; } /* The default for mgf1 is SHA1 - so allow SHA1 */ - if ((mdnid = ossl_digest_rsa_sign_get_md_nid(ctx->libctx, md, 1)) <= 0 + if ((mdnid = ossl_digest_rsa_sign_get_md_nid(md)) <= 0 || !rsa_check_padding(ctx, NULL, mdname, mdnid)) { if (mdnid <= 0) ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, @@ -403,9 +422,11 @@ static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname, } static int rsa_signverify_init(void *vprsactx, void *vrsa, - const OSSL_PARAM params[], int operation) + const OSSL_PARAM params[], int operation, + const char *desc) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; + int protect; if (!ossl_prov_is_running() || prsactx == NULL) return 0; @@ -416,14 +437,13 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, } if (vrsa != NULL) { - if (!ossl_rsa_check_key(prsactx->libctx, vrsa, operation)) - return 0; - if (!RSA_up_ref(vrsa)) return 0; RSA_free(prsactx->rsa); prsactx->rsa = vrsa; } + if (!ossl_rsa_key_op_get_protect(prsactx->rsa, operation, &protect)) + return 0; prsactx->operation = operation; @@ -481,7 +501,7 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, /* call rsa_setup_mgf1_md before rsa_setup_md to avoid duplication */ if (!rsa_setup_mgf1_md(prsactx, mgf1mdname, prsactx->propq) - || !rsa_setup_md(prsactx, mdname, prsactx->propq) + || !rsa_setup_md(prsactx, mdname, prsactx->propq, desc) || !rsa_check_parameters(prsactx, min_saltlen)) return 0; } @@ -493,9 +513,15 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, return 0; } + OSSL_FIPS_IND_SET_APPROVED(prsactx) if (!rsa_set_ctx_params(prsactx, params)) return 0; - +#ifdef FIPS_MODULE + if (!ossl_fips_ind_rsa_key_check(OSSL_FIPS_IND_GET(prsactx), + OSSL_FIPS_IND_SETTABLE0, prsactx->libctx, + prsactx->rsa, desc, protect)) + return 0; +#endif return 1; } @@ -525,7 +551,8 @@ static int rsa_sign_init(void *vprsactx, void *vrsa, const OSSL_PARAM params[]) { if (!ossl_prov_is_running()) return 0; - return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN); + return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_SIGN, + "RSA Sign Init"); } static int rsa_sign(void *vprsactx, unsigned char *sig, size_t *siglen, @@ -680,7 +707,7 @@ static int rsa_verify_recover_init(void *vprsactx, void *vrsa, if (!ossl_prov_is_running()) return 0; return rsa_signverify_init(vprsactx, vrsa, params, - EVP_PKEY_OP_VERIFYRECOVER); + EVP_PKEY_OP_VERIFYRECOVER, "RSA VerifyRecover Init"); } static int rsa_verify_recover(void *vprsactx, @@ -772,7 +799,8 @@ static int rsa_verify_init(void *vprsactx, void *vrsa, { if (!ossl_prov_is_running()) return 0; - return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY); + return rsa_signverify_init(vprsactx, vrsa, params, EVP_PKEY_OP_VERIFY, + "RSA Verify Init"); } static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, @@ -861,20 +889,20 @@ static int rsa_verify(void *vprsactx, const unsigned char *sig, size_t siglen, static int rsa_digest_signverify_init(void *vprsactx, const char *mdname, void *vrsa, const OSSL_PARAM params[], - int operation) + int operation, const char *desc) { PROV_RSA_CTX *prsactx = (PROV_RSA_CTX *)vprsactx; if (!ossl_prov_is_running()) return 0; - if (!rsa_signverify_init(vprsactx, vrsa, params, operation)) + if (!rsa_signverify_init(vprsactx, vrsa, params, operation, desc)) return 0; if (mdname != NULL /* was rsa_setup_md already called in rsa_signverify_init()? */ && (mdname[0] == '\0' || OPENSSL_strcasecmp(prsactx->mdname, mdname) != 0) - && !rsa_setup_md(prsactx, mdname, prsactx->propq)) + && !rsa_setup_md(prsactx, mdname, prsactx->propq, desc)) return 0; prsactx->flag_allow_md = 0; @@ -914,7 +942,8 @@ static int rsa_digest_sign_init(void *vprsactx, const char *mdname, if (!ossl_prov_is_running()) return 0; return rsa_digest_signverify_init(vprsactx, mdname, vrsa, - params, EVP_PKEY_OP_SIGN); + params, EVP_PKEY_OP_SIGN, + "RSA Digest Sign Init"); } static int rsa_digest_sign_final(void *vprsactx, unsigned char *sig, @@ -951,7 +980,8 @@ static int rsa_digest_verify_init(void *vprsactx, const char *mdname, if (!ossl_prov_is_running()) return 0; return rsa_digest_signverify_init(vprsactx, mdname, vrsa, - params, EVP_PKEY_OP_VERIFY); + params, EVP_PKEY_OP_VERIFY, + "RSA Digest Verify Init"); } int rsa_digest_verify_final(void *vprsactx, const unsigned char *sig, @@ -1145,7 +1175,8 @@ static int rsa_get_ctx_params(void *vprsactx, OSSL_PARAM *params) return 0; } } - + if (!OSSL_FIPS_IND_GET_CTX_PARAM(prsactx, params)) + return 0; return 1; } @@ -1155,6 +1186,7 @@ static const OSSL_PARAM known_gettable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), + OSSL_FIPS_IND_GETTABLE_CTX_PARAM() OSSL_PARAM_END }; @@ -1180,6 +1212,14 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) if (params == NULL) return 1; + if (!OSSL_FIPS_IND_SET_CTX_PARAM(prsactx, OSSL_FIPS_IND_SETTABLE0, params, + OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK)) + return 0; + + if (!OSSL_FIPS_IND_SET_CTX_PARAM(prsactx, OSSL_FIPS_IND_SETTABLE1, params, + OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK)) + return 0; + pad_mode = prsactx->pad_mode; saltlen = prsactx->saltlen; @@ -1380,7 +1420,7 @@ static int rsa_set_ctx_params(void *vprsactx, const OSSL_PARAM params[]) return 0; if (pmdname != NULL) { - if (!rsa_setup_md(prsactx, pmdname, pmdprops)) + if (!rsa_setup_md(prsactx, pmdname, pmdprops, "RSA Sign Set Ctx")) return 0; } else { if (!rsa_check_padding(prsactx, NULL, NULL, prsactx->mdnid)) @@ -1396,6 +1436,8 @@ static const OSSL_PARAM settable_ctx_params[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK) + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; @@ -1404,6 +1446,8 @@ static const OSSL_PARAM settable_ctx_params_no_digest[] = { OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_DIGEST, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_MGF1_PROPERTIES, NULL, 0), OSSL_PARAM_utf8_string(OSSL_SIGNATURE_PARAM_PSS_SALTLEN, NULL, 0), + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_KEY_CHECK) + OSSL_FIPS_IND_SETTABLE_CTX_PARAM(OSSL_SIGNATURE_PARAM_FIPS_DIGEST_CHECK) OSSL_PARAM_END }; diff --git a/util/perl/OpenSSL/paramnames.pm b/util/perl/OpenSSL/paramnames.pm index 6e5c027a22..43eb63f1fd 100644 --- a/util/perl/OpenSSL/paramnames.pm +++ b/util/perl/OpenSSL/paramnames.pm @@ -67,6 +67,7 @@ my %params = ( 'ALG_PARAM_ENGINE' => "engine", # utf8_string 'ALG_PARAM_MAC' => "mac", # utf8_string 'ALG_PARAM_PROPERTIES' => "properties", # utf8_string + 'ALG_PARAM_FIPS_APPROVED_INDICATOR' => 'fips-indicator', # int, -1, 0 or 1 # cipher parameters 'CIPHER_PARAM_PADDING' => "padding", # uint @@ -191,6 +192,8 @@ my %params = ( 'KDF_PARAM_ARGON2_LANES' => "lanes", # uint32_t 'KDF_PARAM_ARGON2_MEMCOST' => "memcost", # uint32_t 'KDF_PARAM_ARGON2_VERSION' => "version", # uint32_t + 'KDF_PARAM_FIPS_EMS_CHECK' => "ems_check", # int + 'KDF_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # Known RAND names 'RAND_PARAM_STATE' => "state", @@ -216,6 +219,8 @@ my %params = ( 'DRBG_PARAM_CIPHER' => '*ALG_PARAM_CIPHER', 'DRBG_PARAM_MAC' => '*ALG_PARAM_MAC', 'DRBG_PARAM_USE_DF' => "use_derivation_function", + 'DRBG_PARAM_FIPS_DIGEST_CHECK' => '*PKEY_PARAM_FIPS_DIGEST_CHECK', + 'DRBG_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # DRBG call back parameters 'DRBG_PARAM_ENTROPY_REQUIRED' => "entropy_required", @@ -247,6 +252,8 @@ my %params = ( 'PKEY_PARAM_PUB_KEY' => "pub", 'PKEY_PARAM_PRIV_KEY' => "priv", 'PKEY_PARAM_IMPLICIT_REJECTION' => "implicit-rejection", + 'PKEY_PARAM_FIPS_DIGEST_CHECK' => "digest-check", + 'PKEY_PARAM_FIPS_KEY_CHECK' => "key-check", # Diffie-Hellman/DSA Parameters 'PKEY_PARAM_FFC_P' => "p", @@ -374,6 +381,9 @@ my %params = ( 'EXCHANGE_PARAM_KDF_OUTLEN' => "kdf-outlen",# size_t # The following parameter is an octet_string on set and an octet_ptr on get 'EXCHANGE_PARAM_KDF_UKM' => "kdf-ukm", + 'EXCHANGE_PARAM_FIPS_DIGEST_CHECK' => '*PKEY_PARAM_FIPS_DIGEST_CHECK', + 'EXCHANGE_PARAM_FIPS_KEY_CHECK' => '*PKEY_PARAM_FIPS_KEY_CHECK', + 'EXCHANGE_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # Signature parameters 'SIGNATURE_PARAM_ALGORITHM_ID' => "algorithm-id", @@ -387,6 +397,9 @@ my %params = ( 'SIGNATURE_PARAM_NONCE_TYPE' => "nonce-type", 'SIGNATURE_PARAM_INSTANCE' => "instance", 'SIGNATURE_PARAM_CONTEXT_STRING' => "context-string", + 'SIGNATURE_PARAM_FIPS_DIGEST_CHECK' => '*PKEY_PARAM_FIPS_DIGEST_CHECK', + 'SIGNATURE_PARAM_FIPS_KEY_CHECK' => '*PKEY_PARAM_FIPS_KEY_CHECK', + 'SIGNATURE_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # Asym cipher parameters 'ASYM_CIPHER_PARAM_DIGEST' => '*PKEY_PARAM_DIGEST', @@ -402,6 +415,8 @@ my %params = ( 'ASYM_CIPHER_PARAM_TLS_CLIENT_VERSION' => "tls-client-version", 'ASYM_CIPHER_PARAM_TLS_NEGOTIATED_VERSION' => "tls-negotiated-version", 'ASYM_CIPHER_PARAM_IMPLICIT_REJECTION' => "implicit-rejection", + 'ASYM_CIPHER_PARAM_FIPS_KEY_CHECK' => '*PKEY_PARAM_FIPS_KEY_CHECK', + 'ASYM_CIPHER_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # Encoder / decoder parameters @@ -436,6 +451,8 @@ my %params = ( # KEM parameters 'KEM_PARAM_OPERATION' => "operation", 'KEM_PARAM_IKME' => "ikme", + 'KEM_PARAM_FIPS_KEY_CHECK' => '*PKEY_PARAM_FIPS_KEY_CHECK', + 'KEM_PARAM_FIPS_APPROVED_INDICATOR' => '*ALG_PARAM_FIPS_APPROVED_INDICATOR', # Capabilities |