瀏覽代碼

Don't delay-initialize legacy AEADs.

Instead, add a separate init_with_direction hook. Normal AEADs ignore the
direction, while legacy AEADs must be initialized with it. This avoids
maintaining extra state to support the delayed initialization.

Change-Id: I25271f0e56ee2783a2fd4d4026434154d58dc0a8
Reviewed-on: https://boringssl-review.googlesource.com/3731
Reviewed-by: Adam Langley <agl@google.com>
kris/onging/CECPQ3_patch15
David Benjamin 9 年之前
committed by Adam Langley
父節點
當前提交
b34f510b3b
共有 13 個檔案被更改,包括 1186 行新增1176 行删除
  1. +19
    -2
      crypto/cipher/aead.c
  2. +8
    -8
      crypto/cipher/aead_test.c
  3. +20
    -8
      crypto/cipher/e_aes.c
  4. +5
    -2
      crypto/cipher/e_chacha20poly1305.c
  5. +5
    -2
      crypto/cipher/e_rc4.c
  6. +39
    -70
      crypto/cipher/e_ssl3.c
  7. +69
    -89
      crypto/cipher/e_tls.c
  8. +4
    -0
      crypto/cipher/internal.h
  9. +2
    -0
      crypto/err/cipher.errordata
  10. +996
    -992
      crypto/err/err_data.h
  11. +14
    -1
      include/openssl/aead.h
  12. +2
    -0
      include/openssl/cipher.h
  13. +3
    -2
      ssl/t1_enc.c

+ 19
- 2
crypto/cipher/aead.c 查看文件

@@ -33,12 +33,29 @@ size_t EVP_AEAD_max_tag_len(const EVP_AEAD *aead) { return aead->max_tag_len; }
int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len, size_t tag_len,
ENGINE *impl) {
if (!aead->init) {
OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init, CIPHER_R_NO_DIRECTION_SET);
return 0;
}
return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, tag_len,
evp_aead_open);
}

int EVP_AEAD_CTX_init_with_direction(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
ctx->aead = aead;
if (key_len != aead->key_len) {
OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init, CIPHER_R_UNSUPPORTED_KEY_SIZE);
OPENSSL_PUT_ERROR(CIPHER, EVP_AEAD_CTX_init_with_direction,
CIPHER_R_UNSUPPORTED_KEY_SIZE);
return 0;
}
return aead->init(ctx, key, key_len, tag_len);
if (aead->init) {
return aead->init(ctx, key, key_len, tag_len);
} else {
return aead->init_with_direction(ctx, key, key_len, tag_len, dir);
}
}

