TESTS: add test of decoding of invalid zero length ASN.1 INTEGER zero
[openssl.git] / test / drbgtest.c
index ca8a2113910c11ba8d5c3d741ea20bde569ad843..c1887d659d172601e7281c04c1c52bdaec91be77 100644 (file)
@@ -16,6 +16,7 @@
 #include <openssl/evp.h>
 #include <openssl/aes.h>
 #include "../crypto/rand/rand_lcl.h"
+#include "../crypto/include/internal/rand_int.h"
 
 #if defined(_WIN32)
 # include <windows.h>
@@ -553,7 +554,7 @@ static void reset_hook_ctx(HOOK_CTX *ctx)
 }
 
 /* Resets all drbg hook contexts */
-static void reset_drbg_hook_ctx()
+static void reset_drbg_hook_ctx(void)
 {
     reset_hook_ctx(&master_ctx);
     reset_hook_ctx(&public_ctx);
@@ -691,13 +692,28 @@ static int test_rand_reseed(void)
         || !TEST_ptr_eq(private->parent, master))
         return 0;
 
+    /* uninstantiate the three global DRBGs */
+    RAND_DRBG_uninstantiate(private);
+    RAND_DRBG_uninstantiate(public);
+    RAND_DRBG_uninstantiate(master);
+
+
     /* Install hooks for the following tests */
     hook_drbg(master,  &master_ctx);
     hook_drbg(public,  &public_ctx);
     hook_drbg(private, &private_ctx);
 
+
+    /*
+     * Test initial seeding of shared DRBGs
+     */
+    if (!TEST_true(test_drbg_reseed(1, master, public, private, 1, 1, 1)))
+        goto error;
+    reset_drbg_hook_ctx();
+
+
     /*
-     * Test initial state of shared DRBs
+     * Test initial state of shared DRBGs
      */
     if (!TEST_true(test_drbg_reseed(1, master, public, private, 0, 0, 0)))
         goto error;
@@ -767,6 +783,8 @@ error:
 }
 
 #if defined(OPENSSL_THREADS)
+static int multi_thread_rand_bytes_succeeded = 1;
+static int multi_thread_rand_priv_bytes_succeeded = 1;
 
 static void run_multi_thread_test(void)
 {
@@ -780,8 +798,10 @@ static void run_multi_thread_test(void)
     RAND_DRBG_set_reseed_time_interval(private, 1);
 
     do {
-        RAND_bytes(buf, sizeof(buf));
-        RAND_priv_bytes(buf, sizeof(buf));
+        if (RAND_bytes(buf, sizeof(buf)) <= 0)
+            multi_thread_rand_bytes_succeeded = 0;
+        if (RAND_priv_bytes(buf, sizeof(buf)) <= 0)
+            multi_thread_rand_priv_bytes_succeeded = 0;
     }
     while(time(NULL) - start < 5);
 }
@@ -833,7 +853,7 @@ static int wait_for_thread(thread_t thread)
  * The main thread will also run the test, so we'll have THREADS+1 parallel
  * tests running
  */
-#define THREADS 3
+# define THREADS 3
 
 static int test_multi_thread(void)
 {
@@ -845,10 +865,77 @@ static int test_multi_thread(void)
     run_multi_thread_test();
     for (i = 0; i < THREADS; i++)
         wait_for_thread(t[i]);
+
+    if (!TEST_true(multi_thread_rand_bytes_succeeded))
+        return 0;
+    if (!TEST_true(multi_thread_rand_priv_bytes_succeeded))
+        return 0;
+
     return 1;
 }
 #endif
 
+/*
+ * This function only returns the entropy already added with RAND_add(),
+ * and does not get entropy from the OS.
+ *
+ * Returns 0 on failure and the size of the buffer on success.
+ */
+static size_t get_pool_entropy(RAND_DRBG *drbg,
+                               unsigned char **pout,
+                               int entropy, size_t min_len, size_t max_len,
+                               int prediction_resistance)
+{
+    if (drbg->pool == NULL)
+        return 0;
+
+    if (drbg->pool->entropy < (size_t)entropy || drbg->pool->len < min_len
+        || drbg->pool->len > max_len)
+        return 0;
+
+    *pout = drbg->pool->buffer;
+    return drbg->pool->len;
+}
+
+/*
+ * Clean up the entropy that get_pool_entropy() returned.
+ */
+static void cleanup_pool_entropy(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
+{
+    OPENSSL_secure_clear_free(drbg->pool->buffer, drbg->pool->max_len);
+    OPENSSL_free(drbg->pool);
+    drbg->pool = NULL;
+}
+
+/*
+ * Test that instantiating works when OS entropy is not available and that
+ * RAND_add() is enough to reseed it.
+ */
+static int test_rand_add(void)
+{
+    RAND_DRBG *master = RAND_DRBG_get0_master();
+    RAND_DRBG_get_entropy_fn old_get_entropy = master->get_entropy;
+    RAND_DRBG_cleanup_entropy_fn old_cleanup_entropy = master->cleanup_entropy;
+    int rv = 0;
+    unsigned char rand_add_buf[256];
+
+    master->get_entropy = get_pool_entropy;
+    master->cleanup_entropy = cleanup_pool_entropy;
+    master->reseed_counter++;
+    RAND_DRBG_uninstantiate(master);
+    memset(rand_add_buf, 0xCD, sizeof(rand_add_buf));
+    RAND_add(rand_add_buf, sizeof(rand_add_buf), sizeof(rand_add_buf));
+    if (!TEST_true(RAND_DRBG_instantiate(master, NULL, 0)))
+        goto error;
+
+    rv = 1;
+
+error:
+    master->get_entropy = old_get_entropy;
+    master->cleanup_entropy = old_cleanup_entropy;
+    return rv;
+}
+
 int setup_tests(void)
 {
     app_data_index = RAND_DRBG_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
@@ -856,6 +943,7 @@ int setup_tests(void)
     ADD_ALL_TESTS(test_kats, OSSL_NELEM(drbg_test));
     ADD_ALL_TESTS(test_error_checks, OSSL_NELEM(drbg_test));
     ADD_TEST(test_rand_reseed);
+    ADD_TEST(test_rand_add);
 #if defined(OPENSSL_THREADS)
     ADD_TEST(test_multi_thread);
 #endif