Implement continuous RNG test for SP800-90 DRBGs.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 17 Mar 2011 18:53:33 +0000 (18:53 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 17 Mar 2011 18:53:33 +0000 (18:53 +0000)
crypto/fips_err.h
fips/fips.h
fips/rand/fips_drbg_lib.c
fips/rand/fips_rand_lcl.h

index 4b75c2d..4ff3ec1 100644 (file)
@@ -84,6 +84,7 @@ static ERR_STRING_DATA FIPS_str_functs[]=
 {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"},
@@ -118,6 +119,7 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
 {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"},
index af36f03..6dadc1e 100644 (file)
@@ -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
index 0e06273..94bc36a 100644 (file)
@@ -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;
index 7e64bb4..8f97ac0 100644 (file)
@@ -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;
+
        };