Implement health checks needed by SP800-90.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 17 Mar 2011 16:55:24 +0000 (16:55 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 17 Mar 2011 16:55:24 +0000 (16:55 +0000)
Fix warnings.

Instantiate DRBGs at maximum strength.

12 files changed:
CHANGES
crypto/fips_err.h
fips/ecdh/fips_ecdhvs.c
fips/ecdsa/fips_ecdsavs.c
fips/fips.h
fips/rand/fips_drbg_ctr.c
fips/rand/fips_drbg_hash.c
fips/rand/fips_drbg_lib.c
fips/rand/fips_drbg_selftest.c
fips/rand/fips_drbgvs.c
fips/rand/fips_rand.h
fips/rand/fips_rand_lcl.h

diff --git a/CHANGES b/CHANGES
index 7ab81cb908d138f4d03b672a2a558ed6115431eb..9395529e39da8c5bbed8cebf0dffed0bc545990c 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -4,6 +4,11 @@
 
  Changes between 1.0.1 and 1.1.0  [xx XXX xxxx]
 
+  *) Extensive self tests and health checking required by SP800-90 DRBG.
+     Remove strength parameter from FIPS_drbg_instantiate and always
+     instantiate at maximum supported strength.
+     [Steve Henson]
+
   *) Add SRP support.
      [Tom Wu <tjw@cs.stanford.edu> and Ben Laurie]
 
index 0995b35debc57996bf4e354b283e12ebc8a122ac..4b75c2dc0bf7b5ebd04c88d8b497b68c31b646b5 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_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_FUNC(FIPS_F_FIPS_DRBG_NEW),       "FIPS_drbg_new"},
@@ -117,6 +118,8 @@ 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_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"},
 {ERR_REASON(FIPS_R_ERROR_INSTANTIATING_DRBG),"error instantiating drbg"},
 {ERR_REASON(FIPS_R_ERROR_RETRIEVING_ENTROPY),"error retrieving entropy"},
@@ -127,7 +130,9 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
 {ERR_REASON(FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING),"fingerprint does not match segment aliasing"},
 {ERR_REASON(FIPS_R_FIPS_MODE_ALREADY_SET),"fips mode already set"},
 {ERR_REASON(FIPS_R_FIPS_SELFTEST_FAILED) ,"fips selftest failed"},
+{ERR_REASON(FIPS_R_FUNCTION_ERROR)       ,"function error"},
 {ERR_REASON(FIPS_R_GENERATE_ERROR)       ,"generate error"},
+{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_INVALID_KEY_LENGTH)   ,"invalid key length"},
@@ -136,13 +141,18 @@ static ERR_STRING_DATA FIPS_str_reasons[]=
 {ERR_REASON(FIPS_R_NON_FIPS_METHOD)      ,"non fips method"},
 {ERR_REASON(FIPS_R_NOT_INSTANTIATED)     ,"not instantiated"},
 {ERR_REASON(FIPS_R_PAIRWISE_TEST_FAILED) ,"pairwise test failed"},
+{ERR_REASON(FIPS_R_PERSONALISATION_ERROR_UNDETECTED),"personalisation error undetected"},
 {ERR_REASON(FIPS_R_PERSONALISATION_STRING_TOO_LONG),"personalisation string too long"},
+{ERR_REASON(FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED),"request length error undetected"},
 {ERR_REASON(FIPS_R_REQUEST_TOO_LARGE_FOR_DRBG),"request too large for drbg"},
+{ERR_REASON(FIPS_R_RESEED_COUNTER_ERROR) ,"reseed counter error"},
 {ERR_REASON(FIPS_R_RESEED_ERROR)         ,"reseed error"},
 {ERR_REASON(FIPS_R_RSA_DECRYPT_ERROR)    ,"rsa decrypt error"},
 {ERR_REASON(FIPS_R_RSA_ENCRYPT_ERROR)    ,"rsa encrypt error"},
 {ERR_REASON(FIPS_R_SELFTEST_FAILED)      ,"selftest failed"},
+{ERR_REASON(FIPS_R_STRENGTH_ERROR_UNDETECTED),"strength error undetected"},
 {ERR_REASON(FIPS_R_TEST_FAILURE)         ,"test failure"},
