#include <openssl/sha.h>
#ifdef OPENSSL_FIPS
#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
#endif
#include "dsa_locl.h"
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;
if (!seed_len)
{
- RAND_pseudo_bytes(seed, qsize);
+ if (RAND_pseudo_bytes(seed, qsize) < 0)
+ goto err;
seed_is_random = 1;
}
else
return ok;
}
-/* Permissible parameter values for (L,N): see FIPS186-3 4.2 */
+/* Security strength of parameter values for (L,N): see FIPS186-3 4.2
+ * and SP800-131A
+ */
+
+
+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_check_params(size_t L, size_t N)
+static int dsa2_valid_parameters(size_t L, size_t N)
{
if (L == 1024 && N == 160)
- return 1;
+ return 80;
if (L == 2048 && N == 224)
- return 1;
+ return 112;
if (L == 2048 && N == 256)
- return 1;
+ return 112;
if (L == 3072 && N == 256)
+ return 112;
+ 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
FIPS_R_FIPS_SELFTEST_FAILED);
goto err;
}
-#endif
- if (!dsa2_check_params(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)
{
goto err;
if (!seed_in)
- RAND_pseudo_bytes(seed, qsize);
+ {
+ if (RAND_pseudo_bytes(seed, seed_len) < 0)
+ goto err;
+ }
/* step 2 */
if (!EVP_Digest(seed, seed_len, md, NULL, evpmd, NULL))
goto err;
/* do a callback call */
/* step 5 */
}
+ /* Copy seed to seed_out before we mess with it */
+ if (seed_out)
+ memcpy(seed_out, seed, seed_len);
if(!BN_GENCB_call(cb, 2, 0)) goto err;
if(!BN_GENCB_call(cb, 3, 0)) goto err;
ok=1;
err:
- if (ok)
+ if (ok == 1)
{
if(ret->p) BN_free(ret->p);
if(ret->q) BN_free(ret->q);
}
if (counter_ret != NULL) *counter_ret=counter;
if (h_ret != NULL) *h_ret=h;
- if (seed_out)
- memcpy(seed_out, seed, seed_len);
}
if (seed)
OPENSSL_free(seed);