void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx) {


+ 8
- 8
crypto/cipher/aead_test.c 查看文件

@@ -85,8 +85,8 @@ static int run_test_case(const EVP_AEAD *aead,
* smaller by at least tag length. */
uint8_t out2[sizeof(out)];

if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
NULL)) {
if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bufs[KEY], lengths[KEY],
lengths[TAG], evp_aead_seal)) {
fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
return 0;
}
@@ -123,8 +123,8 @@ static int run_test_case(const EVP_AEAD *aead,
/* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
* reset after each operation. */
EVP_AEAD_CTX_cleanup(&ctx);
if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
NULL)) {
if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bufs[KEY], lengths[KEY],
lengths[TAG], evp_aead_open)) {
fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
return 0;
}
@@ -153,8 +153,8 @@ static int run_test_case(const EVP_AEAD *aead,
/* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
* reset after each operation. */
EVP_AEAD_CTX_cleanup(&ctx);
if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
NULL)) {
if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bufs[KEY], lengths[KEY],
lengths[TAG], evp_aead_open)) {
fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
return 0;
}
@@ -172,8 +172,8 @@ static int run_test_case(const EVP_AEAD *aead,
/* The "stateful" AEADs for implementing pre-AEAD cipher suites need to be
* reset after each operation. */
EVP_AEAD_CTX_cleanup(&ctx);
if (!EVP_AEAD_CTX_init(&ctx, aead, bufs[KEY], lengths[KEY], lengths[TAG],
NULL)) {
if (!EVP_AEAD_CTX_init_with_direction(&ctx, aead, bufs[KEY], lengths[KEY],
lengths[TAG], evp_aead_open)) {
fprintf(stderr, "Failed to init AEAD on line %u\n", line_no);
return 0;
}


+ 20
- 8
crypto/cipher/e_aes.c 查看文件

@@ -1071,8 +1071,11 @@ static const EVP_AEAD aead_aes_128_gcm = {
12, /* nonce len */
EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
aead_aes_gcm_init, aead_aes_gcm_cleanup,
aead_aes_gcm_seal, aead_aes_gcm_open,
aead_aes_gcm_init,
NULL, /* init_with_direction */
aead_aes_gcm_cleanup,
aead_aes_gcm_seal,
aead_aes_gcm_open,
};

static const EVP_AEAD aead_aes_256_gcm = {
@@ -1080,8 +1083,11 @@ static const EVP_AEAD aead_aes_256_gcm = {
12, /* nonce len */
EVP_AEAD_AES_GCM_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_TAG_LEN, /* max tag length */
aead_aes_gcm_init, aead_aes_gcm_cleanup,
aead_aes_gcm_seal, aead_aes_gcm_open,
aead_aes_gcm_init,
NULL, /* init_with_direction */
aead_aes_gcm_cleanup,
aead_aes_gcm_seal,
aead_aes_gcm_open,
};

const EVP_AEAD *EVP_aead_aes_128_gcm(void) { return &aead_aes_128_gcm; }
@@ -1335,8 +1341,11 @@ static const EVP_AEAD aead_aes_128_key_wrap = {
8, /* nonce len */
8, /* overhead */
8, /* max tag length */
aead_aes_key_wrap_init, aead_aes_key_wrap_cleanup,
aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
aead_aes_key_wrap_init,
NULL, /* init_with_direction */
aead_aes_key_wrap_cleanup,
aead_aes_key_wrap_seal,
aead_aes_key_wrap_open,
};

static const EVP_AEAD aead_aes_256_key_wrap = {
@@ -1344,8 +1353,11 @@ static const EVP_AEAD aead_aes_256_key_wrap = {
8, /* nonce len */
8, /* overhead */
8, /* max tag length */
aead_aes_key_wrap_init, aead_aes_key_wrap_cleanup,
aead_aes_key_wrap_seal, aead_aes_key_wrap_open,
aead_aes_key_wrap_init,
NULL, /* init_with_direction */
aead_aes_key_wrap_cleanup,
aead_aes_key_wrap_seal,
aead_aes_key_wrap_open,
};

const EVP_AEAD *EVP_aead_aes_128_key_wrap(void) { return &aead_aes_128_key_wrap; }


+ 5
- 2
crypto/cipher/e_chacha20poly1305.c 查看文件

@@ -209,8 +209,11 @@ static const EVP_AEAD aead_chacha20_poly1305 = {
CHACHA20_NONCE_LEN, /* nonce len */
POLY1305_TAG_LEN, /* overhead */
POLY1305_TAG_LEN, /* max tag length */
aead_chacha20_poly1305_init, aead_chacha20_poly1305_cleanup,
aead_chacha20_poly1305_seal, aead_chacha20_poly1305_open,
aead_chacha20_poly1305_init,
NULL, /* init_with_direction */
aead_chacha20_poly1305_cleanup,
aead_chacha20_poly1305_seal,
aead_chacha20_poly1305_open,
};

const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {


+ 5
- 2
crypto/cipher/e_rc4.c 查看文件

@@ -377,8 +377,11 @@ static const EVP_AEAD aead_rc4_md5_tls = {
0, /* nonce len */
MD5_DIGEST_LENGTH, /* overhead */
MD5_DIGEST_LENGTH, /* max tag length */
aead_rc4_md5_tls_init, aead_rc4_md5_tls_cleanup,
aead_rc4_md5_tls_seal, aead_rc4_md5_tls_open,
aead_rc4_md5_tls_init,
NULL, /* init_with_direction */
aead_rc4_md5_tls_cleanup,
aead_rc4_md5_tls_seal,
aead_rc4_md5_tls_open,
};

const EVP_AEAD *EVP_aead_rc4_md5_tls(void) { return &aead_rc4_md5_tls; }

+ 39
- 70
crypto/cipher/e_ssl3.c 查看文件

@@ -30,17 +30,6 @@
typedef struct {
EVP_CIPHER_CTX cipher_ctx;
EVP_MD_CTX md_ctx;
/* enc_key is the portion of the key used for the stream or block cipher. It
* is retained separately to allow the EVP_CIPHER_CTX to be initialized once
* the direction is known. */
uint8_t enc_key[EVP_MAX_KEY_LENGTH];
uint8_t enc_key_len;
/* iv is the portion of the key used for the fixed IV. It is retained
* separately to allow the EVP_CIPHER_CTX to be initialized once the direction
* is known. */
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t iv_len;
char initialized;
} AEAD_SSL3_CTX;

static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len,
@@ -87,15 +76,13 @@ static void aead_ssl3_cleanup(EVP_AEAD_CTX *ctx) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
EVP_CIPHER_CTX_cleanup(&ssl3_ctx->cipher_ctx);
EVP_MD_CTX_cleanup(&ssl3_ctx->md_ctx);
OPENSSL_cleanse(&ssl3_ctx->enc_key, sizeof(ssl3_ctx->enc_key));
OPENSSL_cleanse(&ssl3_ctx->iv, sizeof(ssl3_ctx->iv));
OPENSSL_free(ssl3_ctx);
ctx->aead_state = NULL;
}

static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t tag_len, const EVP_CIPHER *cipher,
const EVP_MD *md) {
size_t tag_len, enum evp_aead_direction_t dir,
const EVP_CIPHER *cipher, const EVP_MD *md) {
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
tag_len != EVP_MD_size(md)) {
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_init, CIPHER_R_UNSUPPORTED_TAG_SIZE);
@@ -109,11 +96,7 @@ static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,

size_t mac_key_len = EVP_MD_size(md);
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
size_t iv_len = EVP_CIPHER_iv_length(cipher);
assert(mac_key_len + enc_key_len + iv_len == key_len);
assert(mac_key_len < 256);
assert(enc_key_len < 256);
assert(iv_len < 256);
assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len);
/* Although EVP_rc4() is a variable-length cipher, the default key size is
* correct for SSL3. */

@@ -124,14 +107,11 @@ static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
}
EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx);
EVP_MD_CTX_init(&ssl3_ctx->md_ctx);
memcpy(ssl3_ctx->enc_key, &key[mac_key_len], enc_key_len);
ssl3_ctx->enc_key_len = (uint8_t)enc_key_len;
memcpy(ssl3_ctx->iv, &key[mac_key_len + enc_key_len], iv_len);
ssl3_ctx->iv_len = (uint8_t)iv_len;
ssl3_ctx->initialized = 0;

