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>