Преглед на файлове

Don't use bsaes over vpaes for CTR-DRBG.

RAND_bytes rarely uses large enough inputs for bsaes to be worth it.
https://boringssl-review.googlesource.com/c/boringssl/+/33589 includes some
rough benchmarks of various bits here. Some observations:

- 8 blocks of bsaes costs roughly 6.5 blocks of vpaes. Note the comparison
  isn't quite accurate because I'm measuring bsaes_ctr32_encrypt_blocks against
  vpaes_encrypt and vpaes in CTR mode today must make do with a C loop. Even
  assuming a cutoff of 6 rather than 7 blocks, it's rare to ask for 96 bytes
  of entropy at a time.

- CTR-DRBG performs some stray block operations (ctr_drbg_update), which bsaes
  is bad at without extra work to fold them into the CTR loop (not really worth
  it).

- CTR-DRBG calculates a couple new key schedules every RAND_bytes call. We
  don't currently have a constant-time bsaes key schedule. Unfortunately, even
  plain vpaes loses to the current aes_nohw used by bsaes, but it's not
  constant-time. Also taking CTR-DRBG out of the bsaes equation

- Machines without AES hardware (clients) are not going to be RNG-bound. It's
  mostly servers pushing way too many CBC IVs that care. This means bsaes's
  current side channel tradeoffs make even less sense here.

I'm not sure yet what we should do for the rest of the bsaes mess, but it seems
clear that we want to stick with vpaes for the RNG.

Bug: 256
Change-Id: Iec8f13af232794afd007cb1065913e8117eeee24
Reviewed-on: https://boringssl-review.googlesource.com/c/34744
Reviewed-by: Adam Langley <agl@google.com>
kris/onging/CECPQ3_patch15
David Benjamin преди 5 години
родител
ревизия
33f456b8b0
променени са 6 файла, в които са добавени 27 реда и са изтрити 16 реда
  1. +2
    -1
      crypto/cipher_extra/e_aesccm.c
  2. +2
    -2
      crypto/cipher_extra/e_aesctrhmac.c
  3. +3
    -2
      crypto/cipher_extra/e_aesgcmsiv.c
  4. +8
    -6
      crypto/fipsmodule/cipher/e_aes.c
  5. +4
    -3
      crypto/fipsmodule/cipher/internal.h
  6. +8
    -2
      crypto/fipsmodule/rand/ctrdrbg.c

+ 2
- 1
crypto/cipher_extra/e_aesccm.c Целия файл

@@ -66,7 +66,8 @@ static int aead_aes_ccm_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
struct aead_aes_ccm_ctx *ccm_ctx = (struct aead_aes_ccm_ctx *)&ctx->state;

block128_f block;
ctr128_f ctr = aes_ctr_set_key(&ccm_ctx->ks.ks, NULL, &block, key, key_len);
ctr128_f ctr = aes_ctr_set_key(&ccm_ctx->ks.ks, NULL, &block, key, key_len,
1 /* large inputs */);
ctx->tag_len = tag_len;
if (!CRYPTO_ccm128_init(&ccm_ctx->ccm, &ccm_ctx->ks.ks, block, ctr, M, L)) {
OPENSSL_PUT_ERROR(CIPHER, ERR_R_INTERNAL_ERROR);


+ 2
- 2
crypto/cipher_extra/e_aesctrhmac.c Целия файл

@@ -94,8 +94,8 @@ static int aead_aes_ctr_hmac_sha256_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
return 0;
}

aes_ctx->ctr =
aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key, aes_key_len);
aes_ctx->ctr = aes_ctr_set_key(&aes_ctx->ks.ks, NULL, &aes_ctx->block, key,
aes_key_len, 1 /* large inputs */);
ctx->tag_len = tag_len;
hmac_init(&aes_ctx->inner_init_state, &aes_ctx->outer_init_state,
key + aes_key_len);


+ 3
- 2
crypto/cipher_extra/e_aesgcmsiv.c Целия файл

@@ -595,7 +595,7 @@ static int aead_aes_gcm_siv_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
OPENSSL_memset(gcm_siv_ctx, 0, sizeof(struct aead_aes_gcm_siv_ctx));

aes_ctr_set_key(&gcm_siv_ctx->ks.ks, NULL, &gcm_siv_ctx->kgk_block, key,
key_len);
key_len, 1 /* large inputs */);
gcm_siv_ctx->is_256 = (key_len == 32);
ctx->tag_len = tag_len;