ctx->aead_state = ssl3_ctx;
if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, NULL, NULL, 0) ||
if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
&key[mac_key_len + enc_key_len],
dir == evp_aead_seal) ||
!EVP_DigestInit_ex(&ssl3_ctx->md_ctx, md, NULL) ||
!EVP_DigestUpdate(&ssl3_ctx->md_ctx, key, mac_key_len)) {
aead_ssl3_cleanup(ctx);
@@ -142,31 +122,6 @@ static int aead_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
return 1;
}

/* aead_ssl3_ensure_cipher_init initializes |ssl3_ctx| for encryption (or
* decryption, if |encrypt| is zero). If it has already been initialized, it
* ensures the direction matches and fails otherwise. It returns one on success
* and zero on failure.
*
* Note that, unlike normal AEADs, legacy SSL3 AEADs may not be used concurrently
* due to this (and bulk-cipher-internal) statefulness. */
static int aead_ssl3_ensure_cipher_init(AEAD_SSL3_CTX *ssl3_ctx, int encrypt) {
if (!ssl3_ctx->initialized) {
/* Finish initializing the EVP_CIPHER_CTX now that the direction is
* known. */
if (!EVP_CipherInit_ex(&ssl3_ctx->cipher_ctx, NULL, NULL, ssl3_ctx->enc_key,
ssl3_ctx->iv, encrypt)) {
return 0;
}
ssl3_ctx->initialized = 1;
} else if (ssl3_ctx->cipher_ctx.encrypt != encrypt) {
/* Unlike a normal AEAD, using an SSL3 AEAD once freezes the direction. */
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_ensure_cipher_init,
CIPHER_R_INVALID_OPERATION);
return 0;
}
return 1;
}

