Expose the CTR_DRBG API.

Change-Id: Ie071dcd94d2ae8aa8ee148682f9b0054ed9e3501
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/52445
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/rand/ctrdrbg.c b/crypto/fipsmodule/rand/ctrdrbg.c
index 3b21d76..d01c797 100644
--- a/crypto/fipsmodule/rand/ctrdrbg.c
+++ b/crypto/fipsmodule/rand/ctrdrbg.c
@@ -12,7 +12,7 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-#include <openssl/rand.h>
+#include <openssl/ctrdrbg.h>
 
 #include <openssl/type_check.h>
 #include <openssl/mem.h>
@@ -28,6 +28,21 @@
 // See table 3.
 static const uint64_t kMaxReseedCount = UINT64_C(1) << 48;
 
+CTR_DRBG_STATE *CTR_DRBG_new(const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
+                             const uint8_t *personalization,
+                             size_t personalization_len) {
+  CTR_DRBG_STATE *drbg = OPENSSL_malloc(sizeof(CTR_DRBG_STATE));
+  if (drbg == NULL ||
+      !CTR_DRBG_init(drbg, entropy, personalization, personalization_len)) {
+    CTR_DRBG_free(drbg);
+    return NULL;
+  }
+
+  return drbg;
+}
+
+void CTR_DRBG_free(CTR_DRBG_STATE *state) { OPENSSL_free(state); }
+
 int CTR_DRBG_init(CTR_DRBG_STATE *drbg,
                   const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
                   const uint8_t *personalization, size_t personalization_len) {
diff --git a/crypto/fipsmodule/rand/ctrdrbg_test.cc b/crypto/fipsmodule/rand/ctrdrbg_test.cc
index 0cc48b1..e6ebbca 100644
--- a/crypto/fipsmodule/rand/ctrdrbg_test.cc
+++ b/crypto/fipsmodule/rand/ctrdrbg_test.cc
@@ -14,7 +14,7 @@
 
 #include <gtest/gtest.h>
 
-#include <openssl/rand.h>
+#include <openssl/ctrdrbg.h>
 #include <openssl/sha.h>
 
 #include "internal.h"
@@ -60,6 +60,18 @@
   CTR_DRBG_clear(&drbg);
 }
 
+TEST(CTRDRBGTest, Allocated) {
+  const uint8_t kSeed[CTR_DRBG_ENTROPY_LEN] = {0};
+
+  CTR_DRBG_STATE *allocated = CTR_DRBG_new(kSeed, nullptr, 0);
+  ASSERT_TRUE(allocated);
+  CTR_DRBG_free(allocated);
+
+  allocated = CTR_DRBG_new(kSeed, nullptr, 1<<20);
+  ASSERT_FALSE(allocated);
+  CTR_DRBG_free(allocated);
+}
+
 TEST(CTRDRBGTest, Large) {
   const uint8_t kSeed[CTR_DRBG_ENTROPY_LEN] = {0};
 
diff --git a/crypto/fipsmodule/rand/internal.h b/crypto/fipsmodule/rand/internal.h
index b0133a8..59c846b 100644
--- a/crypto/fipsmodule/rand/internal.h
+++ b/crypto/fipsmodule/rand/internal.h
@@ -16,6 +16,7 @@
 #define OPENSSL_HEADER_CRYPTO_RAND_INTERNAL_H
 
 #include <openssl/aes.h>
+#include <openssl/ctrdrbg.h>
 
 #include "../../internal.h"
 #include "../modes/internal.h"
@@ -95,17 +96,13 @@
 
 // CTR_DRBG_STATE contains the state of a CTR_DRBG based on AES-256. See SP
 // 800-90Ar1.
-typedef struct {
+struct ctr_drbg_state_st {
   AES_KEY ks;
   block128_f block;
   ctr128_f ctr;
   uint8_t counter[16];
   uint64_t reseed_counter;
-} CTR_DRBG_STATE;
-
-// See SP 800-90Ar1, table 3.
-#define CTR_DRBG_ENTROPY_LEN 48
-#define CTR_DRBG_MAX_GENERATE_LENGTH 65536
+};
 
 // CTR_DRBG_init initialises |*drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of
 // entropy in |entropy| and, optionally, a personalization string up to
@@ -116,27 +113,6 @@
                                  const uint8_t *personalization,
                                  size_t personalization_len);
 
