Always provide a ctr32_encrypt_blocks function
There were two places where the ctr32_encrypt_blocks function could be
missing:
1. In the AES-CTR EVP_CIPHER, with aes_nohw, we forgot to fill it in but
we actually provide it. We don't care enough about AES-CTR to
benchmark it, but I expect this to be a significant perf win because
aes_nohw is bitsliced.
2. The 32-bit x86 vpaes implementation did not have a
ctr32_encrypt_blocks. Just implement it in C.
This allows us to delete a ton of code for a broadly unreachable
codepath.
32-bit x86 is not a particularly important target in 2024, but just to
confirm, here is the impact on AES-GCM on an Intel(R) Xeon(R) Gold 6154
CPU @ 3.00GHz, running in 32-bit mode and with
OPENSSL_ia32cap='~0x200000000000000'
Before:
Did 5587000 AES-128-GCM (16 bytes) seal operations in 1000098us (5586452.5 ops/sec): 89.4 MB/s
Did 1063000 AES-128-GCM (256 bytes) seal operations in 1000036us (1062961.7 ops/sec): 272.1 MB/s
Did 225000 AES-128-GCM (1350 bytes) seal operations in 1001725us (224612.5 ops/sec): 303.2 MB/s
Did 39000 AES-128-GCM (8192 bytes) seal operations in 1014011us (38461.1 ops/sec): 315.1 MB/s
Did 19127 AES-128-GCM (16384 bytes) seal operations in 1009808us (18941.2 ops/sec): 310.3 MB/s
Did 4742000 AES-256-GCM (16 bytes) seal operations in 1000051us (4741758.2 ops/sec): 75.9 MB/s
Did 820000 AES-256-GCM (256 bytes) seal operations in 1000199us (819836.9 ops/sec): 209.9 MB/s
Did 171000 AES-256-GCM (1350 bytes) seal operations in 1000656us (170887.9 ops/sec): 230.7 MB/s
Did 30000 AES-256-GCM (8192 bytes) seal operations in 1034187us (29008.3 ops/sec): 237.6 MB/s
Did 15000 AES-256-GCM (16384 bytes) seal operations in 1031233us (14545.7 ops/sec): 238.3 MB/s
After:
Did 5314000 AES-128-GCM (16 bytes) seal operations in 1000040us (5313787.4 ops/sec): 85.0 MB/s
Did 1035000 AES-128-GCM (256 bytes) seal operations in 1000919us (1034049.7 ops/sec): 264.7 MB/s
Did 220000 AES-128-GCM (1350 bytes) seal operations in 1001498us (219670.9 ops/sec): 296.6 MB/s
Did 37000 AES-128-GCM (8192 bytes) seal operations in 1009332us (36657.9 ops/sec): 300.3 MB/s
Did 19000 AES-128-GCM (16384 bytes) seal operations in 1018435us (18656.1 ops/sec): 305.7 MB/s
Did 4512250 AES-256-GCM (16 bytes) seal operations in 1000047us (4512037.9 ops/sec): 72.2 MB/s
Did 803000 AES-256-GCM (256 bytes) seal operations in 1000917us (802264.3 ops/sec): 205.4 MB/s
Did 168000 AES-256-GCM (1350 bytes) seal operations in 1002181us (167634.4 ops/sec): 226.3 MB/s
Did 29000 AES-256-GCM (8192 bytes) seal operations in 1033945us (28047.9 ops/sec): 229.8 MB/s
Did 15000 AES-256-GCM (16384 bytes) seal operations in 1055312us (14213.8 ops/sec): 232.9 MB/s
It's a bit slower, but comparable. Any affected device should really be
served ChaCha20-Poly1305 anyway. (Of course, this is entirely
unscientific because this code would never run on anything remotely like
this CPU.)
Fixed: 383994657
Change-Id: Ifca6a6195b20497dc7053d736c61b9000d3074f9
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/74267
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/cipher_extra/e_aesctrhmac.cc b/crypto/cipher_extra/e_aesctrhmac.cc
index f977a89..be94d73 100644
--- a/crypto/cipher_extra/e_aesctrhmac.cc
+++ b/crypto/cipher_extra/e_aesctrhmac.cc
@@ -154,7 +154,7 @@
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 @@
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(
diff --git a/crypto/fipsmodule/aes/aes.cc.inc b/crypto/fipsmodule/aes/aes.cc.inc
index 7eab5ac..05f7a2b 100644
--- a/crypto/fipsmodule/aes/aes.cc.inc
+++ b/crypto/fipsmodule/aes/aes.cc.inc
@@ -125,3 +125,22 @@
}
}
#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
diff --git a/crypto/fipsmodule/aes/aes_test.cc b/crypto/fipsmodule/aes/aes_test.cc
index 75d0520..2024acd 100644
--- a/crypto/fipsmodule/aes/aes_test.cc
+++ b/crypto/fipsmodule/aes/aes_test.cc
@@ -316,9 +316,7 @@
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);
diff --git a/crypto/fipsmodule/aes/internal.h b/crypto/fipsmodule/aes/internal.h
index 170dcc6..7730b00 100644
--- a/crypto/fipsmodule/aes/internal.h
+++ b/crypto/fipsmodule/aes/internal.h
@@ -33,9 +33,6 @@
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 @@
#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 @@
#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_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 @@
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
diff --git a/crypto/fipsmodule/aes/mode_wrappers.cc.inc b/crypto/fipsmodule/aes/mode_wrappers.cc.inc
index 10d98a6..aa76867 100644
--- a/crypto/fipsmodule/aes/mode_wrappers.cc.inc
+++ b/crypto/fipsmodule/aes/mode_wrappers.cc.inc
@@ -62,15 +62,10 @@
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);
diff --git a/crypto/fipsmodule/cipher/e_aes.cc.inc b/crypto/fipsmodule/cipher/e_aes.cc.inc
index 9774268..30957f0 100644
--- a/crypto/fipsmodule/cipher/e_aes.cc.inc
+++ b/crypto/fipsmodule/cipher/e_aes.cc.inc
@@ -211,7 +211,7 @@
#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 @@
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_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 @@
#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 @@
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 @@
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 @@
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);
diff --git a/crypto/fipsmodule/cipher/e_aesccm.cc.inc b/crypto/fipsmodule/cipher/e_aesccm.cc.inc
index b20690e..e1682b6 100644
--- a/crypto/fipsmodule/cipher/e_aesccm.cc.inc
+++ b/crypto/fipsmodule/cipher/e_aesccm.cc.inc
@@ -188,13 +188,8 @@
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;
}
diff --git a/crypto/fipsmodule/cipher/internal.h b/crypto/fipsmodule/cipher/internal.h
index af902e0..e9709f0 100644
--- a/crypto/fipsmodule/cipher/internal.h
+++ b/crypto/fipsmodule/cipher/internal.h
@@ -152,7 +152,7 @@
// 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);
diff --git a/crypto/fipsmodule/modes/ctr.cc.inc b/crypto/fipsmodule/modes/ctr.cc.inc
index 8c333bb..3eae832 100644
--- a/crypto/fipsmodule/modes/ctr.cc.inc
+++ b/crypto/fipsmodule/modes/ctr.cc.inc
@@ -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;
diff --git a/crypto/fipsmodule/modes/gcm.cc.inc b/crypto/fipsmodule/modes/gcm.cc.inc
index 2d67eea..cbd1858 100644
--- a/crypto/fipsmodule/modes/gcm.cc.inc
+++ b/crypto/fipsmodule/modes/gcm.cc.inc
@@ -406,173 +406,6 @@
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) {
diff --git a/crypto/fipsmodule/modes/internal.h b/crypto/fipsmodule/modes/internal.h
index 4cedc39..263b314 100644
--- a/crypto/fipsmodule/modes/internal.h
+++ b/crypto/fipsmodule/modes/internal.h
@@ -97,21 +97,14 @@
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 @@
// 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
diff --git a/crypto/fipsmodule/rand/ctrdrbg.cc.inc b/crypto/fipsmodule/rand/ctrdrbg.cc.inc
index 239a2ec..c60eb8d 100644
--- a/crypto/fipsmodule/rand/ctrdrbg.cc.inc
+++ b/crypto/fipsmodule/rand/ctrdrbg.cc.inc
@@ -181,17 +181,10 @@
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;