static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
@@ -175,6 +130,12 @@ static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
size_t total = 0;

if (!ssl3_ctx->cipher_ctx.encrypt) {
/* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_seal, CIPHER_R_INVALID_OPERATION);
return 0;
}

if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
in_len > INT_MAX) {
/* EVP_CIPHER takes int as input. */
@@ -197,10 +158,6 @@ static int aead_ssl3_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}

if (!aead_ssl3_ensure_cipher_init(ssl3_ctx, 1)) {
return 0;
}

/* Compute the MAC. This must be first in case the operation is being done
* in-place. */
uint8_t mac[EVP_MAX_MD_SIZE];
@@ -257,6 +214,12 @@ static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *ad, size_t ad_len) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;

if (ssl3_ctx->cipher_ctx.encrypt) {
/* Unlike a normal AEAD, an SSL3 AEAD may only be used in one direction. */
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_INVALID_OPERATION);
return 0;
}

size_t mac_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx);
if (in_len < mac_len) {
OPENSSL_PUT_ERROR(CIPHER, aead_ssl3_open, CIPHER_R_BAD_DECRYPT);
@@ -286,10 +249,6 @@ static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}

if (!aead_ssl3_ensure_cipher_init(ssl3_ctx, 0)) {
return 0;
}

/* Decrypt to get the plaintext + MAC + padding. */
size_t total = 0;
int len;
@@ -338,30 +297,35 @@ static int aead_ssl3_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}

static int aead_rc4_md5_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_md5());
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_md5());
}

static int aead_rc4_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_sha1());
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1());
}

static int aead_aes_128_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1());
}

static int aead_aes_256_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1());
}
static int aead_des_ede3_cbc_sha1_ssl3_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len) {
return aead_ssl3_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
const uint8_t *key, size_t key_len,
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1());
}

