Change RNG test to block oriented instead of request oriented, add option
to test a "stuck" DRBG.
This commit is contained in:
@@ -268,8 +268,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx,
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -323,76 +322,13 @@ static int fips_drbg_generate_internal(DRBG_CTX *dctx,
|
||||
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;
|
||||
@@ -461,3 +397,37 @@ int FIPS_drbg_get_strength(DRBG_CTX *dctx)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user