summaryrefslogtreecommitdiffstats
path: root/fips
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2011-03-17 18:53:33 +0000
committerDr. Stephen Henson <steve@openssl.org>2011-03-17 18:53:33 +0000
commit1e803100de9e88fff6fc586a54e12dda5861557b (patch)
tree4684ba2eb2d07755572b190d84f6761796491a12 /fips
parent96ec46f7c03a94f74cc05ebdf7a8889174acb28d (diff)
Implement continuous RNG test for SP800-90 DRBGs.
Diffstat (limited to 'fips')
-rw-r--r--fips/fips.h2
-rw-r--r--fips/rand/fips_drbg_lib.c68
-rw-r--r--fips/rand/fips_rand_lcl.h6
3 files changed, 74 insertions, 2 deletions
diff --git a/fips/fips.h b/fips/fips.h
index af36f03236..6dadc1ee18 100644
--- a/fips/fips.h
+++ b/fips/fips.h
@@ -194,6 +194,7 @@ void ERR_load_FIPS_strings(void);
#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
@@ -225,6 +226,7 @@ void ERR_load_FIPS_strings(void);
#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
diff --git a/fips/rand/fips_drbg_lib.c b/fips/rand/fips_drbg_lib.c
index 0e06273cef..94bc36a31f 100644
--- a/fips/rand/fips_drbg_lib.c
+++ b/fips/rand/fips_drbg_lib.c
@@ -263,7 +263,8 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx,
}
-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)
{
@@ -313,13 +314,76 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
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;
diff --git a/fips/rand/fips_rand_lcl.h b/fips/rand/fips_rand_lcl.h
index 7e64bb491f..8f97ac00be 100644
--- a/fips/rand/fips_rand_lcl.h
+++ b/fips/rand/fips_rand_lcl.h
@@ -167,6 +167,12 @@ struct drbg_ctx_st
size_t (*get_nonce)(DRBG_CTX *ctx, unsigned char *out,
int entropy, size_t min_len, size_t max_len);
+ /* Continuous random number test temporary area */
+ /* Last block */
+ unsigned char lb[16];
+ /* set if lb is valid */
+ int lb_valid;
+
};