+{ERR_REASON(FIPS_R_UNINSTANTIATE_ZEROISE_ERROR),"uninstantiate zeroise error"},
 {ERR_REASON(FIPS_R_UNSUPPORTED_DRBG_TYPE),"unsupported drbg type"},
 {ERR_REASON(FIPS_R_UNSUPPORTED_PLATFORM) ,"unsupported platform"},
 {0,NULL}
index c68daf2e946ee14623e38b230b9c428b649c187b..38178f5eeac0289041be93f7ea9e2f9a9db7eeac 100644 (file)
@@ -279,7 +279,7 @@ int main(int argc,char **argv)
        int argn = argc - 1;
        FILE *in, *out;
        char buf[2048], lbuf[2048];
-       unsigned char *rhash;
+       unsigned char *rhash = NULL;
        long rhashlen;
        BIGNUM *cx = NULL, *cy = NULL;
        BIGNUM *id = NULL, *ix = NULL, *iy = NULL;
index 379df6550196976a89acb8fbfe9c357b7137cfe1..2492ee42c08fcc01866bd518ec384860faf067d6 100644 (file)
@@ -460,7 +460,7 @@ static int SigVer(FILE *in, FILE *out)
 
 int main(int argc, char **argv)
        {
-       FILE *in, *out;
+       FILE *in = NULL, *out = NULL;
        const char *cmd = argv[1];
        int rv = 0;
        fips_set_error_print();
index cd75e19562a3691c06bde78b7a0adab2e8672dfa..af36f0323645aacd1e2fe0a7ff7b4047b7ed7522 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_HEALTH_CHECK                   137
 #define FIPS_F_FIPS_DRBG_INIT                           136
 #define FIPS_F_FIPS_DRBG_INSTANTIATE                    133
 #define FIPS_F_FIPS_DRBG_NEW                            134
@@ -224,6 +225,8 @@ 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_ENTROPY_ERROR_UNDETECTED                         133
+#define FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED                 134
 #define FIPS_R_ERROR_INITIALISING_DRBG                  120
 #define FIPS_R_ERROR_INSTANTIATING_DRBG                         121
 #define FIPS_R_ERROR_RETRIEVING_ENTROPY                         122
@@ -234,7 +237,9 @@ void ERR_load_FIPS_strings(void);
 #define FIPS_R_FINGERPRINT_DOES_NOT_MATCH_SEGMENT_ALIASING 112
 #define FIPS_R_FIPS_MODE_ALREADY_SET                    102
 #define FIPS_R_FIPS_SELFTEST_FAILED                     106
+#define FIPS_R_FUNCTION_ERROR                           135
 #define FIPS_R_GENERATE_ERROR                           124
+#define FIPS_R_GENERATE_ERROR_UNDETECTED                136
 #define FIPS_R_INSTANTIATE_ERROR                        125
 #define FIPS_R_INSUFFICIENT_SECURITY_STRENGTH           132
 #define FIPS_R_INVALID_KEY_LENGTH                       109
@@ -243,13 +248,18 @@ void ERR_load_FIPS_strings(void);
 #define FIPS_R_NON_FIPS_METHOD                          100
 #define FIPS_R_NOT_INSTANTIATED                                 127
 #define FIPS_R_PAIRWISE_TEST_FAILED                     107
+#define FIPS_R_PERSONALISATION_ERROR_UNDETECTED                 137
 #define FIPS_R_PERSONALISATION_STRING_TOO_LONG          128
+#define FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED          138
 #define FIPS_R_REQUEST_TOO_LARGE_FOR_DRBG               129
+#define FIPS_R_RESEED_COUNTER_ERROR                     139
 #define FIPS_R_RESEED_ERROR                             130
 #define FIPS_R_RSA_DECRYPT_ERROR                        115
 #define FIPS_R_RSA_ENCRYPT_ERROR                        116
 #define FIPS_R_SELFTEST_FAILED                          101
+#define FIPS_R_STRENGTH_ERROR_UNDETECTED                140
 #define FIPS_R_TEST_FAILURE                             117
+#define FIPS_R_UNINSTANTIATE_ZEROISE_ERROR              141
 #define FIPS_R_UNSUPPORTED_DRBG_TYPE                    131
 #define FIPS_R_UNSUPPORTED_PLATFORM                     113
 
index 738abdd835e15f530070283d210f37ccc12e7cf5..7e6d497ad1f9c94abd7c196a5a0783844900048a 100644 (file)
@@ -352,7 +352,7 @@ static int drbg_ctr_generate(DRBG_CTX *dctx,
 
 static int drbg_ctr_uninstantiate(DRBG_CTX *dctx)
        {
-       OPENSSL_cleanse(&dctx->d.ctr, sizeof(DRBG_CTR_CTX));
+       memset(&dctx->d.ctr, 0, sizeof(DRBG_CTR_CTX));
        return 1;
        }
 
@@ -385,7 +385,6 @@ int fips_drbg_ctr_init(DRBG_CTX *dctx)
        dctx->generate = drbg_ctr_generate;
        dctx->uninstantiate = drbg_ctr_uninstantiate;
 
-
        cctx->keylen = keylen;
        dctx->strength = keylen * 8;
        dctx->blocklength = 16;
@@ -423,7 +422,7 @@ int fips_drbg_ctr_init(DRBG_CTX *dctx)
                }
 
        dctx->max_request = 1<<19;
-       dctx->reseed_counter = DRBG_MAX_LENGTH;
+       dctx->reseed_interval = 1<<24;
 
        return 1;
        }