@@ -370,6 +334,7 @@ static const EVP_AEAD aead_rc4_md5_ssl3 = {
0, /* nonce len */
MD5_DIGEST_LENGTH, /* overhead */
MD5_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_rc4_md5_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
@@ -381,6 +346,7 @@ static const EVP_AEAD aead_rc4_sha1_ssl3 = {
0, /* nonce len */
SHA_DIGEST_LENGTH, /* overhead */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_rc4_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
@@ -392,6 +358,7 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_128_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
@@ -403,6 +370,7 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_256_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,
@@ -414,6 +382,7 @@ static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = {
0, /* nonce len */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_des_ede3_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_seal,


+ 69
- 89
crypto/cipher/e_tls.c 查看文件

@@ -22,6 +22,7 @@
#include <openssl/hmac.h>
#include <openssl/mem.h>
#include <openssl/sha.h>
#include <openssl/type_check.h>

#include "../crypto/internal.h"
#include "internal.h"
@@ -34,37 +35,26 @@ typedef struct {
* separately for the constant-time CBC code. */
uint8_t mac_key[EVP_MAX_MD_SIZE];
uint8_t mac_key_len;
/* enc_key is the portion of the key used for the stream or block
* cipher. It is retained separately to allow the EVP_CIPHER_CTX to be
* initialized once the direction is known. */
uint8_t enc_key[EVP_MAX_KEY_LENGTH];
uint8_t enc_key_len;
/* iv is the portion of the key used for the fixed IV. It is retained
* separately to allow the EVP_CIPHER_CTX to be initialized once the direction
* is known. */
uint8_t iv[EVP_MAX_IV_LENGTH];
uint8_t iv_len;
/* implicit_iv is one iff this is a pre-TLS-1.1 CBC cipher without an explicit
* IV. */
char implicit_iv;
char initialized;
} AEAD_TLS_CTX;

OPENSSL_COMPILE_ASSERT(EVP_MAX_MD_SIZE < 256, mac_key_len_fits_in_uint8_t);

static void aead_tls_cleanup(EVP_AEAD_CTX *ctx) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
EVP_CIPHER_CTX_cleanup(&tls_ctx->cipher_ctx);
HMAC_CTX_cleanup(&tls_ctx->hmac_ctx);
OPENSSL_cleanse(&tls_ctx->mac_key, sizeof(tls_ctx->mac_key));
OPENSSL_cleanse(&tls_ctx->enc_key, sizeof(tls_ctx->enc_key));
OPENSSL_cleanse(&tls_ctx->iv, sizeof(tls_ctx->iv));
OPENSSL_free(tls_ctx);
ctx->aead_state = NULL;
}

static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
size_t tag_len, const EVP_CIPHER *cipher,
const EVP_MD *md, char implicit_iv) {
size_t tag_len, enum evp_aead_direction_t dir,
const EVP_CIPHER *cipher, const EVP_MD *md,
char implicit_iv) {
if (tag_len != EVP_AEAD_DEFAULT_TAG_LENGTH &&
tag_len != EVP_MD_size(md)) {
OPENSSL_PUT_ERROR(CIPHER, aead_tls_init, CIPHER_R_UNSUPPORTED_TAG_SIZE);
@@ -78,11 +68,8 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,

size_t mac_key_len = EVP_MD_size(md);
size_t enc_key_len = EVP_CIPHER_key_length(cipher);
size_t iv_len = implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0;
assert(mac_key_len + enc_key_len + iv_len == key_len);
assert(mac_key_len < 256);
assert(enc_key_len < 256);
assert(iv_len < 256);
assert(mac_key_len + enc_key_len +
(implicit_iv ? EVP_CIPHER_iv_length(cipher) : 0) == key_len);
/* Although EVP_rc4() is a variable-length cipher, the default key size is
* correct for TLS. */

@@ -93,17 +80,15 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
}
EVP_CIPHER_CTX_init(&tls_ctx->cipher_ctx);
HMAC_CTX_init(&tls_ctx->hmac_ctx);
assert(mac_key_len <= EVP_MAX_MD_SIZE);
memcpy(tls_ctx->mac_key, key, mac_key_len);
tls_ctx->mac_key_len = (uint8_t)mac_key_len;
memcpy(tls_ctx->enc_key, &key[mac_key_len], enc_key_len);
tls_ctx->enc_key_len = (uint8_t)enc_key_len;
memcpy(tls_ctx->iv, &key[mac_key_len + enc_key_len], iv_len);
tls_ctx->iv_len = (uint8_t)iv_len;
tls_ctx->implicit_iv = implicit_iv;
tls_ctx->initialized = 0;

ctx->aead_state = tls_ctx;
if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, NULL, NULL, 0) ||
if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, cipher, NULL, &key[mac_key_len],
implicit_iv ? &key[mac_key_len + enc_key_len] : NULL,
dir == evp_aead_seal) ||
!HMAC_Init_ex(&tls_ctx->hmac_ctx, key, mac_key_len, md, NULL)) {
aead_tls_cleanup(ctx);
return 0;
@@ -113,32 +98,6 @@ static int aead_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len,
return 1;
}

