to test a "stuck" DRBG.
static ERR_STRING_DATA FIPS_str_functs[]=
{
{ERR_FUNC(FIPS_F_DH_BUILTIN_GENPARAMS), "DH_BUILTIN_GENPARAMS"},
+{ERR_FUNC(FIPS_F_DRBG_CPRNG_TEST), "DRBG_CPRNG_TEST"},
{ERR_FUNC(FIPS_F_DSA_BUILTIN_PARAMGEN), "DSA_BUILTIN_PARAMGEN"},
{ERR_FUNC(FIPS_F_DSA_BUILTIN_PARAMGEN2), "DSA_BUILTIN_PARAMGEN2"},
{ERR_FUNC(FIPS_F_DSA_DO_SIGN), "DSA_do_sign"},
{ERR_REASON(FIPS_R_GENERATE_ERROR_UNDETECTED),"generate error undetected"},
{ERR_REASON(FIPS_R_INSTANTIATE_ERROR) ,"instantiate error"},
{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_IN_ERROR_STATE) ,"in error state"},
{ERR_REASON(FIPS_R_KEY_TOO_SHORT) ,"key too short"},
void FIPS_corrupt_rng(void);
void FIPS_corrupt_drbg(void);
void FIPS_rng_stick(void);
+void FIPS_drbg_stick(void);
int FIPS_selftest_rng(void);
int FIPS_selftest_hmac(void);
int FIPS_selftest_drbg(void);
/* Function codes. */
#define FIPS_F_DH_BUILTIN_GENPARAMS 100
+#define FIPS_F_DRBG_CPRNG_TEST 141
#define FIPS_F_DSA_BUILTIN_PARAMGEN 101
#define FIPS_F_DSA_BUILTIN_PARAMGEN2 126
#define FIPS_F_DSA_DO_SIGN 102
#define FIPS_R_GENERATE_ERROR_UNDETECTED 136
#define FIPS_R_INSTANTIATE_ERROR 125
#define FIPS_R_INSUFFICIENT_SECURITY_STRENGTH 132
+#define FIPS_R_INTERNAL_ERROR 143
#define FIPS_R_INVALID_KEY_LENGTH 109
#define FIPS_R_IN_ERROR_STATE 126
#define FIPS_R_KEY_TOO_SHORT 108
int do_corrupt_rsa_keygen = 0, do_corrupt_dsa_keygen = 0;
int bad_rsa = 0, bad_dsa = 0;
int do_rng_stick = 0;
+ int do_drbg_stick = 0;
int no_exit = 0;
fips_algtest_init_nofips();
do_rng_stick = 1;
no_exit = 1;
printf("RNG test with stuck continuous test...\n");
+ } else if (!strcmp(argv[1], "drbgstick")) {
+ do_drbg_stick = 1;
+ no_exit = 1;
+ printf("DRBG test with stuck continuous test...\n");
} else {
printf("Bad argument \"%s\"\n", argv[1]);
exit(1);
FIPS_corrupt_dsa_keygen();
if (do_corrupt_rsa_keygen)
FIPS_corrupt_rsa_keygen();
+ if (do_drbg_stick)
+ FIPS_drbg_stick();
if (do_rng_stick)
FIPS_rng_stick();
for (;;)
{
inc_128(cctx);
+ if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid)
+ {
+ AES_encrypt(cctx->V, dctx->lb, &cctx->ks);
+ dctx->lb_valid = 1;
+ continue;
+ }
if (outlen < 16)
{
/* Use K as temp space as it will be updated */
AES_encrypt(cctx->V, cctx->K, &cctx->ks);
+ if (!drbg_cprng_test(dctx, cctx->K))
+ return 0;
memcpy(out, cctx->K, outlen);
break;
}
AES_encrypt(cctx->V, out, &cctx->ks);
+ if (!drbg_cprng_test(dctx, out))
+ return 0;
out += 16;
outlen -= 16;
if (outlen == 0)
{
FIPS_digestinit(&hctx->mctx, hctx->md);
FIPS_digestupdate(&hctx->mctx, hctx->vtmp, dctx->seedlen);
+ if (!(dctx->flags & DRBG_FLAG_TEST) && !dctx->lb_valid)
+ {
+ FIPS_digestfinal(&hctx->mctx, dctx->lb, NULL);
+ dctx->lb_valid = 1;
+ continue;
+ }
if (outlen < dctx->blocklength)
{
FIPS_digestfinal(&hctx->mctx, hctx->vtmp, NULL);
+ if (!drbg_cprng_test(dctx, hctx->vtmp))
+ return 0;
memcpy(out, hctx->vtmp, outlen);
return 1;
}
FIPS_digestfinal(&hctx->mctx, out, NULL);
+ if (!drbg_cprng_test(dctx, out))
+ return 0;
outlen -= dctx->blocklength;
if (outlen == 0)
return 1;
}
-static int fips_drbg_generate_internal(DRBG_CTX *dctx,
- unsigned char *out, size_t outlen,
+int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
int strength, int prediction_resistance,
const unsigned char *adin, size_t adinlen)
{
if (r)
{
if (!(dctx->flags & DRBG_FLAG_NOERR))
- FIPSerr(FIPS_F_FIPS_DRBG_GENERATE_INTERNAL, r);
+ FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, r);
return 0;
}
return 1;
}
-/* external generate function: incorporates continuous RNG test if not
- * in test mode.
- */
-
-int FIPS_drbg_generate(DRBG_CTX *dctx,
- unsigned char *out, size_t outlen,
- int strength, int prediction_resistance,
- const unsigned char *adin, size_t adinlen)
- {
- unsigned char tmp[16], *pout;
- size_t poutlen;
- /* If test mode don't run continuous RNG test */
- if (dctx->flags & DRBG_FLAG_TEST)
- {
- return fips_drbg_generate_internal(dctx, out, outlen,
- strength,
- prediction_resistance,
- adin, adinlen);
- }
- /* If this is the first call generate block and save buffer */
- if (!dctx->lb_valid)
- {
- if (!fips_drbg_generate_internal(dctx, dctx->lb, 16,
- strength, prediction_resistance,
- adin, adinlen))
- return 0;
- dctx->lb_valid = 1;
- }
-
- /* If request less that 16 bytes request 16 in temp buffer */
-
- if (outlen < 16)
- {
- pout = tmp;
- poutlen = 16;
- }
- else
- {
- pout = out;
- poutlen = outlen;
- }
-
- /* Generate data */
- if (!fips_drbg_generate_internal(dctx, pout, poutlen,
- strength, prediction_resistance,
- adin, adinlen))
- return 0;
- /* Compare to last block for continuous PRNG test */
- if (!memcmp(pout, dctx->lb, 16))
- {
- FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, FIPS_R_DRBG_STUCK);
- return 0;
- }
- /* Update last block */
- memcpy(dctx->lb, pout, 16);
- /* Copy to output buffer if needed */
- if (outlen < 16)
- memcpy(out, pout, outlen);
-
- return 1;
-
- }
-
int FIPS_drbg_uninstantiate(DRBG_CTX *dctx)
{
int rv;
{
return dctx->strength;
}
+
+static int drbg_stick = 0;
+
+void FIPS_drbg_stick(void)
+ {
+ drbg_stick = 1;
+ }
+
+/* Continuous DRBG utility function */
+int drbg_cprng_test(DRBG_CTX *dctx, const unsigned char *out)
+ {
+ /* No CPRNG in test mode */
+ if (dctx->flags & DRBG_FLAG_TEST)
+ return 1;
+ /* Check block is valid: should never happen */
+ if (dctx->lb_valid == 0)
+ {
+ FIPSerr(FIPS_F_DRBG_CPRNG_TEST, FIPS_R_INTERNAL_ERROR);
+ fips_set_selftest_fail();
+ return 0;
+ }
+ if (drbg_stick)
+ memcpy(dctx->lb, out, dctx->blocklength);
+ /* Check against last block: fail if match */
+ if (!memcmp(dctx->lb, out, dctx->blocklength))
+ {
+ FIPSerr(FIPS_F_DRBG_CPRNG_TEST, FIPS_R_DRBG_STUCK);
+ fips_set_selftest_fail();
+ return 0;
+ }
+ /* Save last block for next comparison */
+ memcpy(dctx->lb, out, dctx->blocklength);
+ return 1;
+ }
return rv;
}
+static int fips_drbg_pseudo(unsigned char *out, int count)
+ {
+ if (fips_drbg_bytes(out, count) <= 0)
+ return -1;
+ return 1;
+ }
+
static int fips_drbg_status(void)
{
DRBG_CTX *dctx = &ossl_dctx;
fips_drbg_bytes,
fips_drbg_cleanup,
fips_drbg_add,
- fips_drbg_bytes,
+ fips_drbg_pseudo,
fips_drbg_status
};
/* A default maximum length: larger than any reasonable value used in pratice */
#define DRBG_MAX_LENGTH 0x7ffffff0
+/* Maximum DRBG block length: all md sizes are bigger than cipher blocks sizes
+ * so use max digest length.
+ */
+#define DRBG_MAX_BLOCK EVP_MAX_MD_SIZE
/* DRBG context structure */
/* Continuous random number test temporary area */
/* Last block */
- unsigned char lb[16];
+ unsigned char lb[EVP_MAX_MD_SIZE];
/* set if lb is valid */
int lb_valid;
int fips_drbg_ctr_init(DRBG_CTX *dctx);
int fips_drbg_hash_init(DRBG_CTX *dctx);
int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags);
+int drbg_cprng_test(DRBG_CTX *dctx, const unsigned char *out);