提交 cac4fb58 编写于 作者: D Dr. Stephen Henson

Add PRNG security strength checking.

上级 9e5fe439
......@@ -4,6 +4,10 @@
Changes between 1.0.1 and 1.1.0 [xx XXX xxxx]
*) Add PRNG security strength checks to RSA, DSA and ECDSA using
information in FIPS186-3, SP800-57 and SP800-131A.
[Steve Henson]
*) CCM support via EVP. Interface is very similar to GCM case except we
must supply all data in one chunk (i.e. no update, final) and the
message length must be supplied if AAD is used. Add algorithm test
......
......@@ -113,6 +113,7 @@
*/
#define DSA_FLAG_NON_FIPS_ALLOW 0x0400
#define DSA_FLAG_FIPS_CHECKED 0x0800
#ifdef __cplusplus
extern "C" {
......
......@@ -83,6 +83,7 @@
#include <openssl/sha.h>
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
#include <openssl/fips_rand.h>
#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)
{
......
......@@ -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;
......
......@@ -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);
......
......@@ -703,11 +703,21 @@ typedef struct ec_key_st EC_KEY;
#define EC_PKEY_NO_PARAMETERS 0x001
#define EC_PKEY_NO_PUBKEY 0x002
/* some values for the flags field */
#define EC_FLAG_NON_FIPS_ALLOW 0x1
#define EC_FLAG_FIPS_CHECKED 0x2
/** Creates a new EC_KEY object.
* \return EC_KEY object or NULL if an error occurred.
*/
EC_KEY *EC_KEY_new(void);
int EC_KEY_get_flags(const EC_KEY *key);
void EC_KEY_set_flags(EC_KEY *key, int flags);
void EC_KEY_clear_flags(EC_KEY *key, int flags);
/** Creates a new EC_KEY object using a named curve as underlying
* EC_GROUP object.
* \param nid NID of the named curve.
......
......@@ -80,6 +80,7 @@ EC_KEY *EC_KEY_new(void)
}
ret->version = 1;
ret->flags = 0;
ret->group = NULL;
ret->pub_key = NULL;
ret->priv_key= NULL;
......@@ -199,6 +200,7 @@ EC_KEY *EC_KEY_copy(EC_KEY *dest, const EC_KEY *src)
dest->enc_flag = src->enc_flag;
dest->conv_form = src->conv_form;
dest->version = src->version;
dest->flags = src->flags;
return dest;
}
......@@ -235,6 +237,8 @@ int EC_KEY_up_ref(EC_KEY *r)
#ifdef OPENSSL_FIPS
#include <openssl/evp.h>
#include <openssl/fips.h>
#include <openssl/fips_rand.h>
static int fips_check_ec(EC_KEY *key)
{
......@@ -253,6 +257,46 @@ static int fips_check_ec(EC_KEY *key)
return 1;
}
int fips_check_ec_prng(EC_KEY *ec)
{
int bits, strength;
if (!FIPS_mode())
return 1;
if (ec->flags & (EC_FLAG_NON_FIPS_ALLOW|EC_FLAG_FIPS_CHECKED))
return 1;
if (!ec->group)
return 1;
bits = BN_num_bits(&ec->group->order);
if (bits < 160)
{
FIPSerr(FIPS_F_FIPS_CHECK_DSA_PRNG,FIPS_R_KEY_TOO_SHORT);
return 0;
}
/* Comparable algorithm strengths: from SP800-57 table 2 */
if (bits >= 512)
strength = 256;
else if (bits >= 384)
strength = 192;
else if (bits >= 256)
strength = 128;
else if (bits >= 224)
strength = 112;
else
strength = 80;
if (FIPS_rand_strength() >= strength)
return 1;
FIPSerr(FIPS_F_FIPS_CHECK_EC_PRNG,FIPS_R_PRNG_STRENGTH_TOO_LOW);
return 0;
}
#endif
int EC_KEY_generate_key(EC_KEY *eckey)
......@@ -283,6 +327,11 @@ int EC_KEY_generate_key(EC_KEY *eckey)
if (!EC_GROUP_get_order(eckey->group, order, ctx))
goto err;
#ifdef OPENSSL_FIPS
if (!fips_check_ec_prng(eckey))
goto err;
#endif
do
if (!BN_rand_range(priv_key, order))
goto err;
......@@ -571,3 +620,18 @@ int EC_KEY_precompute_mult(EC_KEY *key, BN_CTX *ctx)
return 0;
return EC_GROUP_precompute_mult(key->group, ctx);
}
int EC_KEY_get_flags(const EC_KEY *key)
{
return key->flags;
}
void EC_KEY_set_flags(EC_KEY *key, int flags)
{
key->flags |= flags;
}
void EC_KEY_clear_flags(EC_KEY *key, int flags)
{
key->flags &= ~flags;
}
......@@ -249,6 +249,7 @@ struct ec_key_st {
point_conversion_form_t conv_form;
int references;
int flags;
EC_EXTRA_DATA *method_data;
} /* EC_KEY */;
......
......@@ -133,6 +133,11 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ERR_R_EC_LIB);
goto err;
}
#ifdef OPENSSL_FIPS
if (!fips_check_ec_prng(eckey))
goto err;
#endif
do
{
......@@ -235,6 +240,11 @@ static ECDSA_SIG *ecdsa_do_sign(const unsigned char *dgst, int dgst_len,
return NULL;
}
#ifdef OPENSSL_FIPS
if (!fips_check_ec_prng(eckey))
return NULL;
#endif
ret = ECDSA_SIG_new();
if (!ret)
{
......
......@@ -77,9 +77,12 @@ static ERR_STRING_DATA FIPS_str_functs[]=
{ERR_FUNC(FIPS_F_DSA_DO_SIGN), "DSA_do_sign"},
{ERR_FUNC(FIPS_F_DSA_DO_VERIFY), "DSA_do_verify"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_DSA), "FIPS_CHECK_DSA"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_DSA_PRNG), "fips_check_dsa_prng"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_EC), "FIPS_CHECK_EC"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_EC_PRNG), "fips_check_ec_prng"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT), "FIPS_check_incore_fingerprint"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_RSA), "fips_check_rsa"},
{ERR_FUNC(FIPS_F_FIPS_CHECK_RSA_PRNG), "fips_check_rsa_prng"},
{ERR_FUNC(FIPS_F_FIPS_CIPHERINIT), "FIPS_CIPHERINIT"},
{ERR_FUNC(FIPS_F_FIPS_DIGESTINIT), "FIPS_DIGESTINIT"},
{ERR_FUNC(FIPS_F_FIPS_DRBG_BYTES), "FIPS_DRBG_BYTES"},
......@@ -149,6 +152,7 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
{ERR_REASON(FIPS_R_INSUFFICIENT_SECURITY_STRENGTH),"insufficient security strength"},
{ERR_REASON(FIPS_R_INTERNAL_ERROR) ,"internal error"},
{ERR_REASON(FIPS_R_INVALID_KEY_LENGTH) ,"invalid key length"},
{ERR_REASON(FIPS_R_INVALID_PARAMETERS) ,"invalid parameters"},
{ERR_REASON(FIPS_R_IN_ERROR_STATE) ,"in error state"},
{ERR_REASON(FIPS_R_KEY_TOO_SHORT) ,"key too short"},
{ERR_REASON(FIPS_R_NON_FIPS_METHOD) ,"non fips method"},
......@@ -156,6 +160,7 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
{ERR_REASON(FIPS_R_PAIRWISE_TEST_FAILED) ,"pairwise test failed"},
{ERR_REASON(FIPS_R_PERSONALISATION_ERROR_UNDETECTED),"personalisation error undetected"},
{ERR_REASON(FIPS_R_PERSONALISATION_STRING_TOO_LONG),"personalisation string too long"},
{ERR_REASON(FIPS_R_PRNG_STRENGTH_TOO_LOW),"prng strength too low"},
{ERR_REASON(FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED),"request length error undetected"},
{ERR_REASON(FIPS_R_REQUEST_TOO_LARGE_FOR_DRBG),"request too large for drbg"},
{ERR_REASON(FIPS_R_RESEED_COUNTER_ERROR) ,"reseed counter error"},
......
......@@ -470,6 +470,10 @@ RSA *RSAPrivateKey_dup(RSA *rsa);
*/
#define RSA_FLAG_NON_FIPS_ALLOW 0x0400
/* Application has decided PRNG is good enough to generate a key: don't
* check.
*/
#define RSA_FLAG_CHECKED 0x0800
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
......
......@@ -74,8 +74,49 @@
#include <openssl/fips.h>
#include <openssl/fips_rand.h>
#include <openssl/evp.h>
/* Check PRNG has sufficient security level to handle an RSA operation */
int fips_check_rsa_prng(RSA *rsa, int bits)
{
int strength;
if (!FIPS_mode())
return 1;
if (rsa->flags & (RSA_FLAG_NON_FIPS_ALLOW|RSA_FLAG_CHECKED))
return 1;
if (bits == 0)
bits = BN_num_bits(rsa->n);
/* Should never happen */
if (bits < 1024)
{
FIPSerr(FIPS_F_FIPS_CHECK_RSA_PRNG,FIPS_R_KEY_TOO_SHORT);
return 0;
}
/* From SP800-57 */
if (bits < 2048)
strength = 80;
else if (bits < 3072)
strength = 112;
else if (bits < 7680)
strength = 128;
else if (bits < 15360)
strength = 192;
else
strength = 256;
if (FIPS_rand_strength() >= strength)
return 1;
FIPSerr(FIPS_F_FIPS_CHECK_RSA_PRNG,FIPS_R_PRNG_STRENGTH_TOO_LOW);
return 0;
}
int fips_check_rsa(RSA *rsa)
{
const unsigned char tbs[] = "RSA Pairwise Check Data";
......@@ -164,11 +205,14 @@ static int rsa_builtin_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb)
return 0;
}
if (FIPS_mode() && (bits < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
if (FIPS_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW)
&& (bits < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
{
FIPSerr(FIPS_F_RSA_BUILTIN_KEYGEN,FIPS_R_KEY_TOO_SHORT);
return 0;
}
if (!fips_check_rsa_prng(rsa, bits))
return 0;
#endif
ctx=BN_CTX_new();
......
......@@ -210,7 +210,8 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, BN_GENCB *cb)
BN_CTX *ctx = NULL;
#ifdef OPENSSL_FIPS
if (bits < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS)
if (FIPS_mode() && !(rsa->flags & RSA_FLAG_NON_FIPS_ALLOW) &&
(bits < OPENSSL_RSA_FIPS_MIN_MODULUS_BITS))
{
FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY_EX,FIPS_R_KEY_TOO_SHORT);
return 0;
......@@ -227,6 +228,8 @@ int RSA_X931_generate_key_ex(RSA *rsa, int bits, const BIGNUM *e, BN_GENCB *cb)
FIPSerr(FIPS_F_RSA_X931_GENERATE_KEY_EX,FIPS_R_FIPS_SELFTEST_FAILED);
return 0;
}
if (!fips_check_rsa_prng(rsa, bits))
return 0;
#endif
ctx = BN_CTX_new();
......
......@@ -60,6 +60,7 @@ extern "C" {
#endif
struct dsa_st;
struct ec_key_st;
struct rsa_st;
struct evp_pkey_st;
struct env_md_st;
......@@ -94,6 +95,9 @@ int FIPS_check_incore_fingerprint(void);
void fips_set_selftest_fail(void);
int fips_check_rsa(struct rsa_st *rsa);
int fips_check_rsa_prng(struct rsa_st *rsa, int bits);
int fips_check_dsa_prng(struct dsa_st *dsa, size_t L, size_t N);
int fips_check_ec_prng(struct ec_key_st *ec);
void FIPS_set_locking_callbacks(void (*func)(int mode, int type,
const char *file,int line),
......@@ -239,9 +243,12 @@ void ERR_load_FIPS_strings(void);
#define FIPS_F_DSA_DO_SIGN 103
#define FIPS_F_DSA_DO_VERIFY 104
#define FIPS_F_FIPS_CHECK_DSA 105
#define FIPS_F_FIPS_CHECK_DSA_PRNG 151
#define FIPS_F_FIPS_CHECK_EC 106
#define FIPS_F_FIPS_CHECK_EC_PRNG 152
#define FIPS_F_FIPS_CHECK_INCORE_FINGERPRINT 107
#define FIPS_F_FIPS_CHECK_RSA 108
#define FIPS_F_FIPS_CHECK_RSA_PRNG 150
#define FIPS_F_FIPS_CIPHERINIT 109
#define FIPS_F_FIPS_DIGESTINIT 110
#define FIPS_F_FIPS_DRBG_BYTES 111
......@@ -308,6 +315,7 @@ void ERR_load_FIPS_strings(void);
#define FIPS_R_INSUFFICIENT_SECURITY_STRENGTH 120
#define FIPS_R_INTERNAL_ERROR 121
#define FIPS_R_INVALID_KEY_LENGTH 122
#define FIPS_R_INVALID_PARAMETERS 144
#define FIPS_R_IN_ERROR_STATE 123
#define FIPS_R_KEY_TOO_SHORT 124
#define FIPS_R_NON_FIPS_METHOD 125
......@@ -315,6 +323,7 @@ void ERR_load_FIPS_strings(void);
#define FIPS_R_PAIRWISE_TEST_FAILED 127
#define FIPS_R_PERSONALISATION_ERROR_UNDETECTED 128
#define FIPS_R_PERSONALISATION_STRING_TOO_LONG 129
#define FIPS_R_PRNG_STRENGTH_TOO_LOW 143
#define FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED 130
#define FIPS_R_REQUEST_TOO_LARGE_FOR_DRBG 131
#define FIPS_R_RESEED_COUNTER_ERROR 132
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册