Check for uninitialised DRBG_CTX and don't free up default DRBG_CTX.
[openssl.git] / fips / rand / fips_drbg_hash.c
index 4dbcdb6..4b3b723 100644 (file)
@@ -56,8 +56,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <openssl/crypto.h>
-#include <openssl/evp.h>
-#include <openssl/aes.h>
 #include <openssl/fips.h>
 #include <openssl/fips_rand.h>
 #include "fips_rand_lcl.h"
@@ -195,17 +193,29 @@ static int hash_gen(DRBG_CTX *dctx, unsigned char *out, size_t outlen)
                {
                FIPS_digestinit(&hctx->mctx, hctx->md);
                FIPS_digestupdate(&hctx->mctx, hctx->vtmp, dctx->seedlen);
-               if (outlen < dctx->blocklength)
+               if (!(dctx->xflags & DRBG_FLAG_TEST) && !dctx->lb_valid)
+                       {
+                       FIPS_digestfinal(&hctx->mctx, dctx->lb, NULL);
+                       dctx->lb_valid = 1;
+                       }
+               else if (outlen < dctx->blocklength)
                        {
                        FIPS_digestfinal(&hctx->mctx, hctx->vtmp, NULL);
+                       if (!fips_drbg_cprng_test(dctx, hctx->vtmp))
+                               return 0;
                        memcpy(out, hctx->vtmp, outlen);
                        return 1;
                        }
-               FIPS_digestfinal(&hctx->mctx, out, NULL);
-               outlen -= dctx->blocklength;
-               if (outlen == 0)
-                       return 1;
-               out += dctx->blocklength;
+               else
+                       {
+                       FIPS_digestfinal(&hctx->mctx, out, NULL);
+                       if (!fips_drbg_cprng_test(dctx, out))
+                               return 0;
+                       outlen -= dctx->blocklength;
+                       if (outlen == 0)
+                               return 1;
+                       out += dctx->blocklength;
+                       }
                ctx_add_buf(dctx, hctx->vtmp, NULL, 0);
                }
        }
@@ -306,46 +316,39 @@ static int drbg_hash_generate(DRBG_CTX *dctx,
        return 1;
        }
 
+static int drbg_hash_uninstantiate(DRBG_CTX *dctx)
+       {
+       EVP_MD_CTX_cleanup(&dctx->d.hash.mctx);
+       OPENSSL_cleanse(&dctx->d.hash, sizeof(DRBG_HASH_CTX));
+       return 1;
+       }
+
 int fips_drbg_hash_init(DRBG_CTX *dctx)
        {
        const EVP_MD *md;
        DRBG_HASH_CTX *hctx = &dctx->d.hash;
+       md = FIPS_get_digestbynid(dctx->type);
+       if (!md)
+               return -2;
        switch (dctx->type)
                {
                case NID_sha1:
-               md = EVP_sha1();
                dctx->strength = 128;
                break;
 
                case NID_sha224:
-               md = EVP_sha224();
                dctx->strength = 192;
                break;
 
-               case NID_sha256:
-               md = EVP_sha256();
-               dctx->strength = 256;
-               break;
-
-               case NID_sha384:
-               md = EVP_sha384();
-               dctx->strength = 256;
-               break;
-
-               case NID_sha512:
-               md = EVP_sha512();
-               dctx->strength = 256;
-               break;
-
                default:
-               return -2;
+               dctx->strength = 256;
                break;
-
                }
 
        dctx->instantiate = drbg_hash_instantiate;
        dctx->reseed = drbg_hash_reseed;
        dctx->generate = drbg_hash_generate;
+       dctx->uninstantiate = drbg_hash_uninstantiate;
 
        dctx->d.hash.md = md;
        EVP_MD_CTX_init(&hctx->mctx);
@@ -360,15 +363,16 @@ int fips_drbg_hash_init(DRBG_CTX *dctx)
 
 
        dctx->min_entropy = dctx->strength / 8;
-       dctx->max_entropy = DRBG_MAX_ENTROPY;
+       dctx->max_entropy = DRBG_MAX_LENGTH;
 
        dctx->min_nonce = dctx->min_entropy / 2;
-       dctx->max_nonce = DRBG_MAX_NONCE;
+       dctx->max_nonce = DRBG_MAX_LENGTH;
 
        dctx->max_pers = DRBG_MAX_LENGTH;
        dctx->max_adin = DRBG_MAX_LENGTH;
 
-       dctx->max_request = 1<<19;
+       dctx->max_request = 1<<16;
+       dctx->reseed_interval = 1<<24;
 
        return 1;
        }