update main-with-bazel from master branch

This commit is contained in:
BoringSSL Robot
2024-12-15 00:08:21 +00:00
12 changed files with 59 additions and 354 deletions
+4 -10
View File
@@ -154,7 +154,7 @@ static void aead_aes_ctr_hmac_sha256_crypt(
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx, uint8_t *out,
const uint8_t *in, size_t len, const uint8_t *nonce) {
// Since the AEAD operation is one-shot, keeping a buffer of unused keystream
// bytes is pointless. However, |CRYPTO_ctr128_encrypt| requires it.
// bytes is pointless. However, |CRYPTO_ctr128_encrypt_ctr32| requires it.
uint8_t partial_block_buffer[AES_BLOCK_SIZE];
unsigned partial_block_offset = 0;
OPENSSL_memset(partial_block_buffer, 0, sizeof(partial_block_buffer));
@@ -163,15 +163,9 @@ static void aead_aes_ctr_hmac_sha256_crypt(
OPENSSL_memcpy(counter, nonce, EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN);
OPENSSL_memset(counter + EVP_AEAD_AES_CTR_HMAC_SHA256_NONCE_LEN, 0, 4);
if (aes_ctx->ctr) {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter,
partial_block_buffer, &partial_block_offset,
aes_ctx->ctr);
} else {
CRYPTO_ctr128_encrypt(in, out, len, &aes_ctx->ks.ks, counter,
partial_block_buffer, &partial_block_offset,
aes_ctx->block);
}
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &aes_ctx->ks.ks, counter,
partial_block_buffer, &partial_block_offset,
aes_ctx->ctr);
}
static int aead_aes_ctr_hmac_sha256_seal_scatter(
+19
View File
@@ -125,3 +125,22 @@ int aes_hw_set_encrypt_key(const uint8_t *user_key, int bits, AES_KEY *key) {
}
}
#endif
#if defined(VPAES) && defined(OPENSSL_X86)
// On x86, there is no |vpaes_ctr32_encrypt_blocks|, so we implement it
// ourselves. This avoids all callers needing to account for a missing function.
void vpaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t blocks,
const AES_KEY *key, const uint8_t iv[16]) {
uint32_t ctr = CRYPTO_load_u32_be(iv + 12);
uint8_t iv_buf[16], enc[16];
OPENSSL_memcpy(iv_buf, iv, 12);
for (size_t i = 0; i < blocks; i++) {
CRYPTO_store_u32_be(iv_buf + 12, ctr);
vpaes_encrypt(iv_buf, enc, key);
CRYPTO_xor16(out, in, enc);
ctr++;
in += 16;
out += 16;
}
}
#endif
-2
View File
@@ -316,9 +316,7 @@ TEST(AESTest, ABI) {
CHECK_ABI(vpaes_cbc_encrypt, buf, buf, AES_BLOCK_SIZE * blocks, &key,
block, AES_ENCRYPT);
#endif
#if defined(VPAES_CTR32)
CHECK_ABI(vpaes_ctr32_encrypt_blocks, buf, buf, blocks, &key, block);
#endif
}
ASSERT_EQ(CHECK_ABI(vpaes_set_decrypt_key, kKey, bits, &key), 0);
+5 -7
View File
@@ -33,9 +33,6 @@ extern "C" {
OPENSSL_INLINE int hwaes_capable(void) { return CRYPTO_is_AESNI_capable(); }
#define VPAES
#if defined(OPENSSL_X86_64)
#define VPAES_CTR32
#endif
#define VPAES_CBC
OPENSSL_INLINE int vpaes_capable(void) { return CRYPTO_is_SSSE3_capable(); }
@@ -47,7 +44,6 @@ OPENSSL_INLINE int hwaes_capable(void) { return CRYPTO_is_ARMv8_AES_capable(); }
#if defined(OPENSSL_ARM)
#define BSAES
#define VPAES
#define VPAES_CTR32
OPENSSL_INLINE int bsaes_capable(void) { return CRYPTO_is_NEON_capable(); }
OPENSSL_INLINE int vpaes_capable(void) { return CRYPTO_is_NEON_capable(); }
#endif
@@ -55,7 +51,6 @@ OPENSSL_INLINE int vpaes_capable(void) { return CRYPTO_is_NEON_capable(); }
#if defined(OPENSSL_AARCH64)
#define VPAES
#define VPAES_CBC
#define VPAES_CTR32
OPENSSL_INLINE int vpaes_capable(void) { return CRYPTO_is_NEON_capable(); }
#endif
@@ -199,10 +194,8 @@ void vpaes_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key);
void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out, size_t length,
const AES_KEY *key, uint8_t *ivec, int enc);
#endif
#if defined(VPAES_CTR32)
void vpaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, const uint8_t ivec[16]);
#endif
#else
OPENSSL_INLINE char vpaes_capable(void) { return 0; }
@@ -229,6 +222,11 @@ OPENSSL_INLINE void vpaes_cbc_encrypt(const uint8_t *in, uint8_t *out,
uint8_t *ivec, int enc) {
abort();
}
OPENSSL_INLINE void vpaes_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
size_t len, const AES_KEY *key,
const uint8_t ivec[16]) {
abort();
}
#endif // !VPAES
@@ -62,15 +62,10 @@ void AES_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
aes_hw_ctr32_encrypt_blocks);
} else if (vpaes_capable()) {
#if defined(VPAES_CTR32)
// TODO(davidben): On ARM, where |BSAES| is additionally defined, this could
// use |vpaes_ctr32_encrypt_blocks_with_bsaes|.
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
vpaes_ctr32_encrypt_blocks);
#else
CRYPTO_ctr128_encrypt(in, out, len, key, ivec, ecount_buf, num,
vpaes_encrypt);
#endif
} else {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, ivec, ecount_buf, num,
aes_nohw_ctr32_encrypt_blocks);
+20 -59
View File
@@ -211,7 +211,7 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
#if defined(BSAES)
assert(bsaes_capable());
dat->stream.ctr = vpaes_ctr32_encrypt_blocks_with_bsaes;
#elif defined(VPAES_CTR32)
#else
dat->stream.ctr = vpaes_ctr32_encrypt_blocks;
#endif
}
@@ -221,6 +221,8 @@ static int aes_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
dat->stream.cbc = NULL;
if (mode == EVP_CIPH_CBC_MODE) {
dat->stream.cbc = aes_nohw_cbc_encrypt;
} else if (mode == EVP_CIPH_CTR_MODE) {
dat->stream.ctr = aes_nohw_ctr32_encrypt_blocks;
}
}
@@ -267,14 +269,8 @@ static int aes_ecb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
static int aes_ctr_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
size_t len) {
EVP_AES_KEY *dat = (EVP_AES_KEY *)ctx->cipher_data;
if (dat->stream.ctr) {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks.ks, ctx->iv, ctx->buf,
&ctx->num, dat->stream.ctr);
} else {
CRYPTO_ctr128_encrypt(in, out, len, &dat->ks.ks, ctx->iv, ctx->buf,
&ctx->num, dat->block);
}
CRYPTO_ctr128_encrypt_ctr32(in, out, len, &dat->ks.ks, ctx->iv, ctx->buf,
&ctx->num, dat->stream.ctr);
return 1;
}
@@ -314,10 +310,8 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
#if defined(BSAES)
assert(bsaes_capable());
return vpaes_ctr32_encrypt_blocks_with_bsaes;
#elif defined(VPAES_CTR32)
return vpaes_ctr32_encrypt_blocks;
#else
return NULL;
return vpaes_ctr32_encrypt_blocks;
#endif
}
@@ -556,26 +550,14 @@ static int aes_gcm_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,
return -1;
}
} else if (ctx->encrypt) {
if (gctx->ctr) {
if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
gctx->ctr)) {
return -1;
}
} else {
if (!CRYPTO_gcm128_encrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
return -1;
}
if (!CRYPTO_gcm128_encrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
gctx->ctr)) {
return -1;
}
} else {
if (gctx->ctr) {
if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
gctx->ctr)) {
return -1;
}
} else {
if (!CRYPTO_gcm128_decrypt(&gctx->gcm, &gctx->ks.ks, in, out, len)) {
return -1;
}
if (!CRYPTO_gcm128_decrypt_ctr32(&gctx->gcm, &gctx->ks.ks, in, out, len,
gctx->ctr)) {
return -1;
}
}
return (int)len;
@@ -973,28 +955,14 @@ static int aead_aes_gcm_seal_scatter_impl(
return 0;
}
if (gcm_ctx->ctr) {
if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len,
gcm_ctx->ctr)) {
return 0;
}
} else {
if (!CRYPTO_gcm128_encrypt(&gcm, key, in, out, in_len)) {
return 0;
}
if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, in, out, in_len, gcm_ctx->ctr)) {
return 0;
}
if (extra_in_len) {
if (gcm_ctx->ctr) {
if (!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, extra_in, out_tag,
extra_in_len, gcm_ctx->ctr)) {
return 0;
}
} else {
if (!CRYPTO_gcm128_encrypt(&gcm, key, extra_in, out_tag, extra_in_len)) {
return 0;
}
}
if (extra_in_len > 0 &&
!CRYPTO_gcm128_encrypt_ctr32(&gcm, key, extra_in, out_tag, extra_in_len,
gcm_ctx->ctr)) {
return 0;
}
CRYPTO_gcm128_tag(&gcm, out_tag + extra_in_len, tag_len);
@@ -1044,15 +1012,8 @@ static int aead_aes_gcm_open_gather_impl(const struct aead_aes_gcm_ctx *gcm_ctx,
return 0;
}
if (gcm_ctx->ctr) {
if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, in_len,
gcm_ctx->ctr)) {
return 0;
}
} else {
if (!CRYPTO_gcm128_decrypt(&gcm, key, in, out, in_len)) {
return 0;
}
if (!CRYPTO_gcm128_decrypt_ctr32(&gcm, key, in, out, in_len, gcm_ctx->ctr)) {
return 0;
}
CRYPTO_gcm128_tag(&gcm, tag, tag_len);
+2 -7
View File
@@ -188,13 +188,8 @@ static int ccm128_encrypt(const struct ccm128_context *ctx,
uint8_t partial_buf[16];
unsigned num = 0;
if (ctx->ctr != NULL) {
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, state->nonce, partial_buf,
&num, ctx->ctr);
} else {
CRYPTO_ctr128_encrypt(in, out, len, key, state->nonce, partial_buf, &num,
ctx->block);
}
CRYPTO_ctr128_encrypt_ctr32(in, out, len, key, state->nonce, partial_buf,
&num, ctx->ctr);
return 1;
}
+1 -1
View File
@@ -152,7 +152,7 @@ struct evp_cipher_st {
// where |key_bytes| must either be 16, 24 or 32. If not NULL, |*out_block| is
// set to a function that encrypts single blocks. If not NULL, |*gcm_key| is
// initialised to do GHASH with the given key. It returns a function for
// optimised CTR-mode, or NULL if CTR-mode should be built using |*out_block|.
// optimised CTR-mode.
ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
block128_f *out_block, const uint8_t *key,
size_t key_bytes);
-62
View File
@@ -53,71 +53,9 @@
#include "../../internal.h"
// NOTE: the IV/counter CTR mode is big-endian. The code itself
// is endian-neutral.
// increment counter (128-bit int) by 1
static void ctr128_inc(uint8_t *counter) {
uint32_t n = 16, c = 1;
do {
--n;
c += counter[n];
counter[n] = (uint8_t) c;
c >>= 8;
} while (n);
}
static_assert(16 % sizeof(crypto_word_t) == 0,
"block cannot be divided into crypto_word_t");
// The input encrypted as though 128bit counter mode is being used. The extra
// state information to record how much of the 128bit block we have used is
// contained in *num, and the encrypted counter is kept in ecount_buf. Both
// *num and ecount_buf must be initialised with zeros before the first call to
// CRYPTO_ctr128_encrypt().
//
// This algorithm assumes that the counter is in the x lower bits of the IV
// (ivec), and that the application has full control over overflow and the rest
// of the IV. This implementation takes NO responsibility for checking that
// the counter doesn't overflow into the rest of the IV when incremented.
void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[16],
uint8_t ecount_buf[16], unsigned int *num,
block128_f block) {
unsigned int n;
assert(key && ecount_buf && num);
assert(len == 0 || (in && out));
assert(*num < 16);
n = *num;
while (n && len) {
*(out++) = *(in++) ^ ecount_buf[n];
--len;
n = (n + 1) % 16;
}
while (len >= 16) {
(*block)(ivec, ecount_buf, key);
ctr128_inc(ivec);
CRYPTO_xor16(out, in, ecount_buf);
len -= 16;
out += 16;
in += 16;
n = 0;
}
if (len) {
(*block)(ivec, ecount_buf, key);
ctr128_inc(ivec);
while (len--) {
out[n] = in[n] ^ ecount_buf[n];
++n;
}
}
*num = n;
}
// increment upper 96 bits of 128-bit counter by 1
static void ctr96_inc(uint8_t *counter) {
uint32_t n = 12, c = 1;
-167
View File
@@ -406,173 +406,6 @@ int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len) {
return 1;
}
int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len) {
block128_f block = ctx->gcm_key.block;
#ifdef GCM_FUNCREF
void (*gcm_gmult_p)(uint8_t Xi[16], const u128 Htable[16]) =
ctx->gcm_key.gmult;
void (*gcm_ghash_p)(uint8_t Xi[16], const u128 Htable[16], const uint8_t *inp,
size_t len) = ctx->gcm_key.ghash;
#endif
uint64_t mlen = ctx->len.msg + len;
if (mlen > ((UINT64_C(1) << 36) - 32) ||
(sizeof(len) == 8 && mlen < len)) {
return 0;
}
ctx->len.msg = mlen;
if (ctx->ares) {
// First call to encrypt finalizes GHASH(AAD)
GCM_MUL(ctx, Xi);
ctx->ares = 0;
}
unsigned n = ctx->mres;
if (n) {
while (n && len) {
ctx->Xi[n] ^= *(out++) = *(in++) ^ ctx->EKi[n];
--len;
n = (n + 1) % 16;
}
if (n == 0) {
GCM_MUL(ctx, Xi);
} else {
ctx->mres = n;
return 1;
}
}
uint32_t ctr = CRYPTO_load_u32_be(ctx->Yi + 12);
while (len >= GHASH_CHUNK) {
size_t j = GHASH_CHUNK;
while (j) {
(*block)(ctx->Yi, ctx->EKi, key);
++ctr;
CRYPTO_store_u32_be(ctx->Yi + 12, ctr);
CRYPTO_xor16(out, in, ctx->EKi);
out += 16;
in += 16;
j -= 16;
}
GHASH(ctx, out - GHASH_CHUNK, GHASH_CHUNK);
len -= GHASH_CHUNK;
}
size_t len_blocks = len & kSizeTWithoutLower4Bits;
if (len_blocks != 0) {
while (len >= 16) {
(*block)(ctx->Yi, ctx->EKi, key);
++ctr;
CRYPTO_store_u32_be(ctx->Yi + 12, ctr);
CRYPTO_xor16(out, in, ctx->EKi);
out += 16;
in += 16;
len -= 16;
}
GHASH(ctx, out - len_blocks, len_blocks);
}
if (len) {
(*block)(ctx->Yi, ctx->EKi, key);
++ctr;
CRYPTO_store_u32_be(ctx->Yi + 12, ctr);
while (len--) {
ctx->Xi[n] ^= out[n] = in[n] ^ ctx->EKi[n];
++n;
}
}
ctx->mres = n;
return 1;
}
int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const AES_KEY *key,
const unsigned char *in, unsigned char *out,
size_t len) {
block128_f block = ctx->gcm_key.block;
#ifdef GCM_FUNCREF
void (*gcm_gmult_p)(uint8_t Xi[16], const u128 Htable[16]) =
ctx->gcm_key.gmult;
void (*gcm_ghash_p)(uint8_t Xi[16], const u128 Htable[16], const uint8_t *inp,
size_t len) = ctx->gcm_key.ghash;
#endif
uint64_t mlen = ctx->len.msg + len;
if (mlen > ((UINT64_C(1) << 36) - 32) ||
(sizeof(len) == 8 && mlen < len)) {
return 0;
}
ctx->len.msg = mlen;
if (ctx->ares) {
// First call to decrypt finalizes GHASH(AAD)
GCM_MUL(ctx, Xi);
ctx->ares = 0;
}
unsigned n = ctx->mres;
if (n) {
while (n && len) {
uint8_t c = *(in++);
*(out++) = c ^ ctx->EKi[n];
ctx->Xi[n] ^= c;
--len;
n = (n + 1) % 16;
}
if (n == 0) {
GCM_MUL(ctx, Xi);
} else {
ctx->mres = n;
return 1;
}
}
uint32_t ctr = CRYPTO_load_u32_be(ctx->Yi + 12);
while (len >= GHASH_CHUNK) {
size_t j = GHASH_CHUNK;
GHASH(ctx, in, GHASH_CHUNK);
while (j) {
(*block)(ctx->Yi, ctx->EKi, key);
++ctr;
CRYPTO_store_u32_be(ctx->Yi + 12, ctr);
CRYPTO_xor16(out, in, ctx->EKi);
out += 16;
in += 16;
j -= 16;
}
len -= GHASH_CHUNK;
}
size_t len_blocks = len & kSizeTWithoutLower4Bits;
if (len_blocks != 0) {
GHASH(ctx, in, len_blocks);
while (len >= 16) {
(*block)(ctx->Yi, ctx->EKi, key);
++ctr;
CRYPTO_store_u32_be(ctx->Yi + 12, ctr);
CRYPTO_xor16(out, in, ctx->EKi);
out += 16;
in += 16;
len -= 16;
}
}
if (len) {
(*block)(ctx->Yi, ctx->EKi, key);
++ctr;
CRYPTO_store_u32_be(ctx->Yi + 12, ctr);
while (len--) {
uint8_t c = in[n];
ctx->Xi[n] ^= c;
out[n] = c ^ ctx->EKi[n];
++n;
}
}
ctx->mres = n;
return 1;
}
int CRYPTO_gcm128_encrypt_ctr32(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len,
ctr128_f stream) {
+4 -23
View File
@@ -97,21 +97,14 @@ OPENSSL_INLINE void CRYPTO_xor16(uint8_t out[16], const uint8_t a[16],
typedef void (*ctr128_f)(const uint8_t *in, uint8_t *out, size_t blocks,
const AES_KEY *key, const uint8_t ivec[16]);
// CRYPTO_ctr128_encrypt encrypts (or decrypts, it's the same in CTR mode)
// CRYPTO_ctr128_encrypt_ctr32 encrypts (or decrypts, it's the same in CTR mode)
// |len| bytes from |in| to |out| using |block| in counter mode. There's no
// requirement that |len| be a multiple of any value and any partial blocks are
// stored in |ecount_buf| and |*num|, which must be zeroed before the initial
// call. The counter is a 128-bit, big-endian value in |ivec| and is
// incremented by this function.
void CRYPTO_ctr128_encrypt(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[16],
uint8_t ecount_buf[16], unsigned *num,
block128_f block);
// CRYPTO_ctr128_encrypt_ctr32 acts like |CRYPTO_ctr128_encrypt| but takes
// |ctr|, a function that performs CTR mode but only deals with the lower 32
// bits of the counter. This is useful when |ctr| can be an optimised
// function.
// incremented by this function. If the counter overflows, it wraps around.
// |ctr| must be a function that performs CTR mode but only deals with the lower
// 32 bits of the counter.
void CRYPTO_ctr128_encrypt_ctr32(const uint8_t *in, uint8_t *out, size_t len,
const AES_KEY *key, uint8_t ivec[16],
uint8_t ecount_buf[16], unsigned *num,
@@ -207,18 +200,6 @@ void CRYPTO_gcm128_setiv(GCM128_CONTEXT *ctx, const AES_KEY *key,
// and zero otherwise.
int CRYPTO_gcm128_aad(GCM128_CONTEXT *ctx, const uint8_t *aad, size_t len);
// CRYPTO_gcm128_encrypt encrypts |len| bytes from |in| to |out|. The |key|
// must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one
// on success and zero otherwise.
int CRYPTO_gcm128_encrypt(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len);
// CRYPTO_gcm128_decrypt decrypts |len| bytes from |in| to |out|. The |key|
// must be the same key that was passed to |CRYPTO_gcm128_init|. It returns one
// on success and zero otherwise.
int CRYPTO_gcm128_decrypt(GCM128_CONTEXT *ctx, const AES_KEY *key,
const uint8_t *in, uint8_t *out, size_t len);
// CRYPTO_gcm128_encrypt_ctr32 encrypts |len| bytes from |in| to |out| using
// a CTR function that only handles the bottom 32 bits of the nonce, like
// |CRYPTO_ctr128_encrypt_ctr32|. The |key| must be the same key that was
+4 -11
View File
@@ -181,17 +181,10 @@ int CTR_DRBG_generate(CTR_DRBG_STATE *drbg, uint8_t *out, size_t out_len,
todo &= ~(AES_BLOCK_SIZE - 1);
const size_t num_blocks = todo / AES_BLOCK_SIZE;
if (drbg->ctr) {
OPENSSL_memset(out, 0, todo);
ctr32_add(drbg, 1);
drbg->ctr(out, out, num_blocks, &drbg->ks, drbg->counter);
ctr32_add(drbg, (uint32_t)(num_blocks - 1));
} else {
for (size_t i = 0; i < todo; i += AES_BLOCK_SIZE) {
ctr32_add(drbg, 1);
drbg->block(drbg->counter, out + i, &drbg->ks);
}
}
OPENSSL_memset(out, 0, todo);
ctr32_add(drbg, 1);
drbg->ctr(out, out, num_blocks, &drbg->ks, drbg->counter);
ctr32_add(drbg, (uint32_t)(num_blocks - 1));
out += todo;
out_len -= todo;