-// CTR_DRBG_reseed reseeds |drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of entropy
-// in |entropy| and, optionally, up to |CTR_DRBG_ENTROPY_LEN| bytes of
-// additional data. It returns one on success or zero on error.
-OPENSSL_EXPORT int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg,
-                                   const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
-                                   const uint8_t *additional_data,
-                                   size_t additional_data_len);
-
-// CTR_DRBG_generate processes to up |CTR_DRBG_ENTROPY_LEN| bytes of additional
-// data (if any) and then writes |out_len| random bytes to |out|, where
-// |out_len| <= |CTR_DRBG_MAX_GENERATE_LENGTH|. It returns one on success or
-// zero on error.
-OPENSSL_EXPORT int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out,
-                                     size_t out_len,
-                                     const uint8_t *additional_data,
-                                     size_t additional_data_len);
-
-// CTR_DRBG_clear zeroises the state of |drbg|.
-OPENSSL_EXPORT void CTR_DRBG_clear(CTR_DRBG_STATE *drbg);
-
-
 #if defined(OPENSSL_X86_64) && !defined(OPENSSL_NO_ASM)
 
 OPENSSL_INLINE int have_rdrand(void) {
diff --git a/crypto/fipsmodule/rand/rand.c b/crypto/fipsmodule/rand/rand.c
index 357be39..b2c61d6 100644
--- a/crypto/fipsmodule/rand/rand.c
+++ b/crypto/fipsmodule/rand/rand.c
@@ -23,6 +23,7 @@
 #endif
 
 #include <openssl/chacha.h>
+#include <openssl/ctrdrbg.h>
 #include <openssl/mem.h>
 #include <openssl/type_check.h>
 
diff --git a/crypto/fipsmodule/rand/urandom_test.cc b/crypto/fipsmodule/rand/urandom_test.cc
index 0a1d753..2c89912 100644
--- a/crypto/fipsmodule/rand/urandom_test.cc
+++ b/crypto/fipsmodule/rand/urandom_test.cc
@@ -15,6 +15,7 @@
 #include <gtest/gtest.h>
 #include <stdlib.h>
 
+#include <openssl/ctrdrbg.h>
 #include <openssl/rand.h>
 
 #include "internal.h"
diff --git a/crypto/fipsmodule/self_check/self_check.c b/crypto/fipsmodule/self_check/self_check.c
index fe9c914..19f5743 100644
--- a/crypto/fipsmodule/self_check/self_check.c
+++ b/crypto/fipsmodule/self_check/self_check.c
@@ -20,6 +20,7 @@
 #include <openssl/aead.h>
 #include <openssl/aes.h>
 #include <openssl/bn.h>
+#include <openssl/ctrdrbg.h>
 #include <openssl/dh.h>
 #include <openssl/digest.h>
 #include <openssl/ec.h>
diff --git a/crypto/fipsmodule/service_indicator/service_indicator_test.cc b/crypto/fipsmodule/service_indicator/service_indicator_test.cc
index d0da9c9..4389b98 100644
--- a/crypto/fipsmodule/service_indicator/service_indicator_test.cc
+++ b/crypto/fipsmodule/service_indicator/service_indicator_test.cc
@@ -20,6 +20,7 @@
 #include <openssl/cipher.h>
 #include <openssl/cmac.h>
 #include <openssl/crypto.h>
+#include <openssl/ctrdrbg.h>
 #include <openssl/dh.h>
 #include <openssl/digest.h>
 #include <openssl/ec.h>
diff --git a/crypto/rand_extra/passive.c b/crypto/rand_extra/passive.c
index a2b388f..f34bc6d 100644
--- a/crypto/rand_extra/passive.c
+++ b/crypto/rand_extra/passive.c
@@ -12,7 +12,8 @@
  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
 
-#include <openssl/base.h>
+#include <openssl/ctrdrbg.h>
+
 #include "../fipsmodule/rand/internal.h"
 
 #if defined(BORINGSSL_FIPS)
diff --git a/include/openssl/base.h b/include/openssl/base.h
index b74e66f..76955c7 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -389,6 +389,7 @@
 typedef struct conf_value_st CONF_VALUE;
 typedef struct crypto_buffer_pool_st CRYPTO_BUFFER_POOL;
 typedef struct crypto_buffer_st CRYPTO_BUFFER;
+typedef struct ctr_drbg_state_st CTR_DRBG_STATE;
 typedef struct dh_st DH;
 typedef struct dsa_st DSA;
 typedef struct ec_group_st EC_GROUP;
diff --git a/include/openssl/ctrdrbg.h b/include/openssl/ctrdrbg.h
new file mode 100644
index 0000000..62afe0c
--- /dev/null
+++ b/include/openssl/ctrdrbg.h
@@ -0,0 +1,76 @@
+/* Copyright (c) 2022, Google Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
+
+#ifndef OPENSSL_HEADER_CTRDRBG_H
+#define OPENSSL_HEADER_CTRDRBG_H
+
+#include <openssl/base.h>
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+
+// FIPS pseudo-random number generator.
+
+
+// CTR-DRBG state objects.
+//
+// CTR_DRBG_STATE contains the state of a FIPS AES-CTR-based pseudo-random
+// number generator. If BoringSSL was built in FIPS mode then this is a FIPS
+// Approved algorithm.
+
+// CTR_DRBG_ENTROPY_LEN is the number of bytes of input entropy. See SP
+// 800-90Ar1, table 3.
+#define CTR_DRBG_ENTROPY_LEN 48
+
+// CTR_DRBG_MAX_GENERATE_LENGTH is the maximum number of bytes that can be
+// generated in a single call to |CTR_DRBG_generate|.
+#define CTR_DRBG_MAX_GENERATE_LENGTH 65536
+
+// CTR_DRBG_new returns an initialized |CTR_DRBG_STATE|, or NULL if either
+// allocation failed or if |personalization_len| is invalid.
+OPENSSL_EXPORT CTR_DRBG_STATE *CTR_DRBG_new(
+    const uint8_t entropy[CTR_DRBG_ENTROPY_LEN], const uint8_t *personalization,
+    size_t personalization_len);
+
+// CTR_DRBG_free frees |state| if non-NULL, or else does nothing.
+OPENSSL_EXPORT void CTR_DRBG_free(CTR_DRBG_STATE* state);
+
+// CTR_DRBG_reseed reseeds |drbg| given |CTR_DRBG_ENTROPY_LEN| bytes of entropy
+// in |entropy| and, optionally, up to |CTR_DRBG_ENTROPY_LEN| bytes of
+// additional data. It returns one on success or zero on error.
+OPENSSL_EXPORT int CTR_DRBG_reseed(CTR_DRBG_STATE *drbg,
+                                   const uint8_t entropy[CTR_DRBG_ENTROPY_LEN],
+                                   const uint8_t *additional_data,
+                                   size_t additional_data_len);
+
+// CTR_DRBG_generate processes to up |CTR_DRBG_ENTROPY_LEN| bytes of additional
+// data (if any) and then writes |out_len| random bytes to |out|, where
+// |out_len| <= |CTR_DRBG_MAX_GENERATE_LENGTH|. It returns one on success or
+// zero on error.
+OPENSSL_EXPORT int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out,
+                                     size_t out_len,
+                                     const uint8_t *additional_data,
+                                     size_t additional_data_len);
+
+// CTR_DRBG_clear zeroises the state of |drbg|.
+OPENSSL_EXPORT void CTR_DRBG_clear(CTR_DRBG_STATE *drbg);
+
+
+#if defined(__cplusplus)
+}  // extern C
+#endif
+
+#endif  // OPENSSL_HEADER_CTRDRBG_H
diff --git a/util/fipstools/acvp/modulewrapper/modulewrapper.cc b/util/fipstools/acvp/modulewrapper/modulewrapper.cc
index f3e583d..f65492c 100644
--- a/util/fipstools/acvp/modulewrapper/modulewrapper.cc
+++ b/util/fipstools/acvp/modulewrapper/modulewrapper.cc
@@ -29,6 +29,7 @@
 #include <openssl/bn.h>
 #include <openssl/cipher.h>
 #include <openssl/cmac.h>
+#include <openssl/ctrdrbg.h>
 #include <openssl/dh.h>
 #include <openssl/digest.h>
 #include <openssl/ec.h>
diff --git a/util/fipstools/test_fips.c b/util/fipstools/test_fips.c
index e192b61..42ed96b 100644
--- a/util/fipstools/test_fips.c
+++ b/util/fipstools/test_fips.c
@@ -21,6 +21,7 @@
 #include <openssl/aes.h>
 #include <openssl/bn.h>
 #include <openssl/crypto.h>
+#include <openssl/ctrdrbg.h>
 #include <openssl/des.h>
 #include <openssl/dh.h>
 #include <openssl/ecdsa.h>