/* aead_tls_ensure_cipher_init initializes |tls_ctx| for encryption (or
* decryption, if |encrypt| is zero). If it has already been initialized, it
* ensures the direction matches and fails otherwise. It returns one on success
* and zero on failure.
*
* Note that, unlike normal AEADs, legacy TLS AEADs may not be used concurrently
* due to this (and bulk-cipher-internal) statefulness. */
static int aead_tls_ensure_cipher_init(AEAD_TLS_CTX *tls_ctx, int encrypt) {
if (!tls_ctx->initialized) {
/* Finish initializing the EVP_CIPHER_CTX now that the direction is
* known. */
if (!EVP_CipherInit_ex(&tls_ctx->cipher_ctx, NULL, NULL, tls_ctx->enc_key,
tls_ctx->implicit_iv ? tls_ctx->iv : NULL,
encrypt)) {
return 0;
}
tls_ctx->initialized = 1;
} else if (tls_ctx->cipher_ctx.encrypt != encrypt) {
/* Unlike a normal AEAD, using a TLS AEAD once freezes the direction. */
OPENSSL_PUT_ERROR(CIPHER, aead_tls_ensure_cipher_init,
CIPHER_R_INVALID_OPERATION);
return 0;
}
return 1;
}

static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
size_t *out_len, size_t max_out_len,
const uint8_t *nonce, size_t nonce_len,
@@ -147,6 +106,13 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
size_t total = 0;

if (!tls_ctx->cipher_ctx.encrypt) {
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
OPENSSL_PUT_ERROR(CIPHER, aead_tls_seal, CIPHER_R_INVALID_OPERATION);
return 0;

}

if (in_len + EVP_AEAD_max_overhead(ctx->aead) < in_len ||
in_len > INT_MAX) {
/* EVP_CIPHER takes int as input. */
@@ -169,10 +135,6 @@ static int aead_tls_seal(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}

if (!aead_tls_ensure_cipher_init(tls_ctx, 1)) {
return 0;
}

/* To allow for CBC mode which changes cipher length, |ad| doesn't include the
* length for legacy ciphers. */
uint8_t ad_extra[2];
@@ -249,6 +211,13 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *ad, size_t ad_len) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;

if (tls_ctx->cipher_ctx.encrypt) {
/* Unlike a normal AEAD, a TLS AEAD may only be used in one direction. */
OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_INVALID_OPERATION);
return 0;

}

if (in_len < HMAC_size(&tls_ctx->hmac_ctx)) {
OPENSSL_PUT_ERROR(CIPHER, aead_tls_open, CIPHER_R_BAD_DECRYPT);
return 0;
@@ -277,10 +246,6 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
return 0;
}

if (!aead_tls_ensure_cipher_init(tls_ctx, 0)) {
return 0;
}

/* Configure the explicit IV. */
if (EVP_CIPHER_CTX_mode(&tls_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE &&
!tls_ctx->implicit_iv &&
@@ -394,71 +359,76 @@ static int aead_tls_open(const EVP_AEAD_CTX *ctx, uint8_t *out,
}

static int aead_rc4_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_rc4(), EVP_sha1(), 0);
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_rc4(), EVP_sha1(),
0);
}

static int aead_aes_128_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1(), 0);
}

static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
const uint8_t *key,
size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
static int aead_aes_128_cbc_sha1_tls_implicit_iv_init(
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha1(), 1);
}

static int aead_aes_128_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_128_cbc(),
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_128_cbc(),
EVP_sha256(), 0);
}

static int aead_aes_256_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx, const uint8_t *key,
size_t key_len, size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1(), 0);
}

static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
const uint8_t *key,
size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
static int aead_aes_256_cbc_sha1_tls_implicit_iv_init(
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha1(), 1);
}