@@ -719,7 +719,8 @@ static void gcm_siv_keys(

OPENSSL_memcpy(out_keys->auth_key, key_material, 16);
aes_ctr_set_key(&out_keys->enc_key.ks, NULL, &out_keys->enc_block,
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16,
1 /* large inputs */);
}

static int aead_aes_gcm_siv_seal_scatter(


+ 8
- 6
crypto/fipsmodule/cipher/e_aes.c Целия файл

@@ -214,7 +214,7 @@ static int aes_ofb_cipher(EVP_CIPHER_CTX *ctx, uint8_t *out, const uint8_t *in,

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) {
size_t key_bytes, int large_inputs) {
if (hwaes_capable()) {
aes_hw_set_encrypt_key(key, key_bytes * 8, aes_key);
if (gcm_key != NULL) {
@@ -226,7 +226,9 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
return aes_hw_ctr32_encrypt_blocks;
}

if (bsaes_capable()) {
const int bsaes_ok = bsaes_capable();
const int vpaes_ok = vpaes_capable();
if (bsaes_ok && (large_inputs || !vpaes_ok)) {
AES_set_encrypt_key(key, key_bytes * 8, aes_key);
if (gcm_key != NULL) {
CRYPTO_gcm128_init_key(gcm_key, aes_key, AES_encrypt, 0);
@@ -237,7 +239,7 @@ ctr128_f aes_ctr_set_key(AES_KEY *aes_key, GCM128_KEY *gcm_key,
return bsaes_ctr32_encrypt_blocks;
}

if (vpaes_capable()) {
if (vpaes_ok) {
vpaes_set_encrypt_key(key, key_bytes * 8, aes_key);
if (out_block) {
*out_block = vpaes_encrypt;
@@ -295,7 +297,7 @@ static int aes_gcm_init_key(EVP_CIPHER_CTX *ctx, const uint8_t *key,
if (key) {
OPENSSL_memset(&gctx->gcm, 0, sizeof(gctx->gcm));
gctx->ctr = aes_ctr_set_key(&gctx->ks.ks, &gctx->gcm.gcm_key, NULL, key,
ctx->key_len);
ctx->key_len, 1 /* large inputs */);
// If we have an iv can set it directly, otherwise use saved IV.
if (iv == NULL && gctx->iv_set) {
iv = gctx->iv;
@@ -838,8 +840,8 @@ static int aead_aes_gcm_init_impl(struct aead_aes_gcm_ctx *gcm_ctx,
return 0;
}

gcm_ctx->ctr =
aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm_key, NULL, key, key_len);
gcm_ctx->ctr = aes_ctr_set_key(&gcm_ctx->ks.ks, &gcm_ctx->gcm_key, NULL, key,
key_len, 1 /* large inputs */);
*out_tag_len = tag_len;
return 1;
}


+ 4
- 3
crypto/fipsmodule/cipher/internal.h Целия файл

@@ -116,11 +116,12 @@ struct evp_aead_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, or NULL if CTR-mode should be built using |*out_block|.
// |large_input| is a hint to select AES implementations. If it is one, the
// caller expects this key to be used with large inputs.
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);
size_t key_bytes, int large_input);

#if defined(__cplusplus)
} // extern C


+ 8
- 2
crypto/fipsmodule/rand/ctrdrbg.c Целия файл

@@ -57,7 +57,12 @@ int CTR_DRBG_init(CTR_DRBG_STATE *drbg,
seed_material[i] ^= kInitMask[i];
}

drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, seed_material, 32);
// |RAND_bytes| is rarely called with large enough inputs for bsaes to be
// faster than vpaes. bsaes also currently has side channel trade offs
// (https://crbug.com/boringssl/256), which we should especially avoid in the
// PRNG. (Note the size hint is a no-op on machines with AES instructions.)
drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, seed_material, 32,
0 /* small inputs */);
OPENSSL_memcpy(drbg->counter.bytes, seed_material + 32, 16);
drbg->reseed_counter = 1;

@@ -93,7 +98,8 @@ static int ctr_drbg_update(CTR_DRBG_STATE *drbg, const uint8_t *data,
temp[i] ^= data[i];
}

drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, temp, 32);
drbg->ctr = aes_ctr_set_key(&drbg->ks, NULL, &drbg->block, temp, 32,
0 /* small inputs */);
OPENSSL_memcpy(drbg->counter.bytes, temp + 32, 16);

return 1;


Зареждане…
Отказ
Запис