{ERR_FUNC(FIPS_F_FIPS_CIPHERINIT), "FIPS_CIPHERINIT"},
{ERR_FUNC(FIPS_F_FIPS_DIGESTINIT), "FIPS_DIGESTINIT"},
{ERR_FUNC(FIPS_F_FIPS_DRBG_GENERATE), "FIPS_drbg_generate"},
+{ERR_FUNC(FIPS_F_FIPS_DRBG_GENERATE_INTERNAL), "FIPS_DRBG_GENERATE_INTERNAL"},
{ERR_FUNC(FIPS_F_FIPS_DRBG_HEALTH_CHECK), "FIPS_DRBG_HEALTH_CHECK"},
{ERR_FUNC(FIPS_F_FIPS_DRBG_INIT), "FIPS_drbg_init"},
{ERR_FUNC(FIPS_F_FIPS_DRBG_INSTANTIATE), "FIPS_drbg_instantiate"},
{ERR_REASON(FIPS_R_CANNOT_READ_EXE) ,"cannot read exe"},
{ERR_REASON(FIPS_R_CANNOT_READ_EXE_DIGEST),"cannot read exe digest"},
{ERR_REASON(FIPS_R_CONTRADICTING_EVIDENCE),"contradicting evidence"},
+{ERR_REASON(FIPS_R_DRBG_STUCK) ,"drbg stuck"},
{ERR_REASON(FIPS_R_ENTROPY_ERROR_UNDETECTED),"entropy error undetected"},
{ERR_REASON(FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED),"entropy not requested for reseed"},
{ERR_REASON(FIPS_R_ERROR_INITIALISING_DRBG),"error initialising drbg"},
#define FIPS_F_FIPS_CIPHERINIT 128
#define FIPS_F_FIPS_DIGESTINIT 127
#define FIPS_F_FIPS_DRBG_GENERATE 132
+#define FIPS_F_FIPS_DRBG_GENERATE_INTERNAL 138
#define FIPS_F_FIPS_DRBG_HEALTH_CHECK 137
#define FIPS_F_FIPS_DRBG_INIT 136
#define FIPS_F_FIPS_DRBG_INSTANTIATE 133
#define FIPS_R_CANNOT_READ_EXE 103
#define FIPS_R_CANNOT_READ_EXE_DIGEST 104
#define FIPS_R_CONTRADICTING_EVIDENCE 114
+#define FIPS_R_DRBG_STUCK 142
#define FIPS_R_ENTROPY_ERROR_UNDETECTED 133
#define FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED 134
#define FIPS_R_ERROR_INITIALISING_DRBG 120
}
-int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
+static int fips_drbg_generate_internal(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, r);
+ FIPSerr(FIPS_F_FIPS_DRBG_GENERATE_INTERNAL, 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;