From 49ed5ba8f62875074f04417189147fd3dda072ab Mon Sep 17 00:00:00 2001 From: Shane Lontis Date: Sat, 29 Aug 2020 18:03:17 +1000 Subject: [PATCH] fix provider signatures Reviewed-by: Tomas Mraz (Merged from https://github.com/openssl/openssl/pull/12745) --- crypto/ffc/ffc_params_generate.c | 49 ++++++++++----- providers/common/check_fips.c | 3 +- providers/common/digest_to_nid.c | 15 ++--- .../implementations/signature/build.info | 7 +-- providers/implementations/signature/dsa.c | 54 ++-------------- providers/implementations/signature/ecdsa.c | 20 +++--- providers/implementations/signature/rsa.c | 62 ++----------------- 7 files changed, 61 insertions(+), 149 deletions(-) diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c index 03b209ebad..1fe8e4a6a5 100644 --- a/crypto/ffc/ffc_params_generate.c +++ b/crypto/ffc/ffc_params_generate.c @@ -37,38 +37,59 @@ * Verify that the passed in L, N pair for DH or DSA is valid. * Returns 0 if invalid, otherwise it returns the security strength. */ + +#ifdef FIPS_MODULE static int ffc_validate_LN(size_t L, size_t N, int type, int verify) { if (type == FFC_PARAM_TYPE_DH) { -#ifndef FIPS_MODULE - /* Allow legacy 1024/160 in non fips mode */ - if (L == 1024 && N == 160) - return 80; -#endif /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */ if (L == 2048 && (N == 224 || N == 256)) return 112; -#ifndef OPENSSL_NO_DH +# ifndef OPENSSL_NO_DH DHerr(0, DH_R_BAD_FFC_PARAMETERS); -#endif +# endif } else if (type == FFC_PARAM_TYPE_DSA) { /* Valid DSA L,N parameters from FIPS 186-4 Section 4.2 */ -#ifdef FIPS_MODULE /* In fips mode 1024/160 can only be used for verification */ - if (verify) -#endif - if (L == 1024 && N == 160) - return 80; + if (verify && L == 1024 && N == 160) + return 80; if (L == 2048 && (N == 224 || N == 256)) return 112; if (L == 3072 && N == 256) return 128; -#ifndef OPENSSL_NO_DSA +# ifndef OPENSSL_NO_DSA DSAerr(0, DSA_R_BAD_FFC_PARAMETERS); -#endif +# endif } return 0; } +#else +static int ffc_validate_LN(size_t L, size_t N, int type, int verify) +{ + if (type == FFC_PARAM_TYPE_DH) { + /* Allow legacy 1024/160 in non fips mode */ + if (L == 1024 && N == 160) + return 80; + /* Valid DH L,N parameters from SP800-56Ar3 5.5.1 Table 1 */ + if (L == 2048 && (N == 224 || N == 256)) + return 112; +# ifndef OPENSSL_NO_DH + DHerr(0, DH_R_BAD_FFC_PARAMETERS); +# endif + } else if (type == FFC_PARAM_TYPE_DSA) { + if (L == 1024 && N == 160) + return 80; + if (L == 2048 && (N == 224 || N == 256)) + return 112; + if (L == 3072 && N == 256) + return 128; +# ifndef OPENSSL_NO_DSA + DSAerr(0, DSA_R_BAD_FFC_PARAMETERS); +# endif + } + return 0; +} +#endif /* FIPS_MODULE */ /* FIPS186-4 A.2.1 Unverifiable Generation of Generator g */ static int generate_unverifiable_g(BN_CTX *ctx, BN_MONT_CTX *mont, BIGNUM *g, diff --git a/providers/common/check_fips.c b/providers/common/check_fips.c index 1ce0718e1d..891df497c3 100644 --- a/providers/common/check_fips.c +++ b/providers/common/check_fips.c @@ -22,7 +22,8 @@ /* * 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. + * 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) { diff --git a/providers/common/digest_to_nid.c b/providers/common/digest_to_nid.c index 4f59709f5d..e233ce4251 100644 --- a/providers/common/digest_to_nid.c +++ b/providers/common/digest_to_nid.c @@ -21,19 +21,14 @@ int digest_md_to_nid(const EVP_MD *md, const OSSL_ITEM *it, size_t it_len) { size_t i; - int mdnid = NID_undef; if (md == NULL) - goto end; + return NID_undef; - for (i = 0; i < it_len; i++) { - if (EVP_MD_is_a(md, it[i].ptr)) { - mdnid = (int)it[i].id; - break; - } - } - end: - return mdnid; + for (i = 0; i < it_len; i++) + if (EVP_MD_is_a(md, it[i].ptr)) + return (int)it[i].id; + return NID_undef; } /* diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info index 9d682b81da..24c5180662 100644 --- a/providers/implementations/signature/build.info +++ b/providers/implementations/signature/build.info @@ -5,14 +5,11 @@ $DSA_GOAL=../../libimplementations.a $EC_GOAL=../../libimplementations.a IF[{- !$disabled{dsa} -}] - SOURCE[../../libfips.a]=dsa.c - SOURCE[../../libnonfips.a]=dsa.c + SOURCE[$DSA_GOAL]=dsa.c ENDIF IF[{- !$disabled{ec} -}] - SOURCE[$EC_GOAL]=eddsa.c - SOURCE[../../libfips.a]=ecdsa.c - SOURCE[../../libnonfips.a]=ecdsa.c + SOURCE[$EC_GOAL]=eddsa.c ecdsa.c ENDIF SOURCE[../../libfips.a]=rsa.c diff --git a/providers/implementations/signature/dsa.c b/providers/implementations/signature/dsa.c index 7d2496aae8..9f44607538 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/provider_util.h" +#include "prov/check.h" #include "crypto/dsa.h" #include "prov/der_dsa.h" @@ -87,48 +87,8 @@ typedef struct { EVP_MD_CTX *mdctx; size_t mdsize; int operation; - } PROV_DSA_CTX; -/* - * Check for valid key sizes if fips mode. Refer to - * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf - * "Table 2" - */ -static int dsa_check_key_size(const PROV_DSA_CTX *ctx) -{ -#ifdef FIPS_MODULE - size_t L, N; - const BIGNUM *p, *q; - DSA *dsa = ctx->dsa; - - 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 (ctx->operation != EVP_PKEY_OP_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); -#else - return 1; -#endif -} static size_t dsa_get_md_size(const PROV_DSA_CTX *pdsactx) { @@ -137,13 +97,6 @@ static size_t dsa_get_md_size(const PROV_DSA_CTX *pdsactx) return 0; } -static int dsa_get_md_nid(const PROV_DSA_CTX *ctx, const EVP_MD *md) -{ - int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); - - return ossl_prov_digest_get_approved_nid(md, sha1_allowed); -} - static void *dsa_newctx(void *provctx, const char *propq) { PROV_DSA_CTX *pdsactx; @@ -172,9 +125,10 @@ static int dsa_setup_md(PROV_DSA_CTX *ctx, 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 = dsa_get_md_nid(ctx, md); + int md_nid = digest_get_approved_nid_with_sha1(md, sha1_allowed); size_t mdname_len = strlen(mdname); if (md == NULL || md_nid == NID_undef) { @@ -230,7 +184,7 @@ static int dsa_signverify_init(void *vpdsactx, void *vdsa, int operation) DSA_free(pdsactx->dsa); pdsactx->dsa = vdsa; pdsactx->operation = operation; - if (!dsa_check_key_size(pdsactx)) { + if (!dsa_check_key(vdsa, operation == EVP_PKEY_OP_SIGN)) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); return 0; } diff --git a/providers/implementations/signature/ecdsa.c b/providers/implementations/signature/ecdsa.c index 8ca235c0b4..75ee839e08 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/provider_util.h" +#include "prov/check.h" #include "crypto/ec.h" #include "prov/der_ec.h" @@ -84,7 +84,7 @@ typedef struct { */ BIGNUM *kinv; BIGNUM *r; -#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) +#if !defined(OPENSSL_NO_ACVP_TESTS) /* * This indicates that KAT (CAVS) test is running. Externally an app will * override the random callback such that the generated private key and k @@ -128,7 +128,7 @@ static int ecdsa_signverify_init(void *vctx, void *ec, int operation) EC_KEY_free(ctx->ec); ctx->ec = ec; ctx->operation = operation; - return ossl_prov_ec_check(ec, operation == EVP_PKEY_OP_SIGN); + return ec_check_key(ec, operation == EVP_PKEY_OP_SIGN); } static int ecdsa_sign_init(void *vctx, void *ec) @@ -157,7 +157,7 @@ static int ecdsa_sign(void *vctx, unsigned char *sig, size_t *siglen, return 1; } -#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) +#if !defined(OPENSSL_NO_ACVP_TESTS) if (ctx->kattest && !ECDSA_sign_setup(ctx->ec, NULL, &ctx->kinv, &ctx->r)) return 0; #endif @@ -187,13 +187,6 @@ static int ecdsa_verify(void *vctx, const unsigned char *sig, size_t siglen, return ECDSA_verify(0, tbs, tbslen, sig, siglen, ctx->ec); } -static int get_md_nid(const PROV_ECDSA_CTX *ctx, const EVP_MD *md) -{ - int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); - - return ossl_prov_digest_get_approved_nid(md, sha1_allowed); -} - static void free_md(PROV_ECDSA_CTX *ctx) { OPENSSL_free(ctx->propq); @@ -211,6 +204,7 @@ static int ecdsa_digest_signverify_init(void *vctx, const char *mdname, PROV_ECDSA_CTX *ctx = (PROV_ECDSA_CTX *)vctx; int md_nid = NID_undef; WPACKET pkt; + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); if (!ossl_prov_is_running()) return 0; @@ -221,7 +215,7 @@ static int ecdsa_digest_signverify_init(void *vctx, const char *mdname, return 0; ctx->md = EVP_MD_fetch(ctx->libctx, mdname, ctx->propq); - md_nid = get_md_nid(ctx, ctx->md); + md_nid = digest_get_approved_nid_with_sha1(ctx->md, sha1_allowed); if (md_nid == NID_undef) goto error; @@ -428,7 +422,7 @@ static int ecdsa_set_ctx_params(void *vctx, const OSSL_PARAM params[]) */ return 1; } -#if defined(FIPS_MODULE) && !defined(OPENSSL_NO_ACVP_TESTS) +#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)) return 0; diff --git a/providers/implementations/signature/rsa.c b/providers/implementations/signature/rsa.c index c7f3f6f6cd..20011b52a1 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/provider_util.h" +#include "prov/check.h" #define RSA_DEFAULT_DIGEST_NAME OSSL_DIGEST_NAME_SHA1 @@ -120,58 +120,6 @@ static size_t rsa_get_md_size(const PROV_RSA_CTX *prsactx) return 0; } -static int rsa_get_md_nid_check(const PROV_RSA_CTX *ctx, const EVP_MD *md, - int sha1_allowed) -{ - int mdnid = NID_undef; - - #ifndef FIPS_MODULE - static const OSSL_ITEM name_to_nid[] = { - { NID_md5, OSSL_DIGEST_NAME_MD5 }, - { NID_md5_sha1, OSSL_DIGEST_NAME_MD5_SHA1 }, - { NID_md2, OSSL_DIGEST_NAME_MD2 }, - { NID_md4, OSSL_DIGEST_NAME_MD4 }, - { NID_mdc2, OSSL_DIGEST_NAME_MDC2 }, - { NID_ripemd160, OSSL_DIGEST_NAME_RIPEMD160 }, - }; - #endif - - if (md == NULL) - goto end; - - mdnid = ossl_prov_digest_get_approved_nid(md, sha1_allowed); - - #ifndef FIPS_MODULE - if (mdnid == NID_undef) - mdnid = ossl_prov_digest_md_to_nid(md, name_to_nid, - OSSL_NELEM(name_to_nid)); - #endif - end: - return mdnid; -} - -static int rsa_get_md_nid(const PROV_RSA_CTX *ctx, const EVP_MD *md) -{ - return rsa_get_md_nid_check(ctx, md, ctx->operation != EVP_PKEY_OP_SIGN); -} - -static int rsa_get_md_mgf1_nid(const PROV_RSA_CTX *ctx, const EVP_MD *md) -{ - /* The default for mgf1 is SHA1 - so allow this */ - return rsa_get_md_nid_check(ctx, md, 1); -} - -static int rsa_check_key_size(const PROV_RSA_CTX *prsactx) -{ -#ifdef FIPS_MODULE - int sz = RSA_bits(prsactx->rsa); - - return (prsactx->operation == EVP_PKEY_OP_SIGN) ? (sz >= 2048) : (sz >= 1024); -#else - return 1; -#endif -} - static int rsa_check_padding(int mdnid, int padding) { if (padding == RSA_NO_PADDING) { @@ -240,7 +188,8 @@ static int rsa_setup_md(PROV_RSA_CTX *ctx, const char *mdname, if (mdname != NULL) { WPACKET pkt; EVP_MD *md = EVP_MD_fetch(ctx->libctx, mdname, mdprops); - int md_nid = rsa_get_md_nid(ctx, md); + int sha1_allowed = (ctx->operation != EVP_PKEY_OP_SIGN); + int md_nid = digest_rsa_sign_get_md_nid(md, sha1_allowed); size_t mdname_len = strlen(mdname); if (md == NULL @@ -306,7 +255,8 @@ static int rsa_setup_mgf1_md(PROV_RSA_CTX *ctx, const char *mdname, "%s could not be fetched", mdname); return 0; } - if (rsa_get_md_mgf1_nid(ctx, md) == NID_undef) { + /* The default for mgf1 is SHA1 - so allow SHA1 */ + if (digest_rsa_sign_get_md_nid(md, 1) == NID_undef) { ERR_raise_data(ERR_LIB_PROV, PROV_R_DIGEST_NOT_ALLOWED, "digest=%s", mdname); EVP_MD_free(md); @@ -337,7 +287,7 @@ static int rsa_signverify_init(void *vprsactx, void *vrsa, int operation) prsactx->rsa = vrsa; prsactx->operation = operation; - if (!rsa_check_key_size(prsactx)) { + if (!rsa_check_key(vrsa, operation == EVP_PKEY_OP_SIGN)) { ERR_raise(ERR_LIB_PROV, PROV_R_INVALID_KEY_LENGTH); return 0; }