index ca3bce7320d6f6c4464c548897047f2fea1d8afc..f6135c031f8f35ebd7192eb673235f96fac019ed 100644 (file)
@@ -377,6 +377,7 @@ int fips_drbg_hash_init(DRBG_CTX *dctx)
        dctx->max_adin = DRBG_MAX_LENGTH;
 
        dctx->max_request = 1<<19;
+       dctx->reseed_interval = 1<<24;
 
        return 1;
        }
index 31c5a7a8b003c7d6ad3eb9654a7c1b331e416944..0e06273cef2bd854be31996da64d65eca0e7721a 100644 (file)
@@ -118,7 +118,6 @@ void FIPS_drbg_free(DRBG_CTX *dctx)
        }
 
 int FIPS_drbg_instantiate(DRBG_CTX *dctx,
-                               int strength,
                                const unsigned char *pers, size_t perslen)
        {
        size_t entlen, noncelen;
@@ -151,12 +150,6 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx,
                goto end;
                }
 
-       if (strength > dctx->strength)
-               {
-               r = FIPS_R_INSUFFICIENT_SECURITY_STRENGTH;
-               goto end;
-               }
-
        dctx->status = DRBG_STATUS_ERROR;
 
        entlen = dctx->get_entropy(dctx, dctx->entropy, dctx->strength,
@@ -197,8 +190,6 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx,
 
        dctx->status = DRBG_STATUS_READY;
        dctx->reseed_counter = 1;
-       /* Initial test value for reseed interval */
-       dctx->reseed_interval = 1<<24;
 
        end:
 
@@ -208,7 +199,7 @@ int FIPS_drbg_instantiate(DRBG_CTX *dctx,
        if (dctx->status == DRBG_STATUS_READY)
                return 1;
 
-       if (r && !(dctx->flags & DRBG_FLAG_TEST))
+       if (r && !(dctx->flags & DRBG_FLAG_NOERR))
                FIPSerr(FIPS_F_FIPS_DRBG_INSTANTIATE, r);
 
        return 0;
@@ -265,7 +256,7 @@ int FIPS_drbg_reseed(DRBG_CTX *dctx,
        if (dctx->status == DRBG_STATUS_READY)
                return 1;
 
-       if (r && !(dctx->flags & DRBG_FLAG_TEST))
+       if (r && !(dctx->flags & DRBG_FLAG_NOERR))
                FIPSerr(FIPS_F_FIPS_DRBG_RESEED, r);
 
        return 0;
@@ -313,7 +304,7 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
                dctx->status = DRBG_STATUS_ERROR;
                goto end;
                }
-       if (dctx->reseed_counter > dctx->reseed_interval)
+       if (dctx->reseed_counter >= dctx->reseed_interval)
                dctx->status = DRBG_STATUS_RESEED;
        else
                dctx->reseed_counter++;
@@ -321,7 +312,7 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
        end:
        if (r)
                {
-               if (!(dctx->flags & DRBG_FLAG_TEST))
+               if (!(dctx->flags & DRBG_FLAG_NOERR))
                        FIPSerr(FIPS_F_FIPS_DRBG_GENERATE, r);
                return 0;
                }
@@ -331,11 +322,14 @@ int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
 
 int FIPS_drbg_uninstantiate(DRBG_CTX *dctx)
        {
-       int save_type, save_flags, rv;
-       save_type = dctx->type;
-       save_flags = dctx->flags;
+       int rv;
+       if (!dctx->uninstantiate)
+               return 1;
        rv = dctx->uninstantiate(dctx);
-       OPENSSL_cleanse(dctx, sizeof(DRBG_CTX));
+       /* Although we'd like to cleanse here we can't because we have to
+        * test the uninstantiate really zeroes the data.
+        */
+       memset(dctx, 0, sizeof(DRBG_CTX));
        /* If method has problems uninstantiating, return error */
        return rv;
        }
index e94a5d8e79a43abe812dbfabd705ecf48412b0c1..4f28d5ab1505bfe891ec545c9482e3386a6e4e03 100644 (file)
@@ -726,8 +726,10 @@ typedef struct
        {
        const unsigned char *ent;
        size_t entlen;
+       int entcnt;
        const unsigned char *nonce;
        size_t noncelen;
+       int noncecnt;
        } TEST_ENT;
 
 static size_t test_entropy(DRBG_CTX *dctx, unsigned char *out,
@@ -735,6 +737,7 @@ static size_t test_entropy(DRBG_CTX *dctx, unsigned char *out,
        {
        TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
        memcpy(out, t->ent, t->entlen);
+       t->entcnt++;
        return t->entlen;
        }
 
@@ -743,6 +746,7 @@ static size_t test_nonce(DRBG_CTX *dctx, unsigned char *out,
        {
        TEST_ENT *t = FIPS_drbg_get_app_data(dctx);
        memcpy(out, t->nonce, t->noncelen);
+       t->noncecnt++;
        return t->noncelen;
        }
 
@@ -767,8 +771,10 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
        t.entlen = td->entlen;
        t.nonce = td->nonce;
        t.noncelen = td->noncelen;
+       t.entcnt = 0;
+       t.noncecnt = 0;
 
-       if (!FIPS_drbg_instantiate(dctx, 0, td->pers, td->perslen))
+       if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
                goto err;
 
        t.ent = td->entpr;
@@ -796,13 +802,197 @@ static int fips_drbg_single_kat(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
        return rv;
        }
 
+/* This is the "health check" function required by SP800-90. Induce several
+ * failure modes and check an error condition is set.
+ */
+
+static int fips_drbg_health_check(DRBG_CTX *dctx, DRBG_SELFTEST_DATA *td)
+       {
+       unsigned char randout[1024];
+       TEST_ENT t;
+       size_t i;
+       unsigned char *p = (unsigned char *)dctx;
+
+       /* Initialise DRBG */
+
+       if (!FIPS_drbg_init(dctx, td->nid, td->flags))
+               goto err;
+
+       if (!FIPS_drbg_set_test_mode(dctx, test_entropy, test_nonce))
+               goto err;
+
+       FIPS_drbg_set_app_data(dctx, &t);
+
+       t.ent = td->ent;
+       t.entlen = td->entlen;
+       t.nonce = td->nonce;
+       t.noncelen = td->noncelen;
+       t.entcnt = 0;
+       t.noncecnt = 0;
+
+       /* Don't report induced errors */
+       dctx->flags |= DRBG_FLAG_NOERR;
+
+       /* Try too large a personalisation length */
+       if (FIPS_drbg_instantiate(dctx, td->pers, dctx->max_pers + 1) > 0)
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_PERSONALISATION_ERROR_UNDETECTED);
+               goto err;
+               }
+
+       /* Test entropy source failure detection */
+
+       t.entlen = 0;
+       if (FIPS_drbg_instantiate(dctx, td->pers, td->perslen) > 0)
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
+               goto err;
+               }
+
+       /* Try to generate output from uninstantiated DRBG */
+       if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
+                               td->adin, td->adinlen))
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_GENERATE_ERROR_UNDETECTED);
+               goto err;
+               }
+
+       /* Instantiate with valid data. NB: errors now reported again */
+       if (!FIPS_drbg_init(dctx, td->nid, td->flags))
+               goto err;
+       if (!FIPS_drbg_set_test_mode(dctx, test_entropy, test_nonce))
+               goto err;
+       FIPS_drbg_set_app_data(dctx, &t);
+
+       t.entlen = td->entlen;
+       if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
+               goto err;
+
+       /* Check generation is now OK */
+       if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
+                               td->adin, td->adinlen))
+               goto err;
+
+       /* Try to generate with too high a strength.
+        */
+
+       dctx->flags |= DRBG_FLAG_NOERR;
+       if (dctx->strength != 256)
+               {
+               if (FIPS_drbg_generate(dctx, randout, td->katlen, 256, 0,
+                                       td->adin, td->adinlen))
+                       {
+                       FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_STRENGTH_ERROR_UNDETECTED);
+
+                       goto err;
+                       }
+               }
+
+       /* Request too much data for one request */
+       if (FIPS_drbg_generate(dctx, randout, dctx->max_request + 1, 0, 0,
+                               td->adin, td->adinlen))
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_REQUEST_LENGTH_ERROR_UNDETECTED);
+               goto err;
+               }
+
+       /* Check prediction resistance request fails if entropy source
+        * failure.
+        */
+
+       t.entlen = 0;
+
+       if (FIPS_drbg_generate(dctx, randout, td->katlen, 0, 1,
+                               td->adin, td->adinlen))
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_ERROR_UNDETECTED);
+               goto err;
+               }
+               
+
+       /* Instantiate again with valid data */
+
+       if (!FIPS_drbg_init(dctx, td->nid, td->flags))
+               goto err;
+       if (!FIPS_drbg_set_test_mode(dctx, test_entropy, test_nonce))
+               goto err;
+       FIPS_drbg_set_app_data(dctx, &t);
+
+       t.entlen = td->entlen;
+       /* Test reseeding works */
+       dctx->reseed_interval = 2;
+       if (!FIPS_drbg_instantiate(dctx, td->pers, td->perslen))
+               goto err;
+
+       /* Check generation is now OK */
+       if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
+                               td->adin, td->adinlen))
+               goto err;
+       if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
+                               td->adin, td->adinlen))
+               goto err;
+
+       /* DRBG should now require a reseed */
+       if (dctx->status != DRBG_STATUS_RESEED)
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_RESEED_COUNTER_ERROR);
+               goto err;
+               }
+
+
+       /* Generate again and check entropy has been requested for reseed */
+       t.entcnt = 0;
+       if (!FIPS_drbg_generate(dctx, randout, td->katlen, 0, 0,
+                               td->adin, td->adinlen))
+               goto err;
+       if (t.entcnt != 1)
+               {
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_ENTROPY_NOT_REQUESTED_FOR_RESEED);
+               goto err;
+               }
+
+       FIPS_drbg_uninstantiate(dctx);
+       p = (unsigned char *)dctx;
+       /* Standard says we have to check uninstantiate really zeroes
+        * the data...
+        */
+       for (i = 0; i < sizeof(DRBG_CTX); i++)
+               {
+               if (*p != 0)
+                       {
+                       FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_UNINSTANTIATE_ZEROISE_ERROR);
+                       goto err;
+                       }
+               p++;
+               }
+
+       return 1;
+
+       err:
+       /* A real error as opposed to an induced one: underlying function will
+        * indicate the error.
+        */
+       if (!(dctx->flags & DRBG_FLAG_NOERR))
+               FIPSerr(FIPS_F_FIPS_DRBG_HEALTH_CHECK, FIPS_R_FUNCTION_ERROR);
+       FIPS_drbg_uninstantiate(dctx);
+       return 0;
+
+       }
+               
+
 int fips_drbg_kat(DRBG_CTX *dctx, int nid, unsigned int flags)
        {
+       int rv;
        DRBG_SELFTEST_DATA *td;
        for (td = drbg_test; td->nid != 0; td++)
                {
                if (td->nid == nid && td->flags == flags)
-                       return fips_drbg_single_kat(dctx, td);
+                       {
+                       rv = fips_drbg_single_kat(dctx, td);
+                       if (rv <= 0)
+                               return rv;
+                       return fips_drbg_health_check(dctx, td);
+                       }
                }
        return 0;
        }