static int aead_aes_256_cbc_sha256_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha256(), 0);
}

static int aead_aes_256_cbc_sha384_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_aes_256_cbc(),
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_aes_256_cbc(),
EVP_sha384(), 0);
}

static int aead_des_ede3_cbc_sha1_tls_init(EVP_AEAD_CTX *ctx,
const uint8_t *key, size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1(), 0);
}

static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(EVP_AEAD_CTX *ctx,
const uint8_t *key,
size_t key_len,
size_t tag_len) {
return aead_tls_init(ctx, key, key_len, tag_len, EVP_des_ede3_cbc(),
static int aead_des_ede3_cbc_sha1_tls_implicit_iv_init(
EVP_AEAD_CTX *ctx, const uint8_t *key, size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir) {
return aead_tls_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(),
EVP_sha1(), 1);
}

@@ -467,6 +437,7 @@ static const EVP_AEAD aead_rc4_sha1_tls = {
0, /* nonce len */
SHA_DIGEST_LENGTH, /* overhead */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_rc4_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -478,6 +449,7 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_tls = {
16, /* nonce len (IV) */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_128_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -489,6 +461,7 @@ static const EVP_AEAD aead_aes_128_cbc_sha1_tls_implicit_iv = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_128_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -500,6 +473,7 @@ static const EVP_AEAD aead_aes_128_cbc_sha256_tls = {
16, /* nonce len (IV) */
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_128_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -511,6 +485,7 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls = {
16, /* nonce len (IV) */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_256_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -522,6 +497,7 @@ static const EVP_AEAD aead_aes_256_cbc_sha1_tls_implicit_iv = {
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_256_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -533,6 +509,7 @@ static const EVP_AEAD aead_aes_256_cbc_sha256_tls = {
16, /* nonce len (IV) */
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_256_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -544,6 +521,7 @@ static const EVP_AEAD aead_aes_256_cbc_sha384_tls = {
16, /* nonce len (IV) */
16 + SHA384_DIGEST_LENGTH, /* overhead (padding + SHA384) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_aes_256_cbc_sha384_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -555,6 +533,7 @@ static const EVP_AEAD aead_des_ede3_cbc_sha1_tls = {
8, /* nonce len (IV) */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_des_ede3_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_seal,
@@ -566,6 +545,7 @@ static const EVP_AEAD aead_des_ede3_cbc_sha1_tls_implicit_iv = {
0, /* nonce len */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
NULL, /* init */
aead_des_ede3_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_seal,


+ 4
- 0
crypto/cipher/internal.h 查看文件

@@ -59,6 +59,7 @@

#include <openssl/base.h>

#include <openssl/aead.h>
#include <openssl/asn1t.h>

#if defined(__cplusplus)
@@ -117,6 +118,9 @@ struct evp_aead_st {

int (*init)(struct evp_aead_ctx_st *, const uint8_t *key,
size_t key_len, size_t tag_len);
int (*init_with_direction)(struct evp_aead_ctx_st *, const uint8_t *key,
size_t key_len, size_t tag_len,
enum evp_aead_direction_t dir);
void (*cleanup)(struct evp_aead_ctx_st *);

int (*seal)(const struct evp_aead_ctx_st *ctx, uint8_t *out,


+ 2
- 0
crypto/err/cipher.errordata 查看文件

@@ -1,4 +1,5 @@
CIPHER,function,100,EVP_AEAD_CTX_init
CIPHER,function,131,EVP_AEAD_CTX_init_with_direction
CIPHER,function,101,EVP_AEAD_CTX_open
CIPHER,function,102,EVP_AEAD_CTX_seal
CIPHER,function,103,EVP_CIPHER_CTX_copy
@@ -44,6 +45,7 @@ CIPHER,reason,111,INVALID_NONCE_SIZE
CIPHER,reason,112,INVALID_OPERATION
CIPHER,reason,113,IV_TOO_LARGE
CIPHER,reason,114,NO_CIPHER_SET
CIPHER,reason,124,NO_DIRECTION_SET
CIPHER,reason,115,OUTPUT_ALIASES_INPUT
CIPHER,reason,116,TAG_TOO_LARGE
CIPHER,reason,117,TOO_LARGE


+ 996
- 992
crypto/err/err_data.h
文件差異過大導致無法顯示
查看文件


+ 14
- 1
include/openssl/aead.h 查看文件

@@ -205,7 +205,13 @@ typedef struct evp_aead_ctx_st {
* be used. */
#define EVP_AEAD_DEFAULT_TAG_LENGTH 0

/* EVP_AEAD_init initializes |ctx| for the given AEAD algorithm from |impl|.
/* evp_aead_direction_t denotes the direction of an AEAD operation. */
enum evp_aead_direction_t {
evp_aead_open,
evp_aead_seal,
};

/* EVP_AEAD_CTX_init initializes |ctx| for the given AEAD algorithm from |impl|.
* The |impl| argument may be NULL to choose the default implementation.
* Authentication tags may be truncated by passing a size as |tag_len|. A
* |tag_len| of zero indicates the default tag length and this is defined as
@@ -215,6 +221,13 @@ OPENSSL_EXPORT int EVP_AEAD_CTX_init(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
const uint8_t *key, size_t key_len,
size_t tag_len, ENGINE *impl);

/* EVP_AEAD_CTX_init_with_direction calls |EVP_AEAD_CTX_init| for normal
* AEADs. For TLS-specific and SSL3-specific AEADs, it initializes |ctx| for a
* given direction. */
OPENSSL_EXPORT int EVP_AEAD_CTX_init_with_direction(
EVP_AEAD_CTX *ctx, const EVP_AEAD *aead, const uint8_t *key, size_t key_len,
size_t tag_len, enum evp_aead_direction_t dir);

/* EVP_AEAD_CTX_cleanup frees any data allocated by |ctx|. */
OPENSSL_EXPORT void EVP_AEAD_CTX_cleanup(EVP_AEAD_CTX *ctx);



+ 2
- 0
include/openssl/cipher.h 查看文件

@@ -530,6 +530,7 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cbc(void);
#define CIPHER_F_aead_tls_seal 128
#define CIPHER_F_aes_init_key 129
#define CIPHER_F_aesni_init_key 130
#define CIPHER_F_EVP_AEAD_CTX_init_with_direction 131
#define CIPHER_R_AES_KEY_SETUP_FAILED 100
#define CIPHER_R_BAD_DECRYPT 101
#define CIPHER_R_BAD_KEY_LENGTH 102
@@ -554,5 +555,6 @@ OPENSSL_EXPORT const EVP_CIPHER *EVP_aes_192_cbc(void);
#define CIPHER_R_UNSUPPORTED_NONCE_SIZE 121
#define CIPHER_R_UNSUPPORTED_TAG_SIZE 122
#define CIPHER_R_WRONG_FINAL_BLOCK_LENGTH 123
#define CIPHER_R_NO_DIRECTION_SET 124

#endif /* OPENSSL_HEADER_CIPHER_H */

+ 3
- 2
ssl/t1_enc.c 查看文件

@@ -353,8 +353,9 @@ static int tls1_change_cipher_state_aead(SSL *s, char is_read,
aead_ctx = s->aead_write_ctx;
}

if (!EVP_AEAD_CTX_init(&aead_ctx->ctx, aead, key, key_len,
EVP_AEAD_DEFAULT_TAG_LENGTH, NULL /* engine */)) {
if (!EVP_AEAD_CTX_init_with_direction(
&aead_ctx->ctx, aead, key, key_len, EVP_AEAD_DEFAULT_TAG_LENGTH,
is_read ? evp_aead_open : evp_aead_seal)) {
OPENSSL_free(aead_ctx);
if (is_read) {
s->aead_read_ctx = NULL;


Loading…
取消
儲存