diff options
author | Shane Lontis <shane.lontis@oracle.com> | 2020-09-04 17:55:28 +1000 |
---|---|---|
committer | Matt Caswell <matt@openssl.org> | 2020-09-18 14:20:39 +0100 |
commit | 7a810fac866c6c1d93015999633ee2a29f17b3d2 (patch) | |
tree | 5d66eb98a8120b53d5f916735864096d003fb180 /providers | |
parent | 850a485f252e6a6b04734308451e2c64f39b0457 (diff) |
Add 'fips-securitychecks' option and plumb this into the actual fips checks
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/12745)
Diffstat (limited to 'providers')
-rw-r--r-- | providers/common/build.info | 7 | ||||
-rw-r--r-- | providers/common/check_fips.c | 188 | ||||
-rw-r--r-- | providers/common/digest_to_nid.c | 2 | ||||
-rw-r--r-- | providers/common/include/prov/securitycheck.h (renamed from providers/common/include/prov/check.h) | 7 | ||||
-rw-r--r-- | providers/common/securitycheck.c | 209 | ||||
-rw-r--r-- | providers/common/securitycheck_default.c (renamed from providers/common/check_default.c) | 41 | ||||
-rw-r--r-- | providers/common/securitycheck_fips.c | 39 | ||||
-rw-r--r-- | providers/implementations/asymciphers/rsa_enc.c | 2 | ||||
-rw-r--r-- | providers/implementations/exchange/dh_exch.c | 2 | ||||
-rw-r--r-- | providers/implementations/exchange/ecdh_exch.c | 2 | ||||
-rw-r--r-- | providers/implementations/signature/dsa.c | 2 | ||||
-rw-r--r-- | providers/implementations/signature/ecdsa.c | 2 | ||||
-rw-r--r-- | providers/implementations/signature/rsa.c | 2 |
13 files changed, 268 insertions, 237 deletions
diff --git a/providers/common/build.info b/providers/common/build.info index 1e0ea4e5dd..2179b2a0f8 100644 --- a/providers/common/build.info +++ b/providers/common/build.info @@ -1,6 +1,7 @@ SUBDIRS=der SOURCE[../libcommon.a]=provider_err.c provider_ctx.c -$FIPSCOMMON=provider_util.c capabilities.c bio_prov.c digest_to_nid.c -SOURCE[../libnonfips.a]=$FIPSCOMMON nid_to_name.c check_default.c -SOURCE[../libfips.a]=$FIPSCOMMON check_fips.c +$FIPSCOMMON=provider_util.c capabilities.c bio_prov.c digest_to_nid.c\ + securitycheck.c +SOURCE[../libnonfips.a]=$FIPSCOMMON nid_to_name.c securitycheck_default.c +SOURCE[../libfips.a]=$FIPSCOMMON securitycheck_fips.c diff --git a/providers/common/check_fips.c b/providers/common/check_fips.c deleted file mode 100644 index 891df497c3..0000000000 --- a/providers/common/check_fips.c +++ /dev/null @@ -1,188 +0,0 @@ -/* - * Copyright 2020 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 - * in the file LICENSE in the source distribution or at - * https://www.openssl.org/source/license.html - */ - -#include "internal/deprecated.h" - -#include <openssl/rsa.h> -#include <openssl/dsa.h> -#include <openssl/dh.h> -#include <openssl/ec.h> -#include <openssl/err.h> -#include <openssl/core_names.h> -#include <openssl/obj_mac.h> -#include "prov/check.h" -#include "prov/providercommonerr.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 rsa_check_key(const RSA *rsa, int protect) -{ - int sz = RSA_bits(rsa); - - return protect ? (sz >= 2048) : (sz >= 1024); -} - -#ifndef OPENSSL_NO_EC -/* - * In FIPS mode: - * protect should be 1 for any operations that need 112 bits of security - * strength (such as signing, and key exchange), or 0 for operations that allow - * a lower security strength (such as verify). - * - * For ECDH key agreement refer to SP800-56A - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf - * "Appendix D" - * - * For ECDSA signatures refer to - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf - * "Table 2" - */ -int ec_check_key(const EC_KEY *ec, int protect) -{ - 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; - } - return 1; -} -#endif /* OPENSSL_NO_EC */ - -#ifndef OPENSSL_NO_DSA -/* - * Check for valid key sizes if fips mode. Refer to - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf - * "Table 2" - */ -int dsa_check_key(const DSA *dsa, int sign) -{ - 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); - - /* - * Valid sizes or verification - Note this could be a fips186-2 type - * key - so we allow 512 also. When this is no longer suppported the - * lower bound should be increased to 1024. - */ - if (!sign) - return (L >= 512 && N >= 160); - - /* Valid sizes for both sign and verify */ - if (L == 2048 && (N == 224 || N == 256)) - return 1; - return (L == 3072 && N == 256); -} -#endif /* OPENSSL_NO_DSA */ - -#ifndef OPENSSL_NO_DH -/* - * For DH key agreement refer to SP800-56A - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf - * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and - * "Appendix D" FFC Safe-prime Groups - */ -int dh_check_key(const DH *dh) -{ - size_t L, N; - const BIGNUM *p, *q; - - if (dh == 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; - - /* 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); - - return (L == 2048 && (N == 224 || N == 256)); -} -#endif /* OPENSSL_NO_DH */ - -int digest_get_approved_nid_with_sha1(const EVP_MD *md, int sha1_allowed) -{ - int mdnid = digest_get_approved_nid(md); - - if (mdnid == NID_sha1 && !sha1_allowed) - mdnid = NID_undef; - - return mdnid; -} - -int digest_is_allowed(const EVP_MD *md) -{ - return (digest_get_approved_nid(md) != NID_undef); -} - -int digest_rsa_sign_get_md_nid(const EVP_MD *md, int sha1_allowed) -{ - return digest_get_approved_nid_with_sha1(md, sha1_allowed); -} diff --git a/providers/common/digest_to_nid.c b/providers/common/digest_to_nid.c index e233ce4251..99633c150c 100644 --- a/providers/common/digest_to_nid.c +++ b/providers/common/digest_to_nid.c @@ -11,7 +11,7 @@ #include <openssl/core_names.h> #include <openssl/evp.h> #include <openssl/core.h> -#include "prov/check.h" +#include "prov/securitycheck.h" #include "internal/nelem.h" /* diff --git a/providers/common/include/prov/check.h b/providers/common/include/prov/securitycheck.h index 30425840b5..0d3b9e8bac 100644 --- a/providers/common/include/prov/check.h +++ b/providers/common/include/prov/securitycheck.h @@ -7,7 +7,7 @@ * https://www.openssl.org/source/license.html */ -/* Functions that have different implementations for the FIPS_MODULE */ +/* Functions that are common */ int rsa_check_key(const RSA *rsa, int protect); int ec_check_key(const EC_KEY *ec, int protect); int dsa_check_key(const DSA *dsa, int sign); @@ -15,8 +15,11 @@ int dh_check_key(const DH *dh); int digest_is_allowed(const EVP_MD *md); int digest_get_approved_nid_with_sha1(const EVP_MD *md, int sha1_allowed); -int digest_rsa_sign_get_md_nid(const EVP_MD *md, ossl_unused int sha1_allowed); /* Functions that are common */ int digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len); int digest_get_approved_nid(const EVP_MD *md); + +/* Functions that have different implementations for the FIPS_MODULE */ +int digest_rsa_sign_get_md_nid(const EVP_MD *md, int sha1_allowed); +int securitycheck_enabled(void); diff --git a/providers/common/securitycheck.c b/providers/common/securitycheck.c new file mode 100644 index 0000000000..624843e3ab --- /dev/null +++ b/providers/common/securitycheck.c @@ -0,0 +1,209 @@ +/* + * Copyright 2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/deprecated.h" + +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/dh.h> +#include <openssl/ec.h> +#include <openssl/err.h> +#include <openssl/core_names.h> +#include <openssl/obj_mac.h> +#include "prov/securitycheck.h" +#include "prov/providercommonerr.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 rsa_check_key(const RSA *rsa, int protect) +{ +#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) { + int sz = RSA_bits(rsa); + + return protect ? (sz >= 2048) : (sz >= 1024); + } +#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + return 1; +} + +#ifndef OPENSSL_NO_EC +/* + * In FIPS mode: + * protect should be 1 for any operations that need 112 bits of security + * strength (such as signing, and key exchange), or 0 for operations that allow + * a lower security strength (such as verify). + * + * For ECDH key agreement refer to SP800-56A + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf + * "Appendix D" + * + * For ECDSA signatures refer to + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf + * "Table 2" + */ +int ec_check_key(const EC_KEY *ec, int protect) +{ +# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) { + 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 */ + return 1; +} +#endif /* OPENSSL_NO_EC */ + +#ifndef OPENSSL_NO_DSA +/* + * Check for valid key sizes if fips mode. Refer to + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf + * "Table 2" + */ +int dsa_check_key(const DSA *dsa, int sign) +{ +# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) { + 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); + + /* + * Valid sizes or verification - Note this could be a fips186-2 type + * key - so we allow 512 also. When this is no longer suppported the + * lower bound should be increased to 1024. + */ + if (!sign) + return (L >= 512 && N >= 160); + + /* Valid sizes for both sign and verify */ + if (L == 2048 && (N == 224 || N == 256)) + return 1; + return (L == 3072 && N == 256); + } +# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + return 1; +} +#endif /* OPENSSL_NO_DSA */ + +#ifndef OPENSSL_NO_DH +/* + * For DH key agreement refer to SP800-56A + * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Ar3.pdf + * "Section 5.5.1.1FFC Domain Parameter Selection/Generation" and + * "Appendix D" FFC Safe-prime Groups + */ +int dh_check_key(const DH *dh) +{ +# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) { + size_t L, N; + const BIGNUM *p, *q; + + if (dh == 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; + + /* 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); + + return (L == 2048 && (N == 224 || N == 256)); + } +# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + return 1; +} +#endif /* OPENSSL_NO_DH */ + +int digest_get_approved_nid_with_sha1(const EVP_MD *md, int sha1_allowed) +{ + int mdnid = digest_get_approved_nid(md); + +# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) { + if (mdnid == NID_sha1 && !sha1_allowed) + mdnid = NID_undef; + } +# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + return mdnid; +} + +int digest_is_allowed(const EVP_MD *md) +{ +# if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) + return (digest_get_approved_nid(md) != NID_undef); +# endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + return 1; +} diff --git a/providers/common/check_default.c b/providers/common/securitycheck_default.c index 2bfa690573..e88b642ae2 100644 --- a/providers/common/check_default.c +++ b/providers/common/securitycheck_default.c @@ -13,44 +13,13 @@ #include <openssl/core.h> #include <openssl/core_names.h> #include <openssl/obj_mac.h> -#include "prov/check.h" +#include "prov/securitycheck.h" #include "internal/nelem.h" -int rsa_check_key(ossl_unused const RSA *rsa, ossl_unused int protect) +/* Disable the security checks in the default provider */ +int securitycheck_enabled(void) { - return 1; -} - -#ifndef OPENSSL_NO_EC -int ec_check_key(ossl_unused const EC_KEY *ec, ossl_unused int protect) -{ - return 1; -} -#endif - -#ifndef OPENSSL_NO_DSA -int dsa_check_key(ossl_unused const DSA *dsa, ossl_unused int sign) -{ - return 1; -} -#endif - -#ifndef OPENSSL_NO_DH -int dh_check_key(const DH *dh) -{ - return 1; -} -#endif - -int digest_is_allowed(ossl_unused const EVP_MD *md) -{ - return 1; -} - -int digest_get_approved_nid_with_sha1(const EVP_MD *md, - ossl_unused int sha1_allowed) -{ - return digest_get_approved_nid(md); + return 0; } int digest_rsa_sign_get_md_nid(const EVP_MD *md, ossl_unused int sha1_allowed) @@ -65,8 +34,6 @@ int digest_rsa_sign_get_md_nid(const EVP_MD *md, ossl_unused int sha1_allowed) { NID_mdc2, OSSL_DIGEST_NAME_MDC2 }, { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 }, }; - if (md == NULL) - return NID_undef; mdnid = digest_get_approved_nid_with_sha1(md, 1); if (mdnid == NID_undef) diff --git a/providers/common/securitycheck_fips.c b/providers/common/securitycheck_fips.c new file mode 100644 index 0000000000..f73eae9569 --- /dev/null +++ b/providers/common/securitycheck_fips.c @@ -0,0 +1,39 @@ +/* + * Copyright 2020 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 + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include "internal/deprecated.h" + +#include <openssl/rsa.h> +#include <openssl/dsa.h> +#include <openssl/dh.h> +#include <openssl/ec.h> +#include <openssl/err.h> +#include <openssl/core_names.h> +#include <openssl/obj_mac.h> +#include "prov/securitycheck.h" +#include "prov/providercommonerr.h" + +int securitycheck_enabled(void) +{ +#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + /* TODO(3.0): make this configurable */ + return 1; +#else + return 0; +#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ +} + +int digest_rsa_sign_get_md_nid(const EVP_MD *md, int sha1_allowed) +{ +#if !defined(OPENSSL_NO_FIPS_SECURITYCHECKS) + if (securitycheck_enabled()) + return digest_get_approved_nid_with_sha1(md, sha1_allowed); +#endif /* OPENSSL_NO_FIPS_SECURITYCHECKS */ + return digest_get_approved_nid(md); +} diff --git a/providers/implementations/asymciphers/rsa_enc.c b/providers/implementations/asymciphers/rsa_enc.c index 437d7c5de9..199edbbaed 100644 --- a/providers/implementations/asymciphers/rsa_enc.c +++ b/providers/implementations/asymciphers/rsa_enc.c @@ -29,7 +29,7 @@ #include "prov/provider_ctx.h" #include "prov/implementations.h" #include "prov/providercommon.h" -#include "prov/check.h" +#include "prov/securitycheck.h" #include <stdlib.h> diff --git a/providers/implementations/exchange/dh_exch.c b/providers/implementations/exchange/dh_exch.c index 3ca3da40fc..9e0860870f 100644 --- a/providers/implementations/exchange/dh_exch.c +++ b/providers/implementations/exchange/dh_exch.c @@ -23,7 +23,7 @@ #include "prov/providercommon.h" #include "prov/implementations.h" #include "prov/provider_ctx.h" -#include "prov/check.h" +#include "prov/securitycheck.h" #include "crypto/dh.h" static OSSL_FUNC_keyexch_newctx_fn dh_newctx; diff --git a/providers/implementations/exchange/ecdh_exch.c b/providers/implementations/exchange/ecdh_exch.c index 9933383be7..e668161dd4 100644 --- a/providers/implementations/exchange/ecdh_exch.c +++ b/providers/implementations/exchange/ecdh_exch.c @@ -24,7 +24,7 @@ #include "prov/provider_ctx.h" #include "prov/providercommon.h" #include "prov/implementations.h" -#include "prov/check.h" +#include "prov/securitycheck.h" #include "crypto/ec.h" /* ecdh_KDF_X9_63() */ static OSSL_FUNC_keyexch_newctx_fn ecdh_newctx; diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c index 9f44607538..31f6abf5fc 100644 --- a/providers/implementations/signature/dsa.c +++ b/providers/implementations/signature/dsa.c @@ -30,7 +30,7 @@ #include "prov/implementations.h" #include "prov/providercommonerr.h" #include "prov/provider_ctx.h" -#include "prov/check.h" +#include "prov/securitycheck.h" #include "crypto/dsa.h" #include "prov/der_dsa.h" diff --git a/providers/implementations/signature/ecdsa.c b/providers/implementations/signature/ecdsa.c index 75ee839e08..5fd4d48fc1 100644 --- a/providers/implementations/signature/ecdsa.c +++ b/providers/implementations/signature/ecdsa.c @@ -28,7 +28,7 @@ #include "prov/providercommonerr.h" #include "prov/implementations.h" #include "prov/provider_ctx.h" -#include "prov/check.h" +#include "prov/securitycheck.h" #include "crypto/ec.h" #include "prov/der_ec.h" diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c index 20011b52a1..5209ac992b 100644 --- a/providers/implementations/signature/rsa.c +++ b/providers/implementations/signature/rsa.c @@ -30,7 +30,7 @@ #include "prov/implementations.h" #include "prov/provider_ctx.h" #include "prov/der_rsa.h" -#include "prov/check.h" +#include "prov/securitycheck.h" #define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1 |