@@ -815,8 +1005,12 @@ int FIPS_selftest_drbg(void)
        if (!dctx)
                return 0;
        for (td = drbg_test; td->nid != 0; td++)
+               {
                if (!fips_drbg_single_kat(dctx, td))
                        break;
+               if (!fips_drbg_health_check(dctx, td))
+                       break;
+               }
        if (td->nid == 0)
                return 1;
        return 0;
index c60b80bf2f1a2bcad6dc3535e35fe6e8fa6ad03a..0c5839e5530b0386d153a826b263fe061bfcc806 100644 (file)
@@ -156,9 +156,9 @@ static size_t test_nonce(DRBG_CTX *dctx, unsigned char *out,
 int main(int argc,char **argv)
        {
        FILE *in, *out;
-       DRBG_CTX *dctx;
+       DRBG_CTX *dctx = NULL;
        TEST_ENT t;
-       int r, nid;
+       int r, nid = 0;
        int pr = 0;
        char buf[2048], lbuf[2048];
        unsigned char randout[2048];
@@ -166,7 +166,7 @@ int main(int argc,char **argv)
 
        unsigned char *ent = NULL, *nonce = NULL, *pers = NULL, *adin = NULL;
        long entlen, noncelen, perslen, adinlen;
-       int df;
+       int df = 0;
 
        int randoutlen = 0;
 
@@ -251,7 +251,7 @@ int main(int argc,char **argv)
                        FIPS_drbg_set_test_mode(dctx, test_entropy, test_nonce);
                        FIPS_drbg_set_app_data(dctx, &t);
                        randoutlen = (int)FIPS_drbg_get_blocklength(dctx);
-                       r = FIPS_drbg_instantiate(dctx, 0, pers, perslen);
+                       r = FIPS_drbg_instantiate(dctx, pers, perslen);
                        if (!r)
                                {
                                fprintf(stderr, "Error instantiating DRBG\n");
index 829a0e12a41baa968e45f10c906bf618b88ea23d..c4d1d910ba136699507a2154bc939a02966d5412 100644 (file)
@@ -77,7 +77,7 @@ typedef struct drbg_ctx_st DRBG_CTX;
 
 DRBG_CTX *FIPS_drbg_new(int type, unsigned int flags);
 int FIPS_drbg_init(DRBG_CTX *dctx, int type, unsigned int flags);
-int FIPS_drbg_instantiate(DRBG_CTX *dctx, int strength,
+int FIPS_drbg_instantiate(DRBG_CTX *dctx,
                                const unsigned char *pers, size_t perslen);
 int FIPS_drbg_reseed(DRBG_CTX *dctx, const unsigned char *adin, size_t adinlen);
 int FIPS_drbg_generate(DRBG_CTX *dctx, unsigned char *out, size_t outlen,
index 2f0dfac95c584f3eabcd085d111a47e3c7bb8566..7e64bb491f4e27415f642e044fd53eafc43d651c 100644 (file)
@@ -86,6 +86,8 @@ struct drbg_ctr_ctx_st
 
 /* PRNG is in test state */
 #define        DRBG_FLAG_TEST                  0x2
+/* Functions shouldn't call err library */
+#define        DRBG_FLAG_NOERR                 0x4
 
 /* DRBG status values */
 /* not initialised */
@@ -103,7 +105,7 @@ struct drbg_ctr_ctx_st
 
 /* A default maximum length: larger than any reasonable value used in pratice */
 
-#define DRBG_MAX_LENGTH                        0x7fffffff
+#define DRBG_MAX_LENGTH                        0x7ffffff0
 
 /* DRBG context structure */