From cac4fb58e02d8cf799d75212179f56c69e652ec7 Mon Sep 17 00:00:00 2001 From: "Dr. Stephen Henson" Date: Sat, 23 Apr 2011 19:55:55 +0000 Subject: Add PRNG security strength checking. --- crypto/dsa/dsa.h | 1 + crypto/dsa/dsa_gen.c | 68 +++++++++++++++++++++++++++++++++++++++++++++------ crypto/dsa/dsa_key.c | 5 +++- crypto/dsa/dsa_ossl.c | 5 +++- 4 files changed, 69 insertions(+), 10 deletions(-) (limited to 'crypto/dsa') diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h index b68fbce169..86766dacb4 100644 --- a/crypto/dsa/dsa.h +++ b/crypto/dsa/dsa.h @@ -113,6 +113,7 @@ */ #define DSA_FLAG_NON_FIPS_ALLOW 0x0400 +#define DSA_FLAG_FIPS_CHECKED 0x0800 #ifdef __cplusplus extern "C" { diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c index 6517b1592d..4d6bbc0d05 100644 --- a/crypto/dsa/dsa_gen.c +++ b/crypto/dsa/dsa_gen.c @@ -83,6 +83,7 @@ #include #ifdef OPENSSL_FIPS #include +#include #endif #include "dsa_locl.h" @@ -140,7 +141,8 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits, goto err; } - if (FIPS_mode() && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) + if (FIPS_mode() && !(ret->flags & DSA_FLAG_NON_FIPS_ALLOW) + && (bits < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) { DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN, DSA_R_KEY_SIZE_TOO_SMALL); goto err; @@ -375,7 +377,24 @@ err: */ -static int dsa2_security_strength(size_t L, size_t N) +static int fips_ffc_strength(size_t L, size_t N) + { + if (L >= 15360 && N >= 512) + return 256; + if (L >= 7680 && N >= 384) + return 192; + if (L >= 3072 && N >= 256) + return 128; + if (L >= 2048 && N >= 224) + return 112; + if (L >= 1024 && N >= 160) + return 80; + return 0; + } + +/* Valid DSA2 parameters from FIPS 186-3 */ + +static int dsa2_valid_parameters(size_t L, size_t N) { if (L == 1024 && N == 160) return 80; @@ -388,6 +407,42 @@ static int dsa2_security_strength(size_t L, size_t N) return 0; } +int fips_check_dsa_prng(DSA *dsa, size_t L, size_t N) + { + int strength; + if (!FIPS_mode()) + return 1; + + if (dsa->flags & (DSA_FLAG_NON_FIPS_ALLOW|DSA_FLAG_FIPS_CHECKED)) + return 1; + + if (!L || !N) + { + L = BN_num_bits(dsa->p); + N = BN_num_bits(dsa->q); + } + if (!dsa2_valid_parameters(L, N)) + { + FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG, FIPS_R_INVALID_PARAMETERS); + return 0; + } + + strength = fips_ffc_strength(L, N); + + if (!strength) + { + FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG,FIPS_R_KEY_TOO_SHORT); + return 0; + } + + if (FIPS_rand_strength() >= strength) + return 1; + + FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG,FIPS_R_PRNG_STRENGTH_TOO_LOW); + return 0; + + } + /* This is a parameter generation algorithm for the DSA2 algorithm as * described in FIPS 186-3. */ @@ -417,13 +472,10 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N, FIPS_R_FIPS_SELFTEST_FAILED); goto err; } -#endif - if (!dsa2_security_strength(L, N)) - { - DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS); - ok = 0; + + if (!fips_check_dsa_prng(ret, L, N)) goto err; - } +#endif if (evpmd == NULL) { diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c index 942000e3a5..3df9a6c6a9 100644 --- a/crypto/dsa/dsa_key.c +++ b/crypto/dsa/dsa_key.c @@ -106,11 +106,14 @@ static int dsa_builtin_keygen(DSA *dsa) BIGNUM *pub_key=NULL,*priv_key=NULL; #ifdef OPENSSL_FIPS - if (FIPS_mode() && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) + if (FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW) + && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) { DSAerr(DSA_F_DSA_BUILTIN_KEYGEN, DSA_R_KEY_SIZE_TOO_SMALL); goto err; } + if (!fips_check_dsa_prng(dsa, 0, 0)) + goto err; #endif if ((ctx=BN_CTX_new()) == NULL) goto err; diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index f1512a40dd..acf7af95c4 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -150,11 +150,14 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) return NULL; } - if (FIPS_mode() && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) + if (FIPS_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW) + && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) { DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_KEY_SIZE_TOO_SMALL); return NULL; } + if (!fips_check_dsa_prng(dsa, 0, 0)) + goto err; #endif BN_init(&m); -- cgit v1.2.3