Update-Note: SSL_CTX_set_min_proto_version(SSL3_VERSION) now fails. SSL_OP_NO_SSLv3 is now zero. Internal SSL3-specific "AEAD"s are gone. Change-Id: I34edb160be40a5eea3e2e0fdea562c6e2adda229 Reviewed-on: https://boringssl-review.googlesource.com/29444 Commit-Queue: David Benjamin <davidben@google.com> CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org> Reviewed-by: Adam Langley <agl@google.com>kris/onging/CECPQ3_patch15
@@ -27,7 +27,6 @@ add_library( | |||
tls_cbc.c | |||
e_tls.c | |||
e_ssl3.c | |||
${CIPHER_ARCH_SOURCES} | |||
) | |||
@@ -84,12 +84,6 @@ static const struct KnownAEAD kAEADs[] = { | |||
{"DES_EDE3_CBC_SHA1_TLSImplicitIV", | |||
EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv, | |||
"des_ede3_cbc_sha1_tls_implicit_iv_tests.txt", true, false, 11}, | |||
{"AES_128_CBC_SHA1_SSL3", EVP_aead_aes_128_cbc_sha1_ssl3, | |||
"aes_128_cbc_sha1_ssl3_tests.txt", true, false, 9}, | |||
{"AES_256_CBC_SHA1_SSL3", EVP_aead_aes_256_cbc_sha1_ssl3, | |||
"aes_256_cbc_sha1_ssl3_tests.txt", true, false, 9}, | |||
{"DES_EDE3_CBC_SHA1_SSL3", EVP_aead_des_ede3_cbc_sha1_ssl3, | |||
"des_ede3_cbc_sha1_ssl3_tests.txt", true, false, 9}, | |||
{"AES_128_CTR_HMAC_SHA256", EVP_aead_aes_128_ctr_hmac_sha256, | |||
"aes_128_ctr_hmac_sha256.txt", false, true, 0}, | |||
{"AES_256_CTR_HMAC_SHA256", EVP_aead_aes_256_ctr_hmac_sha256, | |||
@@ -1,460 +0,0 @@ | |||
/* Copyright (c) 2014, 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. */ | |||
#include <assert.h> | |||
#include <limits.h> | |||
#include <string.h> | |||
#include <openssl/aead.h> | |||
#include <openssl/cipher.h> | |||
#include <openssl/err.h> | |||
#include <openssl/hmac.h> | |||
#include <openssl/md5.h> | |||
#include <openssl/mem.h> | |||
#include <openssl/sha.h> | |||
#include "internal.h" | |||
#include "../internal.h" | |||
#include "../fipsmodule/cipher/internal.h" | |||
typedef struct { | |||
EVP_CIPHER_CTX cipher_ctx; | |||
EVP_MD_CTX md_ctx; | |||
} AEAD_SSL3_CTX; | |||
static int ssl3_mac(AEAD_SSL3_CTX *ssl3_ctx, uint8_t *out, unsigned *out_len, | |||
const uint8_t *ad, size_t ad_len, const uint8_t *in, | |||
size_t in_len) { | |||
size_t md_size = EVP_MD_CTX_size(&ssl3_ctx->md_ctx); | |||
size_t pad_len = (md_size == 20) ? 40 : 48; | |||
// To allow for CBC mode which changes cipher length, |ad| doesn't include the | |||
// length for legacy ciphers. | |||
uint8_t ad_extra[2]; | |||
ad_extra[0] = (uint8_t)(in_len >> 8); | |||
ad_extra[1] = (uint8_t)(in_len & 0xff); | |||
EVP_MD_CTX md_ctx; | |||
EVP_MD_CTX_init(&md_ctx); | |||
uint8_t pad[48]; | |||
uint8_t tmp[EVP_MAX_MD_SIZE]; | |||
OPENSSL_memset(pad, 0x36, pad_len); | |||
if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) || | |||
!EVP_DigestUpdate(&md_ctx, pad, pad_len) || | |||
!EVP_DigestUpdate(&md_ctx, ad, ad_len) || | |||
!EVP_DigestUpdate(&md_ctx, ad_extra, sizeof(ad_extra)) || | |||
!EVP_DigestUpdate(&md_ctx, in, in_len) || | |||
!EVP_DigestFinal_ex(&md_ctx, tmp, NULL)) { | |||
EVP_MD_CTX_cleanup(&md_ctx); | |||
return 0; | |||
} | |||
OPENSSL_memset(pad, 0x5c, pad_len); | |||
if (!EVP_MD_CTX_copy_ex(&md_ctx, &ssl3_ctx->md_ctx) || | |||
!EVP_DigestUpdate(&md_ctx, pad, pad_len) || | |||
!EVP_DigestUpdate(&md_ctx, tmp, md_size) || | |||
!EVP_DigestFinal_ex(&md_ctx, out, out_len)) { | |||
EVP_MD_CTX_cleanup(&md_ctx); | |||
return 0; | |||
} | |||
EVP_MD_CTX_cleanup(&md_ctx); | |||
return 1; | |||
} | |||
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_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, 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, CIPHER_R_UNSUPPORTED_TAG_SIZE); | |||
return 0; | |||
} | |||
if (key_len != EVP_AEAD_key_length(ctx->aead)) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_KEY_LENGTH); | |||
return 0; | |||
} | |||
size_t mac_key_len = EVP_MD_size(md); | |||
size_t enc_key_len = EVP_CIPHER_key_length(cipher); | |||
assert(mac_key_len + enc_key_len + EVP_CIPHER_iv_length(cipher) == key_len); | |||
AEAD_SSL3_CTX *ssl3_ctx = OPENSSL_malloc(sizeof(AEAD_SSL3_CTX)); | |||
if (ssl3_ctx == NULL) { | |||
OPENSSL_PUT_ERROR(CIPHER, ERR_R_MALLOC_FAILURE); | |||
return 0; | |||
} | |||
EVP_CIPHER_CTX_init(&ssl3_ctx->cipher_ctx); | |||
EVP_MD_CTX_init(&ssl3_ctx->md_ctx); | |||
ctx->aead_state = ssl3_ctx; | |||
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); | |||
ctx->aead_state = NULL; | |||
return 0; | |||
} | |||
EVP_CIPHER_CTX_set_padding(&ssl3_ctx->cipher_ctx, 0); | |||
return 1; | |||
} | |||
static size_t aead_ssl3_tag_len(const EVP_AEAD_CTX *ctx, const size_t in_len, | |||
const size_t extra_in_len) { | |||
assert(extra_in_len == 0); | |||
const AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX*)ctx->aead_state; | |||
const size_t digest_len = EVP_MD_CTX_size(&ssl3_ctx->md_ctx); | |||
if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) != EVP_CIPH_CBC_MODE) { | |||
// The NULL cipher. | |||
return digest_len; | |||
} | |||
const size_t block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx); | |||
// An overflow of |in_len + digest_len| doesn't affect the result mod | |||
// |block_size|, provided that |block_size| is a smaller power of two. | |||
assert(block_size != 0 && (block_size & (block_size - 1)) == 0); | |||
const size_t pad_len = block_size - ((in_len + digest_len) % block_size); | |||
return digest_len + pad_len; | |||
} | |||
static int aead_ssl3_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out, | |||
uint8_t *out_tag, size_t *out_tag_len, | |||
const size_t max_out_tag_len, | |||
const uint8_t *nonce, const size_t nonce_len, | |||
const uint8_t *in, const size_t in_len, | |||
const uint8_t *extra_in, | |||
const size_t extra_in_len, const uint8_t *ad, | |||
const 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, CIPHER_R_INVALID_OPERATION); | |||
return 0; | |||
} | |||
if (in_len > INT_MAX) { | |||
// EVP_CIPHER takes int as input. | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); | |||
return 0; | |||
} | |||
if (max_out_tag_len < aead_ssl3_tag_len(ctx, in_len, extra_in_len)) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); | |||
return 0; | |||
} | |||
if (nonce_len != 0) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_IV_TOO_LARGE); | |||
return 0; | |||
} | |||
if (ad_len != 11 - 2 /* length bytes */) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); | |||
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]; | |||
unsigned mac_len; | |||
if (!ssl3_mac(ssl3_ctx, mac, &mac_len, ad, ad_len, in, in_len)) { | |||
return 0; | |||
} | |||
// Encrypt the input. | |||
int len; | |||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, | |||
(int)in_len)) { | |||
return 0; | |||
} | |||
const size_t block_size = EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx); | |||
// Feed the MAC into the cipher in two steps. First complete the final partial | |||
// block from encrypting the input and split the result between |out| and | |||
// |out_tag|. Then encrypt the remainder. | |||
size_t early_mac_len = (block_size - (in_len % block_size)) % block_size; | |||
if (early_mac_len != 0) { | |||
assert(len + block_size - early_mac_len == in_len); | |||
uint8_t buf[EVP_MAX_BLOCK_LENGTH]; | |||
int buf_len; | |||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, buf, &buf_len, mac, | |||
(int)early_mac_len)) { | |||
return 0; | |||
} | |||
assert(buf_len == (int)block_size); | |||
OPENSSL_memcpy(out + len, buf, block_size - early_mac_len); | |||
OPENSSL_memcpy(out_tag, buf + block_size - early_mac_len, early_mac_len); | |||
} | |||
size_t tag_len = early_mac_len; | |||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out_tag + tag_len, &len, | |||
mac + tag_len, mac_len - tag_len)) { | |||
return 0; | |||
} | |||
tag_len += len; | |||
if (block_size > 1) { | |||
assert(block_size <= 256); | |||
assert(EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE); | |||
// Compute padding and feed that into the cipher. | |||
uint8_t padding[256]; | |||
size_t padding_len = block_size - ((in_len + mac_len) % block_size); | |||
OPENSSL_memset(padding, 0, padding_len - 1); | |||
padding[padding_len - 1] = padding_len - 1; | |||
if (!EVP_EncryptUpdate(&ssl3_ctx->cipher_ctx, out_tag + tag_len, &len, padding, | |||
(int)padding_len)) { | |||
return 0; | |||
} | |||
tag_len += len; | |||
} | |||
if (!EVP_EncryptFinal_ex(&ssl3_ctx->cipher_ctx, out_tag + tag_len, &len)) { | |||
return 0; | |||
} | |||
tag_len += len; | |||
assert(tag_len == aead_ssl3_tag_len(ctx, in_len, extra_in_len)); | |||
*out_tag_len = tag_len; | |||
return 1; | |||
} | |||
static int aead_ssl3_open(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, | |||
const uint8_t *in, size_t in_len, | |||
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, 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, CIPHER_R_BAD_DECRYPT); | |||
return 0; | |||
} | |||
if (max_out_len < in_len) { | |||
// This requires that the caller provide space for the MAC, even though it | |||
// will always be removed on return. | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); | |||
return 0; | |||
} | |||
if (nonce_len != 0) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); | |||
return 0; | |||
} | |||
if (ad_len != 11 - 2 /* length bytes */) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_AD_SIZE); | |||
return 0; | |||
} | |||
if (in_len > INT_MAX) { | |||
// EVP_CIPHER takes int as input. | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_TOO_LARGE); | |||
return 0; | |||
} | |||
// Decrypt to get the plaintext + MAC + padding. | |||
size_t total = 0; | |||
int len; | |||
if (!EVP_DecryptUpdate(&ssl3_ctx->cipher_ctx, out, &len, in, (int)in_len)) { | |||
return 0; | |||
} | |||
total += len; | |||
if (!EVP_DecryptFinal_ex(&ssl3_ctx->cipher_ctx, out + total, &len)) { | |||
return 0; | |||
} | |||
total += len; | |||
assert(total == in_len); | |||
// Remove CBC padding and MAC. This would normally be timing-sensitive, but | |||
// SSLv3 CBC ciphers are already broken. Support will be removed eventually. | |||
// https://www.openssl.org/~bodo/ssl-poodle.pdf | |||
size_t data_len; | |||
if (EVP_CIPHER_CTX_mode(&ssl3_ctx->cipher_ctx) == EVP_CIPH_CBC_MODE) { | |||
unsigned padding_length = out[total - 1]; | |||
if (total < padding_length + 1 + mac_len) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); | |||
return 0; | |||
} | |||
// The padding must be minimal. | |||
if (padding_length + 1 > EVP_CIPHER_CTX_block_size(&ssl3_ctx->cipher_ctx)) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); | |||
return 0; | |||
} | |||
data_len = total - padding_length - 1 - mac_len; | |||
} else { | |||
data_len = total - mac_len; | |||
} | |||
// Compute the MAC and compare against the one in the record. | |||
uint8_t mac[EVP_MAX_MD_SIZE]; | |||
if (!ssl3_mac(ssl3_ctx, mac, NULL, ad, ad_len, out, data_len)) { | |||
return 0; | |||
} | |||
if (CRYPTO_memcmp(&out[data_len], mac, mac_len) != 0) { | |||
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BAD_DECRYPT); | |||
return 0; | |||
} | |||
*out_len = data_len; | |||
return 1; | |||
} | |||
static int aead_ssl3_get_iv(const EVP_AEAD_CTX *ctx, const uint8_t **out_iv, | |||
size_t *out_iv_len) { | |||
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state; | |||
const size_t iv_len = EVP_CIPHER_CTX_iv_length(&ssl3_ctx->cipher_ctx); | |||
if (iv_len <= 1) { | |||
return 0; | |||
} | |||
*out_iv = ssl3_ctx->cipher_ctx.iv; | |||
*out_iv_len = iv_len; | |||
return 1; | |||
} | |||
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, | |||
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, | |||
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, | |||
enum evp_aead_direction_t dir) { | |||
return aead_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_des_ede3_cbc(), | |||
EVP_sha1()); | |||
} | |||
static int aead_null_sha1_ssl3_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_ssl3_init(ctx, key, key_len, tag_len, dir, EVP_enc_null(), | |||
EVP_sha1()); | |||
} | |||
static const EVP_AEAD aead_aes_128_cbc_sha1_ssl3 = { | |||
SHA_DIGEST_LENGTH + 16 + 16, // key len (SHA1 + AES128 + IV) | |||
0, // nonce len | |||
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1) | |||
SHA_DIGEST_LENGTH, // max tag length | |||
0, // seal_scatter_supports_extra_in | |||
NULL, // init | |||
aead_aes_128_cbc_sha1_ssl3_init, | |||
aead_ssl3_cleanup, | |||
aead_ssl3_open, | |||
aead_ssl3_seal_scatter, | |||
NULL, // open_gather | |||
aead_ssl3_get_iv, | |||
aead_ssl3_tag_len, | |||
}; | |||
static const EVP_AEAD aead_aes_256_cbc_sha1_ssl3 = { | |||
SHA_DIGEST_LENGTH + 32 + 16, // key len (SHA1 + AES256 + IV) | |||
0, // nonce len | |||
16 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1) | |||
SHA_DIGEST_LENGTH, // max tag length | |||
0, // seal_scatter_supports_extra_in | |||
NULL, // init | |||
aead_aes_256_cbc_sha1_ssl3_init, | |||
aead_ssl3_cleanup, | |||
aead_ssl3_open, | |||
aead_ssl3_seal_scatter, | |||
NULL, // open_gather | |||
aead_ssl3_get_iv, | |||
aead_ssl3_tag_len, | |||
}; | |||
static const EVP_AEAD aead_des_ede3_cbc_sha1_ssl3 = { | |||
SHA_DIGEST_LENGTH + 24 + 8, // key len (SHA1 + 3DES + IV) | |||
0, // nonce len | |||
8 + SHA_DIGEST_LENGTH, // overhead (padding + SHA1) | |||
SHA_DIGEST_LENGTH, // max tag length | |||
0, // seal_scatter_supports_extra_in | |||
NULL, // init | |||
aead_des_ede3_cbc_sha1_ssl3_init, | |||
aead_ssl3_cleanup, | |||
aead_ssl3_open, | |||
aead_ssl3_seal_scatter, | |||
NULL, // open_gather | |||
aead_ssl3_get_iv, | |||
aead_ssl3_tag_len, | |||
}; | |||
static const EVP_AEAD aead_null_sha1_ssl3 = { | |||
SHA_DIGEST_LENGTH, // key len | |||
0, // nonce len | |||
SHA_DIGEST_LENGTH, // overhead (SHA1) | |||
SHA_DIGEST_LENGTH, // max tag length | |||
0, // seal_scatter_supports_extra_in | |||
NULL, // init | |||
aead_null_sha1_ssl3_init, | |||
aead_ssl3_cleanup, | |||
aead_ssl3_open, | |||
aead_ssl3_seal_scatter, | |||
NULL, // open_gather | |||
NULL, // get_iv | |||
aead_ssl3_tag_len, | |||
}; | |||
const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void) { | |||
return &aead_aes_128_cbc_sha1_ssl3; | |||
} | |||
const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void) { | |||
return &aead_aes_256_cbc_sha1_ssl3; | |||
} | |||
const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void) { | |||
return &aead_des_ede3_cbc_sha1_ssl3; | |||
} | |||
const EVP_AEAD *EVP_aead_null_sha1_ssl3(void) { return &aead_null_sha1_ssl3; } |
@@ -13,7 +13,3 @@ go run make_legacy_aead_tests.go -cipher aes256 -mac sha384 > aes_256_cbc_sha384 | |||
go run make_legacy_aead_tests.go -cipher 3des -mac sha1 > des_ede3_cbc_sha1_tls_tests.txt | |||
go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -implicit-iv > des_ede3_cbc_sha1_tls_implicit_iv_tests.txt | |||
go run make_legacy_aead_tests.go -cipher aes128 -mac sha1 -ssl3 > aes_128_cbc_sha1_ssl3_tests.txt | |||
go run make_legacy_aead_tests.go -cipher aes256 -mac sha1 -ssl3 > aes_256_cbc_sha1_ssl3_tests.txt | |||
go run make_legacy_aead_tests.go -cipher 3des -mac sha1 -ssl3 > des_ede3_cbc_sha1_ssl3_tests.txt |
@@ -20,7 +20,6 @@ import ( | |||
var bulkCipher *string = flag.String("cipher", "", "The bulk cipher to use") | |||
var mac *string = flag.String("mac", "", "The hash function to use in the MAC") | |||
var implicitIV *bool = flag.Bool("implicit-iv", false, "If true, generate tests for a cipher using a pre-TLS-1.0 implicit IV") | |||
var ssl3 *bool = flag.Bool("ssl3", false, "If true, use the SSLv3 MAC and padding rather than TLS") | |||
// rc4Stream produces a deterministic stream of pseudorandom bytes. This is to | |||
// make this script idempotent. | |||
@@ -84,30 +83,6 @@ func newBlockCipher(name string, key []byte) (cipher.Block, error) { | |||
} | |||
} | |||
var ssl30Pad1 = [48]byte{0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36} | |||
var ssl30Pad2 = [48]byte{0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c} | |||
func ssl30MAC(hash crypto.Hash, key, input, ad []byte) []byte { | |||
padLength := 48 | |||
if hash.Size() == 20 { | |||
padLength = 40 | |||
} | |||
h := hash.New() | |||
h.Write(key) | |||
h.Write(ssl30Pad1[:padLength]) | |||
h.Write(ad) | |||
h.Write(input) | |||
digestBuf := h.Sum(nil) | |||
h.Reset() | |||
h.Write(key) | |||
h.Write(ssl30Pad2[:padLength]) | |||
h.Write(digestBuf) | |||
return h.Sum(digestBuf[:0]) | |||
} | |||
type testCase struct { | |||
digest []byte | |||
key []byte | |||
@@ -148,12 +123,7 @@ func makeTestCase(length int, options options) (*testCase, error) { | |||
input := make([]byte, length) | |||
rand.fillBytes(input) | |||
var adFull []byte | |||
if *ssl3 { | |||
adFull = make([]byte, 11) | |||
} else { | |||
adFull = make([]byte, 13) | |||
} | |||
adFull := make([]byte, 13) | |||
ad := adFull[:len(adFull)-2] | |||
rand.fillBytes(ad) | |||
adFull[len(adFull)-2] = uint8(length >> 8) | |||
@@ -167,18 +137,10 @@ func makeTestCase(length int, options options) (*testCase, error) { | |||
macKey := make([]byte, hash.Size()) | |||
rand.fillBytes(macKey) | |||
var digest []byte | |||
if *ssl3 { | |||
if hash != crypto.SHA1 && hash != crypto.MD5 { | |||
return nil, fmt.Errorf("invalid hash for SSLv3: '%s'", *mac) | |||
} | |||
digest = ssl30MAC(hash, macKey, input, adFull) | |||
} else { | |||
h := hmac.New(hash.New, macKey) | |||
h.Write(adFull) | |||
h.Write(input) | |||
digest = h.Sum(nil) | |||
} | |||
h := hmac.New(hash.New, macKey) | |||
h.Write(adFull) | |||
h.Write(input) | |||
digest := h.Sum(nil) | |||
size := getKeySize(*bulkCipher) | |||
if size == 0 { | |||
@@ -198,7 +160,7 @@ func makeTestCase(length int, options options) (*testCase, error) { | |||
iv := make([]byte, block.BlockSize()) | |||
rand.fillBytes(iv) | |||
if *implicitIV || *ssl3 { | |||
if *implicitIV { | |||
fixedIV = iv | |||
} else { | |||
nonce = iv | |||
@@ -232,31 +194,20 @@ func makeTestCase(length int, options options) (*testCase, error) { | |||
paddingLen = 256 | |||
} | |||
noSeal = true | |||
if *ssl3 { | |||
// SSLv3 padding must be minimal. | |||
fails = true | |||
} | |||
} | |||
if *ssl3 { | |||
sealed = append(sealed, make([]byte, paddingLen-1)...) | |||
sealed = append(sealed, byte(paddingLen-1)) | |||
} else { | |||
pad := make([]byte, paddingLen) | |||
for i := range pad { | |||
pad[i] = byte(paddingLen - 1) | |||
} | |||
sealed = append(sealed, pad...) | |||
pad := make([]byte, paddingLen) | |||
for i := range pad { | |||
pad[i] = byte(paddingLen - 1) | |||
} | |||
sealed = append(sealed, pad...) | |||
if options.wrongPadding { | |||
if options.wrongPaddingOffset >= paddingLen { | |||
return nil, fmt.Errorf("invalid wrongPaddingOffset") | |||
} | |||
sealed[len(sealed)-paddingLen+options.wrongPaddingOffset]++ | |||
noSeal = true | |||
if !*ssl3 { | |||
// TLS specifies the all the padding bytes. | |||
fails = true | |||
} | |||
// TLS specifies the all the padding bytes. | |||
fails = true | |||
} | |||
} | |||
cbc.CryptBlocks(sealed, sealed) | |||
@@ -314,9 +265,6 @@ func main() { | |||
if *implicitIV { | |||
commandLine += " -implicit-iv" | |||
} | |||
if *ssl3 { | |||
commandLine += " -ssl3" | |||
} | |||
fmt.Printf("# Generated by\n") | |||
fmt.Printf("# %s\n", commandLine) | |||
fmt.Printf("#\n") | |||
@@ -382,20 +382,6 @@ OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_gcm_tls13(void); | |||
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_gcm_tls13(void); | |||
// SSLv3-specific AEAD algorithms. | |||
// | |||
// These AEAD primitives do not meet the definition of generic AEADs. They are | |||
// all specific to SSLv3 and should not be used outside of that context. They | |||
// must be initialized with |EVP_AEAD_CTX_init_with_direction|, are stateful, | |||
// and may not be used concurrently. They only accept an |ad| parameter of | |||
// length 9 (the standard TLS one with length and version omitted). | |||
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_128_cbc_sha1_ssl3(void); | |||
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_aes_256_cbc_sha1_ssl3(void); | |||
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_des_ede3_cbc_sha1_ssl3(void); | |||
OPENSSL_EXPORT const EVP_AEAD *EVP_aead_null_sha1_ssl3(void); | |||
// Obscure functions. | |||
// evp_aead_direction_t denotes the direction of an AEAD operation. | |||
@@ -649,7 +649,6 @@ OPENSSL_EXPORT int SSL_version(const SSL *ssl); | |||
// The following flags toggle individual protocol versions. This is deprecated. | |||
// Use |SSL_CTX_set_min_proto_version| and |SSL_CTX_set_max_proto_version| | |||
// instead. | |||
#define SSL_OP_NO_SSLv3 0x02000000L | |||
#define SSL_OP_NO_TLSv1 0x04000000L | |||
#define SSL_OP_NO_TLSv1_2 0x08000000L | |||
#define SSL_OP_NO_TLSv1_1 0x10000000L | |||
@@ -4000,6 +3999,7 @@ DEFINE_STACK_OF(SSL_COMP) | |||
#define SSL_OP_NO_COMPRESSION 0 | |||
#define SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION 0 | |||
#define SSL_OP_NO_SSLv2 0 | |||
#define SSL_OP_NO_SSLv3 0 | |||
#define SSL_OP_PKCS1_CHECK_1 0 | |||
#define SSL_OP_PKCS1_CHECK_2 0 | |||
#define SSL_OP_SINGLE_DH_USE 0 | |||
@@ -6,7 +6,6 @@ | |||
set( | |||
CRYPTO_TEST_DATA | |||
crypto/cipher_extra/test/aes_128_cbc_sha1_ssl3_tests.txt | |||
crypto/cipher_extra/test/aes_128_cbc_sha1_tls_implicit_iv_tests.txt | |||
crypto/cipher_extra/test/aes_128_cbc_sha1_tls_tests.txt | |||
crypto/cipher_extra/test/aes_128_cbc_sha256_tls_tests.txt | |||
@@ -15,7 +14,6 @@ set( | |||
crypto/cipher_extra/test/aes_128_ctr_hmac_sha256.txt | |||
crypto/cipher_extra/test/aes_128_gcm_siv_tests.txt | |||
crypto/cipher_extra/test/aes_128_gcm_tests.txt | |||
crypto/cipher_extra/test/aes_256_cbc_sha1_ssl3_tests.txt | |||
crypto/cipher_extra/test/aes_256_cbc_sha1_tls_implicit_iv_tests.txt | |||
crypto/cipher_extra/test/aes_256_cbc_sha1_tls_tests.txt | |||
crypto/cipher_extra/test/aes_256_cbc_sha256_tls_tests.txt | |||
@@ -25,7 +23,6 @@ set( | |||
crypto/cipher_extra/test/aes_256_gcm_tests.txt | |||
crypto/cipher_extra/test/chacha20_poly1305_tests.txt | |||
crypto/cipher_extra/test/cipher_tests.txt | |||
crypto/cipher_extra/test/des_ede3_cbc_sha1_ssl3_tests.txt | |||
crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_implicit_iv_tests.txt | |||
crypto/cipher_extra/test/des_ede3_cbc_sha1_tls_tests.txt | |||
crypto/cipher_extra/test/nist_cavp/aes_128_cbc.txt | |||
@@ -100,7 +100,7 @@ bool SSL_apply_handoff(SSL *ssl, Span<const uint8_t> handoff) { | |||
} | |||
bool SSL_serialize_handback(const SSL *ssl, CBB *out) { | |||
if (!ssl->server || ssl->method->is_dtls || ssl->version < TLS1_VERSION) { | |||
if (!ssl->server || ssl->method->is_dtls) { | |||
return false; | |||
} | |||
handback_t type; | |||
@@ -433,20 +433,18 @@ enum ssl_hs_wait_t ssl_get_finished(SSL_HANDSHAKE *hs) { | |||
} | |||
// Copy the Finished so we can use it for renegotiation checks. | |||
if (ssl->version != SSL3_VERSION) { | |||
if (finished_len > sizeof(ssl->s3->previous_client_finished) || | |||
finished_len > sizeof(ssl->s3->previous_server_finished)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return ssl_hs_error; | |||
} | |||
if (finished_len > sizeof(ssl->s3->previous_client_finished) || | |||
finished_len > sizeof(ssl->s3->previous_server_finished)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return ssl_hs_error; | |||
} | |||
if (ssl->server) { | |||
OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len); | |||
ssl->s3->previous_client_finished_len = finished_len; | |||
} else { | |||
OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len); | |||
ssl->s3->previous_server_finished_len = finished_len; | |||
} | |||
if (ssl->server) { | |||
OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len); | |||
ssl->s3->previous_client_finished_len = finished_len; | |||
} else { | |||
OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len); | |||
ssl->s3->previous_server_finished_len = finished_len; | |||
} | |||
ssl->method->next_message(ssl); | |||
@@ -472,20 +470,18 @@ bool ssl_send_finished(SSL_HANDSHAKE *hs) { | |||
} | |||
// Copy the Finished so we can use it for renegotiation checks. | |||
if (ssl->version != SSL3_VERSION) { | |||
if (finished_len > sizeof(ssl->s3->previous_client_finished) || | |||
finished_len > sizeof(ssl->s3->previous_server_finished)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return 0; | |||
} | |||
if (finished_len > sizeof(ssl->s3->previous_client_finished) || | |||
finished_len > sizeof(ssl->s3->previous_server_finished)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return 0; | |||
} | |||
if (ssl->server) { | |||
OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len); | |||
ssl->s3->previous_server_finished_len = finished_len; | |||
} else { | |||
OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len); | |||
ssl->s3->previous_client_finished_len = finished_len; | |||
} | |||
if (ssl->server) { | |||
OPENSSL_memcpy(ssl->s3->previous_server_finished, finished, finished_len); | |||
ssl->s3->previous_server_finished_len = finished_len; | |||
} else { | |||
OPENSSL_memcpy(ssl->s3->previous_client_finished, finished, finished_len); | |||
ssl->s3->previous_client_finished_len = finished_len; | |||
} | |||
ScopedCBB cbb; | |||
@@ -269,15 +269,6 @@ static int ssl_write_client_cipher_list(SSL_HANDSHAKE *hs, CBB *out) { | |||
} | |||
} | |||
// For SSLv3, the SCSV is added. Otherwise the renegotiation extension is | |||
// added. | |||
if (hs->max_version == SSL3_VERSION && | |||
!ssl->s3->initial_handshake_complete) { | |||
if (!CBB_add_u16(&child, SSL3_CK_SCSV & 0xffff)) { | |||
return 0; | |||
} | |||
} | |||
if (ssl->mode & SSL_MODE_SEND_FALLBACK_SCSV) { | |||
if (!CBB_add_u16(&child, SSL3_CK_FALLBACK_SCSV & 0xffff)) { | |||
return 0; | |||
@@ -394,12 +385,6 @@ static enum ssl_hs_wait_t do_start_connect(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_error; | |||
} | |||
// SSL 3.0 ClientHellos should use SSL 3.0 not TLS 1.0, for the record-layer | |||
// version. | |||
if (hs->max_version == SSL3_VERSION) { | |||
ssl->s3->aead_write_ctx->SetVersionIfNullCipher(SSL3_VERSION); | |||
} | |||
// Always advertise the ClientHello version from the original maximum version, | |||
// even on renegotiation. The static RSA key exchange uses this field, and | |||
// some servers fail when it changes across handshakes. | |||
@@ -1192,16 +1177,6 @@ static enum ssl_hs_wait_t do_send_client_certificate(SSL_HANDSHAKE *hs) { | |||
if (!ssl_has_certificate(hs->config)) { | |||
// Without a client certificate, the handshake buffer may be released. | |||
hs->transcript.FreeBuffer(); | |||
// In SSL 3.0, the Certificate message is replaced with a warning alert. | |||
if (ssl->version == SSL3_VERSION) { | |||
if (!ssl->method->add_alert(ssl, SSL3_AL_WARNING, | |||
SSL_AD_NO_CERTIFICATE)) { | |||
return ssl_hs_error; | |||
} | |||
hs->state = state_send_client_key_exchange; | |||
return ssl_hs_ok; | |||
} | |||
} | |||
if (!ssl_on_certificate_selected(hs) || | |||
@@ -1286,21 +1261,14 @@ static enum ssl_hs_wait_t do_send_client_key_exchange(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_error; | |||
} | |||
CBB child, *enc_pms = &body; | |||
size_t enc_pms_len; | |||
// In TLS, there is a length prefix. | |||
if (ssl->version > SSL3_VERSION) { | |||
if (!CBB_add_u16_length_prefixed(&body, &child)) { | |||
return ssl_hs_error; | |||
} | |||
enc_pms = &child; | |||
} | |||
CBB enc_pms; | |||
uint8_t *ptr; | |||
if (!CBB_reserve(enc_pms, &ptr, RSA_size(rsa)) || | |||
size_t enc_pms_len; | |||
if (!CBB_add_u16_length_prefixed(&body, &enc_pms) || | |||
!CBB_reserve(&enc_pms, &ptr, RSA_size(rsa)) || | |||
!RSA_encrypt(rsa, &enc_pms_len, ptr, RSA_size(rsa), pms.data(), | |||
pms.size(), RSA_PKCS1_PADDING) || | |||
!CBB_did_write(enc_pms, enc_pms_len) || | |||
!CBB_did_write(&enc_pms, enc_pms_len) || | |||
!CBB_flush(&body)) { | |||
return ssl_hs_error; | |||
} | |||
@@ -1407,40 +1375,16 @@ static enum ssl_hs_wait_t do_send_client_certificate_verify(SSL_HANDSHAKE *hs) { | |||
} | |||
size_t sig_len = max_sig_len; | |||
// The SSL3 construction for CertificateVerify does not decompose into a | |||
// single final digest and signature, and must be special-cased. | |||
if (ssl_protocol_version(ssl) == SSL3_VERSION) { | |||
if (hs->config->cert->key_method != NULL) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNSUPPORTED_PROTOCOL_FOR_CUSTOM_KEY); | |||
return ssl_hs_error; | |||
} | |||
uint8_t digest[EVP_MAX_MD_SIZE]; | |||
size_t digest_len; | |||
if (!hs->transcript.GetSSL3CertVerifyHash( | |||
digest, &digest_len, hs->new_session.get(), signature_algorithm)) { | |||
return ssl_hs_error; | |||
} | |||
UniquePtr<EVP_PKEY_CTX> pctx( | |||
EVP_PKEY_CTX_new(hs->config->cert->privatekey.get(), nullptr)); | |||
if (!pctx || | |||
!EVP_PKEY_sign_init(pctx.get()) || | |||
!EVP_PKEY_sign(pctx.get(), ptr, &sig_len, digest, digest_len)) { | |||
switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len, | |||
signature_algorithm, | |||
hs->transcript.buffer())) { | |||
case ssl_private_key_success: | |||
break; | |||
case ssl_private_key_failure: | |||
return ssl_hs_error; | |||
} | |||
} else { | |||
switch (ssl_private_key_sign(hs, ptr, &sig_len, max_sig_len, | |||
signature_algorithm, | |||
hs->transcript.buffer())) { | |||
case ssl_private_key_success: | |||
break; | |||
case ssl_private_key_failure: | |||
return ssl_hs_error; | |||
case ssl_private_key_retry: | |||
hs->state = state_send_client_certificate_verify; | |||
return ssl_hs_private_key_operation; | |||
} | |||
case ssl_private_key_retry: | |||
hs->state = state_send_client_certificate_verify; | |||
return ssl_hs_private_key_operation; | |||
} | |||
if (!CBB_did_write(&child, sig_len) || | |||
@@ -213,7 +213,6 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert, | |||
0x03, 0x03, // TLS 1.2 | |||
0x03, 0x02, // TLS 1.1 | |||
0x03, 0x01, // TLS 1 | |||
0x03, 0x00, // SSL 3 | |||
}; | |||
static const uint8_t kDTLSVersions[] = { | |||
@@ -232,12 +231,10 @@ static int negotiate_version(SSL_HANDSHAKE *hs, uint8_t *out_alert, | |||
versions_len); | |||
} else { | |||
if (client_hello->version >= TLS1_2_VERSION) { | |||
versions_len = 8; | |||
} else if (client_hello->version >= TLS1_1_VERSION) { | |||
versions_len = 6; | |||
} else if (client_hello->version >= TLS1_VERSION) { | |||
} else if (client_hello->version >= TLS1_1_VERSION) { | |||
versions_len = 4; | |||
} else if (client_hello->version >= SSL3_VERSION) { | |||
} else if (client_hello->version >= TLS1_VERSION) { | |||
versions_len = 2; | |||
} | |||
CBS_init(&versions, kTLSVersions + sizeof(kTLSVersions) - versions_len, | |||
@@ -917,8 +914,7 @@ static enum ssl_hs_wait_t do_send_server_hello_done(SSL_HANDSHAKE *hs) { | |||
SSL3_MT_CERTIFICATE_REQUEST) || | |||
!CBB_add_u8_length_prefixed(&body, &cert_types) || | |||
!CBB_add_u8(&cert_types, SSL3_CT_RSA_SIGN) || | |||
(ssl_protocol_version(ssl) >= TLS1_VERSION && | |||
!CBB_add_u8(&cert_types, TLS_CT_ECDSA_SIGN)) || | |||
!CBB_add_u8(&cert_types, TLS_CT_ECDSA_SIGN) || | |||
// TLS 1.2 has no way to specify different signature algorithms for | |||
// certificates and the online signature, so emit the more restrictive | |||
// certificate list. | |||
@@ -959,26 +955,7 @@ static enum ssl_hs_wait_t do_read_client_certificate(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_read_message; | |||
} | |||
if (msg.type != SSL3_MT_CERTIFICATE) { | |||
if (ssl->version == SSL3_VERSION && | |||
msg.type == SSL3_MT_CLIENT_KEY_EXCHANGE) { | |||
// In SSL 3.0, the Certificate message is omitted to signal no | |||
// certificate. | |||
if (hs->config->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); | |||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); | |||
return ssl_hs_error; | |||
} | |||
// OpenSSL returns X509_V_OK when no certificates are received. This is | |||
// classed by them as a bug, but it's assumed by at least NGINX. | |||
hs->new_session->verify_result = X509_V_OK; | |||
hs->state = state12_verify_client_certificate; | |||
return ssl_hs_ok; | |||
} | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_UNEXPECTED_MESSAGE); | |||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_UNEXPECTED_MESSAGE); | |||
if (!ssl_check_message_type(ssl, msg, SSL3_MT_CERTIFICATE)) { | |||
return ssl_hs_error; | |||
} | |||
@@ -1011,14 +988,6 @@ static enum ssl_hs_wait_t do_read_client_certificate(SSL_HANDSHAKE *hs) { | |||
// No client certificate so the handshake buffer may be discarded. | |||
hs->transcript.FreeBuffer(); | |||
// In SSL 3.0, sending no certificate is signaled by omitting the | |||
// Certificate message. | |||
if (ssl->version == SSL3_VERSION) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_NO_CERTIFICATES_RETURNED); | |||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_HANDSHAKE_FAILURE); | |||
return ssl_hs_error; | |||
} | |||
if (hs->config->verify_mode & SSL_VERIFY_FAIL_IF_NO_PEER_CERT) { | |||
// Fail for TLS only if we required a certificate | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_PEER_DID_NOT_RETURN_A_CERTIFICATE); | |||
@@ -1101,16 +1070,12 @@ static enum ssl_hs_wait_t do_read_client_key_exchange(SSL_HANDSHAKE *hs) { | |||
Array<uint8_t> premaster_secret; | |||
if (alg_k & SSL_kRSA) { | |||
CBS encrypted_premaster_secret; | |||
if (ssl->version > SSL3_VERSION) { | |||
if (!CBS_get_u16_length_prefixed(&client_key_exchange, | |||
&encrypted_premaster_secret) || | |||
CBS_len(&client_key_exchange) != 0) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||
return ssl_hs_error; | |||
} | |||
} else { | |||
encrypted_premaster_secret = client_key_exchange; | |||
if (!CBS_get_u16_length_prefixed(&client_key_exchange, | |||
&encrypted_premaster_secret) || | |||
CBS_len(&client_key_exchange) != 0) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR); | |||
ssl_send_alert(ssl, SSL3_AL_FATAL, SSL_AD_DECODE_ERROR); | |||
return ssl_hs_error; | |||
} | |||
// Allocate a buffer large enough for an RSA decryption. | |||
@@ -1317,29 +1282,9 @@ static enum ssl_hs_wait_t do_read_client_certificate_verify(SSL_HANDSHAKE *hs) { | |||
return ssl_hs_error; | |||
} | |||
bool sig_ok; | |||
// The SSL3 construction for CertificateVerify does not decompose into a | |||
// single final digest and signature, and must be special-cased. | |||
if (ssl_protocol_version(ssl) == SSL3_VERSION) { | |||
uint8_t digest[EVP_MAX_MD_SIZE]; | |||
size_t digest_len; | |||
if (!hs->transcript.GetSSL3CertVerifyHash( | |||
digest, &digest_len, hs->new_session.get(), signature_algorithm)) { | |||
return ssl_hs_error; | |||
} | |||
UniquePtr<EVP_PKEY_CTX> pctx( | |||
EVP_PKEY_CTX_new(hs->peer_pubkey.get(), nullptr)); | |||
sig_ok = pctx && | |||
EVP_PKEY_verify_init(pctx.get()) && | |||
EVP_PKEY_verify(pctx.get(), CBS_data(&signature), | |||
CBS_len(&signature), digest, digest_len); | |||
} else { | |||
sig_ok = | |||
ssl_public_key_verify(ssl, signature, signature_algorithm, | |||
hs->peer_pubkey.get(), hs->transcript.buffer()); | |||
} | |||
bool sig_ok = | |||
ssl_public_key_verify(ssl, signature, signature_algorithm, | |||
hs->peer_pubkey.get(), hs->transcript.buffer()); | |||
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE) | |||
sig_ok = true; | |||
ERR_clear_error(); | |||
@@ -609,14 +609,6 @@ class SSLTranscript { | |||
// the number of bytes written. Otherwise, it returns false. | |||
bool GetHash(uint8_t *out, size_t *out_len); | |||
// GetSSL3CertVerifyHash writes the SSL 3.0 CertificateVerify hash into the | |||
// bytes pointed to by |out| and writes the number of bytes to | |||
// |*out_len|. |out| must have room for |EVP_MAX_MD_SIZE| bytes. It returns | |||
// one on success and zero on failure. | |||
bool GetSSL3CertVerifyHash(uint8_t *out, size_t *out_len, | |||
const SSL_SESSION *session, | |||
uint16_t signature_algorithm); | |||
// GetFinishedMAC computes the MAC for the Finished message into the bytes | |||
// pointed by |out| and writes the number of bytes to |*out_len|. |out| must | |||
// have room for |EVP_MAX_MD_SIZE| bytes. It returns true on success and false | |||
@@ -778,9 +770,6 @@ class SSLAEADContext { | |||
// omit_length_in_ad_ is true if the length should be omitted in the | |||
// AEAD's ad parameter. | |||
bool omit_length_in_ad_ : 1; | |||
// omit_version_in_ad_ is true if the version should be omitted | |||
// in the AEAD's ad parameter. | |||
bool omit_version_in_ad_ : 1; | |||
// omit_ad_ is true if the AEAD's ad parameter should be omitted. | |||
bool omit_ad_ : 1; | |||
// ad_is_header_ is true if the AEAD's ad parameter is the record header. | |||
@@ -397,7 +397,7 @@ static ssl_open_record_t read_v2_client_hello(SSL *ssl, size_t *out_consumed, | |||
OPENSSL_memcpy(random + (SSL3_RANDOM_SIZE - rand_len), CBS_data(&challenge), | |||
rand_len); | |||
// Write out an equivalent SSLv3 ClientHello. | |||
// Write out an equivalent TLS ClientHello. | |||
size_t max_v3_client_hello = SSL3_HM_HEADER_LENGTH + 2 /* version */ + | |||
SSL3_RANDOM_SIZE + 1 /* session ID length */ + | |||
2 /* cipher list length */ + | |||
@@ -42,7 +42,6 @@ SSLAEADContext::SSLAEADContext(uint16_t version_arg, bool is_dtls_arg, | |||
random_variable_nonce_(false), | |||
xor_fixed_nonce_(false), | |||
omit_length_in_ad_(false), | |||
omit_version_in_ad_(false), | |||
omit_ad_(false), | |||
ad_is_header_(false) { | |||
OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_)); | |||
@@ -147,7 +146,6 @@ UniquePtr<SSLAEADContext> SSLAEADContext::Create( | |||
aead_ctx->variable_nonce_included_in_record_ = true; | |||
aead_ctx->random_variable_nonce_ = true; | |||
aead_ctx->omit_length_in_ad_ = true; | |||
aead_ctx->omit_version_in_ad_ = (protocol_version == SSL3_VERSION); | |||
} | |||
return aead_ctx; | |||
@@ -235,10 +233,8 @@ Span<const uint8_t> SSLAEADContext::GetAdditionalData( | |||
OPENSSL_memcpy(storage, seqnum, 8); | |||
size_t len = 8; | |||
storage[len++] = type; | |||
if (!omit_version_in_ad_) { | |||
storage[len++] = static_cast<uint8_t>((record_version >> 8)); | |||
storage[len++] = static_cast<uint8_t>(record_version); | |||
} | |||
storage[len++] = static_cast<uint8_t>((record_version >> 8)); | |||
storage[len++] = static_cast<uint8_t>(record_version); | |||
if (!omit_length_in_ad_) { | |||
storage[len++] = static_cast<uint8_t>((plaintext_len >> 8)); | |||
storage[len++] = static_cast<uint8_t>(plaintext_len); | |||
@@ -613,36 +613,23 @@ bool ssl_cipher_get_evp_aead(const EVP_AEAD **out_aead, | |||
} | |||
} else if (cipher->algorithm_mac == SSL_SHA1) { | |||
if (cipher->algorithm_enc == SSL_eNULL) { | |||
if (version == SSL3_VERSION) { | |||
*out_aead = EVP_aead_null_sha1_ssl3(); | |||
} else { | |||
*out_aead = EVP_aead_null_sha1_tls(); | |||
} | |||
*out_aead = EVP_aead_null_sha1_tls(); | |||
} else if (cipher->algorithm_enc == SSL_3DES) { | |||
if (version == SSL3_VERSION) { | |||
*out_aead = EVP_aead_des_ede3_cbc_sha1_ssl3(); | |||
*out_fixed_iv_len = 8; | |||
} else if (version == TLS1_VERSION) { | |||
if (version == TLS1_VERSION) { | |||
*out_aead = EVP_aead_des_ede3_cbc_sha1_tls_implicit_iv(); | |||
*out_fixed_iv_len = 8; | |||
} else { | |||
*out_aead = EVP_aead_des_ede3_cbc_sha1_tls(); | |||
} | |||
} else if (cipher->algorithm_enc == SSL_AES128) { | |||
if (version == SSL3_VERSION) { | |||
*out_aead = EVP_aead_aes_128_cbc_sha1_ssl3(); | |||
*out_fixed_iv_len = 16; | |||
} else if (version == TLS1_VERSION) { | |||
if (version == TLS1_VERSION) { | |||
*out_aead = EVP_aead_aes_128_cbc_sha1_tls_implicit_iv(); | |||
*out_fixed_iv_len = 16; | |||
} else { | |||
*out_aead = EVP_aead_aes_128_cbc_sha1_tls(); | |||
} | |||
} else if (cipher->algorithm_enc == SSL_AES256) { | |||
if (version == SSL3_VERSION) { | |||
*out_aead = EVP_aead_aes_256_cbc_sha1_ssl3(); | |||
*out_fixed_iv_len = 16; | |||
} else if (version == TLS1_VERSION) { | |||
if (version == TLS1_VERSION) { | |||
*out_aead = EVP_aead_aes_256_cbc_sha1_tls_implicit_iv(); | |||
*out_fixed_iv_len = 16; | |||
} else { | |||
@@ -464,10 +464,7 @@ static bool ssl_can_renegotiate(const SSL *ssl) { | |||
return false; | |||
} | |||
// We do not accept at SSL 3.0. SSL 3.0 will be removed entirely in the future | |||
// and requires retaining more data for renegotiation_info. | |||
uint16_t version = ssl_protocol_version(ssl); | |||
if (version == SSL3_VERSION || version >= TLS1_3_VERSION) { | |||
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | |||
return false; | |||
} | |||
@@ -1490,9 +1487,8 @@ int SSL_get_tls_unique(const SSL *ssl, uint8_t *out, size_t *out_len, | |||
*out_len = 0; | |||
OPENSSL_memset(out, 0, max_out); | |||
// tls-unique is not defined for SSL 3.0 or TLS 1.3. | |||
// tls-unique is not defined for TLS 1.3. | |||
if (!ssl->s3->initial_handshake_complete || | |||
ssl_protocol_version(ssl) < TLS1_VERSION || | |||
ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | |||
return 0; | |||
} | |||
@@ -1644,7 +1640,6 @@ static size_t copy_finished(void *out, size_t out_len, const uint8_t *in, | |||
size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) { | |||
if (!ssl->s3->initial_handshake_complete || | |||
ssl_protocol_version(ssl) < TLS1_VERSION || | |||
ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | |||
return 0; | |||
} | |||
@@ -1660,7 +1655,6 @@ size_t SSL_get_finished(const SSL *ssl, void *buf, size_t count) { | |||
size_t SSL_get_peer_finished(const SSL *ssl, void *buf, size_t count) { | |||
if (!ssl->s3->initial_handshake_complete || | |||
ssl_protocol_version(ssl) < TLS1_VERSION || | |||
ssl_protocol_version(ssl) >= TLS1_3_VERSION) { | |||
return 0; | |||
} | |||
@@ -739,7 +739,6 @@ enum ssl_hs_wait_t ssl_get_prev_session(SSL_HANDSHAKE *hs, | |||
size_t ticket_len = 0; | |||
const bool tickets_supported = | |||
!(SSL_get_options(hs->ssl) & SSL_OP_NO_TICKET) && | |||
hs->ssl->version > SSL3_VERSION && | |||
SSL_early_callback_ctx_extension_get( | |||
client_hello, TLSEXT_TYPE_session_ticket, &ticket, &ticket_len); | |||
if (tickets_supported && ticket_len > 0) { | |||
@@ -71,7 +71,6 @@ struct VersionParam { | |||
static const size_t kTicketKeyLen = 48; | |||
static const VersionParam kAllVersions[] = { | |||
{SSL3_VERSION, VersionParam::is_tls, "SSL3"}, | |||
{TLS1_VERSION, VersionParam::is_tls, "TLS1"}, | |||
{TLS1_1_VERSION, VersionParam::is_tls, "TLS1_1"}, | |||
{TLS1_2_VERSION, VersionParam::is_tls, "TLS1_2"}, | |||
@@ -1965,13 +1964,6 @@ TEST(SSLTest, ClientHello) { | |||
uint16_t max_version; | |||
std::vector<uint8_t> expected; | |||
} kTests[] = { | |||
{SSL3_VERSION, | |||
{0x16, 0x03, 0x00, 0x00, 0x3b, 0x01, 0x00, 0x00, 0x37, 0x03, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
0x00, 0x10, 0xc0, 0x09, 0xc0, 0x13, 0xc0, 0x0a, 0xc0, 0x14, 0x00, | |||
0x2f, 0x00, 0x35, 0x00, 0x0a, 0x00, 0xff, 0x01, 0x00}}, | |||
{TLS1_VERSION, | |||
{0x16, 0x03, 0x01, 0x00, 0x5a, 0x01, 0x00, 0x00, 0x56, 0x03, 0x01, 0x00, | |||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | |||
@@ -2015,8 +2007,6 @@ TEST(SSLTest, ClientHello) { | |||
// Our default cipher list varies by CPU capabilities, so manually place the | |||
// ChaCha20 ciphers in front. | |||
const char *cipher_list = "CHACHA20:ALL"; | |||
// SSLv3 is off by default. | |||
ASSERT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION)); | |||
ASSERT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), t.max_version)); | |||
ASSERT_TRUE(SSL_CTX_set_strict_cipher_list(ctx.get(), cipher_list)); | |||
@@ -2349,11 +2339,6 @@ TEST_P(SSLVersionTest, SessionTimeout) { | |||
session.get(), | |||
false /* expect session not reused */)); | |||
// SSL 3.0 cannot renew sessions. | |||
if (version() == SSL3_VERSION) { | |||
continue; | |||
} | |||
// Renew the session 10 seconds before expiration. | |||
time_t new_start_time = kStartTime + timeout - 10; | |||
g_current_time.tv_sec = new_start_time; | |||
@@ -2436,10 +2421,6 @@ TEST_P(SSLVersionTest, DefaultTicketKeyInitialization) { | |||
} | |||
TEST_P(SSLVersionTest, DefaultTicketKeyRotation) { | |||
if (GetParam().version == SSL3_VERSION) { | |||
return; | |||
} | |||
static const time_t kStartTime = 1001; | |||
g_current_time.tv_sec = kStartTime; | |||
uint8_t ticket_key[kTicketKeyLen]; | |||
@@ -2509,11 +2490,6 @@ static int SwitchContext(SSL *ssl, int *out_alert, void *arg) { | |||
} | |||
TEST_P(SSLVersionTest, SNICallback) { | |||
// SSL 3.0 lacks extensions. | |||
if (version() == SSL3_VERSION) { | |||
return; | |||
} | |||
bssl::UniquePtr<X509> cert2 = GetECDSATestCertificate(); | |||
ASSERT_TRUE(cert2); | |||
bssl::UniquePtr<EVP_PKEY> key2 = GetECDSATestKey(); | |||
@@ -2619,12 +2595,13 @@ TEST(SSLTest, SetVersion) { | |||
EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), 0)); | |||
EXPECT_EQ(TLS1_VERSION, ctx->conf_min_version); | |||
// SSL 3.0 and TLS 1.3 are available, but not by default. | |||
EXPECT_TRUE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION)); | |||
EXPECT_EQ(SSL3_VERSION, ctx->conf_min_version); | |||
// TLS 1.3 is available, but not by default. | |||
EXPECT_TRUE(SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_VERSION)); | |||
EXPECT_EQ(TLS1_3_VERSION, ctx->conf_max_version); | |||
// SSL 3.0 is not available. | |||
EXPECT_FALSE(SSL_CTX_set_min_proto_version(ctx.get(), SSL3_VERSION)); | |||
// TLS1_3_DRAFT_VERSION is not an API-level version. | |||
EXPECT_FALSE( | |||
SSL_CTX_set_max_proto_version(ctx.get(), TLS1_3_DRAFT23_VERSION)); | |||
@@ -2655,8 +2632,6 @@ TEST(SSLTest, SetVersion) { | |||
static const char *GetVersionName(uint16_t version) { | |||
switch (version) { | |||
case SSL3_VERSION: | |||
return "SSLv3"; | |||
case TLS1_VERSION: | |||
return "TLSv1"; | |||
case TLS1_1_VERSION: | |||
@@ -2697,11 +2672,6 @@ TEST_P(SSLVersionTest, Version) { | |||
// Tests that that |SSL_get_pending_cipher| is available during the ALPN | |||
// selection callback. | |||
TEST_P(SSLVersionTest, ALPNCipherAvailable) { | |||
// SSL 3.0 lacks extensions. | |||
if (version() == SSL3_VERSION) { | |||
return; | |||
} | |||
ASSERT_TRUE(UseCertAndKey(client_ctx_.get())); | |||
static const uint8_t kALPNProtos[] = {0x03, 'f', 'o', 'o'}; | |||
@@ -3018,11 +2988,6 @@ TEST_P(SSLVersionTest, RecordCallback) { | |||
} | |||
TEST_P(SSLVersionTest, GetServerName) { | |||
// No extensions in SSL 3.0. | |||
if (version() == SSL3_VERSION) { | |||
return; | |||
} | |||
ClientConfig config; | |||
config.servername = "host1"; | |||
@@ -271,103 +271,9 @@ bool SSLTranscript::GetHash(uint8_t *out, size_t *out_len) { | |||
return true; | |||
} | |||
static bool SSL3HandshakeMAC(const SSL_SESSION *session, | |||
const EVP_MD_CTX *ctx_template, const char *sender, | |||
size_t sender_len, uint8_t *p, size_t *out_len) { | |||
ScopedEVP_MD_CTX ctx; | |||
if (!EVP_MD_CTX_copy_ex(ctx.get(), ctx_template)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); | |||
return false; | |||
} | |||
static const uint8_t kPad1[48] = { | |||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |||
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, | |||
}; | |||
static const uint8_t kPad2[48] = { | |||
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |||
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |||
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |||
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, | |||
}; | |||
size_t n = EVP_MD_CTX_size(ctx.get()); | |||
size_t npad = (48 / n) * n; | |||
EVP_DigestUpdate(ctx.get(), sender, sender_len); | |||
EVP_DigestUpdate(ctx.get(), session->master_key, session->master_key_length); | |||
EVP_DigestUpdate(ctx.get(), kPad1, npad); | |||
unsigned md_buf_len; | |||
uint8_t md_buf[EVP_MAX_MD_SIZE]; | |||
EVP_DigestFinal_ex(ctx.get(), md_buf, &md_buf_len); | |||
if (!EVP_DigestInit_ex(ctx.get(), EVP_MD_CTX_md(ctx.get()), NULL)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); | |||
return false; | |||
} | |||
EVP_DigestUpdate(ctx.get(), session->master_key, session->master_key_length); | |||
EVP_DigestUpdate(ctx.get(), kPad2, npad); | |||
EVP_DigestUpdate(ctx.get(), md_buf, md_buf_len); | |||
unsigned len; | |||
EVP_DigestFinal_ex(ctx.get(), p, &len); | |||
*out_len = len; | |||
return true; | |||
} | |||
bool SSLTranscript::GetSSL3CertVerifyHash(uint8_t *out, size_t *out_len, | |||
const SSL_SESSION *session, | |||
uint16_t signature_algorithm) { | |||
if (Digest() != EVP_md5_sha1()) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return false; | |||
} | |||
if (signature_algorithm == SSL_SIGN_RSA_PKCS1_MD5_SHA1) { | |||
size_t md5_len, len; | |||
if (!SSL3HandshakeMAC(session, md5_.get(), NULL, 0, out, &md5_len) || | |||
!SSL3HandshakeMAC(session, hash_.get(), NULL, 0, out + md5_len, &len)) { | |||
return false; | |||
} | |||
*out_len = md5_len + len; | |||
return true; | |||
} | |||
if (signature_algorithm == SSL_SIGN_ECDSA_SHA1) { | |||
return SSL3HandshakeMAC(session, hash_.get(), NULL, 0, out, out_len); | |||
} | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return false; | |||
} | |||
bool SSLTranscript::GetFinishedMAC(uint8_t *out, size_t *out_len, | |||
const SSL_SESSION *session, | |||
bool from_server) { | |||
if (session->ssl_version == SSL3_VERSION) { | |||
if (Digest() != EVP_md5_sha1()) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return false; | |||
} | |||
const char *sender = from_server ? SSL3_MD_SERVER_FINISHED_CONST | |||
: SSL3_MD_CLIENT_FINISHED_CONST; | |||
const size_t sender_len = 4; | |||
size_t md5_len, len; | |||
if (!SSL3HandshakeMAC(session, md5_.get(), sender, sender_len, out, | |||
&md5_len) || | |||
!SSL3HandshakeMAC(session, hash_.get(), sender, sender_len, | |||
out + md5_len, &len)) { | |||
return false; | |||
} | |||
*out_len = md5_len + len; | |||
return true; | |||
} | |||
static const char kClientLabel[] = "client finished"; | |||
static const char kServerLabel[] = "server finished"; | |||
auto label = from_server | |||
@@ -27,7 +27,6 @@ namespace bssl { | |||
bool ssl_protocol_version_from_wire(uint16_t *out, uint16_t version) { | |||
switch (version) { | |||
case SSL3_VERSION: | |||
case TLS1_VERSION: | |||
case TLS1_1_VERSION: | |||
case TLS1_2_VERSION: | |||
@@ -62,7 +61,6 @@ static const uint16_t kTLSVersions[] = { | |||
TLS1_2_VERSION, | |||
TLS1_1_VERSION, | |||
TLS1_VERSION, | |||
SSL3_VERSION, | |||
}; | |||
static const uint16_t kDTLSVersions[] = { | |||
@@ -114,9 +112,6 @@ static const char *ssl_version_to_string(uint16_t version) { | |||
case TLS1_VERSION: | |||
return "TLSv1"; | |||
case SSL3_VERSION: | |||
return "SSLv3"; | |||
case DTLS1_VERSION: | |||
return "DTLSv1"; | |||
@@ -200,7 +195,6 @@ const struct { | |||
uint16_t version; | |||
uint32_t flag; | |||
} kProtocolVersions[] = { | |||
{SSL3_VERSION, SSL_OP_NO_SSLv3}, | |||
{TLS1_VERSION, SSL_OP_NO_TLSv1}, | |||
{TLS1_1_VERSION, SSL_OP_NO_TLSv1_1}, | |||
{TLS1_2_VERSION, SSL_OP_NO_TLSv1_2}, | |||
@@ -164,56 +164,6 @@ bool tls1_prf(const EVP_MD *digest, Span<uint8_t> out, | |||
seed2.size()); | |||
} | |||
static bool ssl3_prf(Span<uint8_t> out, Span<const uint8_t> secret, | |||
Span<const char> label, Span<const uint8_t> seed1, | |||
Span<const uint8_t> seed2) { | |||
ScopedEVP_MD_CTX md5; | |||
ScopedEVP_MD_CTX sha1; | |||
uint8_t buf[16], smd[SHA_DIGEST_LENGTH]; | |||
uint8_t c = 'A'; | |||
size_t k = 0; | |||
while (!out.empty()) { | |||
k++; | |||
if (k > sizeof(buf)) { | |||
// bug: 'buf' is too small for this ciphersuite | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
return false; | |||
} | |||
for (size_t j = 0; j < k; j++) { | |||
buf[j] = c; | |||
} | |||
c++; | |||
if (!EVP_DigestInit_ex(sha1.get(), EVP_sha1(), NULL)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); | |||
return false; | |||
} | |||
EVP_DigestUpdate(sha1.get(), buf, k); | |||
EVP_DigestUpdate(sha1.get(), secret.data(), secret.size()); | |||
// |label| is ignored for SSLv3. | |||
EVP_DigestUpdate(sha1.get(), seed1.data(), seed1.size()); | |||
EVP_DigestUpdate(sha1.get(), seed2.data(), seed2.size()); | |||
EVP_DigestFinal_ex(sha1.get(), smd, NULL); | |||
if (!EVP_DigestInit_ex(md5.get(), EVP_md5(), NULL)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_LIB_EVP); | |||
return false; | |||
} | |||
EVP_DigestUpdate(md5.get(), secret.data(), secret.size()); | |||
EVP_DigestUpdate(md5.get(), smd, SHA_DIGEST_LENGTH); | |||
if (out.size() < MD5_DIGEST_LENGTH) { | |||
EVP_DigestFinal_ex(md5.get(), smd, NULL); | |||
OPENSSL_memcpy(out.data(), smd, out.size()); | |||
break; | |||
} | |||
EVP_DigestFinal_ex(md5.get(), out.data(), NULL); | |||
out = out.subspan(MD5_DIGEST_LENGTH); | |||
} | |||
OPENSSL_cleanse(smd, SHA_DIGEST_LENGTH); | |||
return true; | |||
} | |||
static bool get_key_block_lengths(const SSL *ssl, size_t *out_mac_secret_len, | |||
size_t *out_key_len, size_t *out_iv_len, | |||
const SSL_CIPHER *cipher) { | |||
@@ -318,16 +268,9 @@ int tls1_generate_master_secret(SSL_HANDSHAKE *hs, uint8_t *out, | |||
} else { | |||
auto label = | |||
MakeConstSpan(kMasterSecretLabel, sizeof(kMasterSecretLabel) - 1); | |||
if (ssl_protocol_version(ssl) == SSL3_VERSION) { | |||
if (!ssl3_prf(out_span, premaster, label, ssl->s3->client_random, | |||
ssl->s3->server_random)) { | |||
return 0; | |||
} | |||
} else { | |||
if (!tls1_prf(hs->transcript.Digest(), out_span, premaster, label, | |||
ssl->s3->client_random, ssl->s3->server_random)) { | |||
return 0; | |||
} | |||
if (!tls1_prf(hs->transcript.Digest(), out_span, premaster, label, | |||
ssl->s3->client_random, ssl->s3->server_random)) { | |||
return 0; | |||
} | |||
} | |||
@@ -357,11 +300,6 @@ int SSL_generate_key_block(const SSL *ssl, uint8_t *out, size_t out_len) { | |||
static const char kLabel[] = "key expansion"; | |||
auto label = MakeConstSpan(kLabel, sizeof(kLabel) - 1); | |||
if (ssl_protocol_version(ssl) == SSL3_VERSION) { | |||
return ssl3_prf(out_span, master_key, label, ssl->s3->server_random, | |||
ssl->s3->client_random); | |||
} | |||
const EVP_MD *digest = ssl_session_get_digest(session); | |||
return tls1_prf(digest, out_span, master_key, label, ssl->s3->server_random, | |||
ssl->s3->client_random); | |||
@@ -371,11 +309,6 @@ int SSL_export_keying_material(SSL *ssl, uint8_t *out, size_t out_len, | |||
const char *label, size_t label_len, | |||
const uint8_t *context, size_t context_len, | |||
int use_context) { | |||
if (!ssl->s3->have_version || ssl->version == SSL3_VERSION) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_HANDSHAKE_NOT_COMPLETE); | |||
return 0; | |||
} | |||
// Exporters may be used in False Start and server 0-RTT, where the handshake | |||
// has progressed enough. Otherwise, they may not be used during a handshake. | |||
if (SSL_in_init(ssl) && | |||
@@ -243,7 +243,7 @@ int ssl_client_hello_init(SSL *ssl, SSL_CLIENT_HELLO *out, | |||
out->compression_methods_len = CBS_len(&compression_methods); | |||
// If the ClientHello ends here then it's valid, but doesn't have any | |||
// extensions. (E.g. SSLv3.) | |||
// extensions. | |||
if (CBS_len(&client_hello) == 0) { | |||
out->extensions = NULL; | |||
out->extensions_len = 0; | |||
@@ -862,7 +862,7 @@ static bool ext_ri_add_serverhello(SSL_HANDSHAKE *hs, CBB *out) { | |||
static bool ext_ems_add_clienthello(SSL_HANDSHAKE *hs, CBB *out) { | |||
// Extended master secret is not necessary in TLS 1.3. | |||
if (hs->min_version >= TLS1_3_VERSION || hs->max_version <= SSL3_VERSION) { | |||
if (hs->min_version >= TLS1_3_VERSION) { | |||
return true; | |||
} | |||
@@ -880,7 +880,6 @@ static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | |||
if (contents != NULL) { | |||
if (ssl_protocol_version(ssl) >= TLS1_3_VERSION || | |||
ssl->version == SSL3_VERSION || | |||
CBS_len(contents) != 0) { | |||
return false; | |||
} | |||
@@ -902,9 +901,7 @@ static bool ext_ems_parse_serverhello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | |||
static bool ext_ems_parse_clienthello(SSL_HANDSHAKE *hs, uint8_t *out_alert, | |||
CBS *contents) { | |||
uint16_t version = ssl_protocol_version(hs->ssl); | |||
if (version >= TLS1_3_VERSION || | |||
version == SSL3_VERSION) { | |||
if (ssl_protocol_version(hs->ssl) >= TLS1_3_VERSION) { | |||
return true; | |||
} | |||
@@ -3085,12 +3082,6 @@ static const struct tls_extension *tls_extension_find(uint32_t *out_index, | |||
int ssl_add_clienthello_tlsext(SSL_HANDSHAKE *hs, CBB *out, size_t header_len) { | |||
SSL *const ssl = hs->ssl; | |||
// Don't add extensions for SSLv3 unless doing secure renegotiation. | |||
if (hs->client_version == SSL3_VERSION && | |||
!ssl->s3->send_connection_binding) { | |||
return 1; | |||
} | |||
CBB extensions; | |||
if (!CBB_add_u16_length_prefixed(out, &extensions)) { | |||
OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR); | |||
@@ -3239,7 +3230,6 @@ err: | |||
static int ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs, | |||
const SSL_CLIENT_HELLO *client_hello, | |||
int *out_alert) { | |||
SSL *const ssl = hs->ssl; | |||
for (size_t i = 0; i < kNumExtensions; i++) { | |||
if (kExtensions[i].init != NULL) { | |||
kExtensions[i].init(hs); | |||
@@ -3261,16 +3251,9 @@ static int ssl_scan_clienthello_tlsext(SSL_HANDSHAKE *hs, | |||
return 0; | |||
} | |||
// RFC 5746 made the existence of extensions in SSL 3.0 somewhat | |||
// ambiguous. Ignore all but the renegotiation_info extension. | |||
if (ssl->version == SSL3_VERSION && type != TLSEXT_TYPE_renegotiate) { | |||
continue; | |||
} | |||
unsigned ext_index; | |||
const struct tls_extension *const ext = | |||
tls_extension_find(&ext_index, type); | |||
if (ext == NULL) { | |||
if (!custom_ext_parse_clienthello(hs, out_alert, type, &extension)) { | |||
OPENSSL_PUT_ERROR(SSL, SSL_R_ERROR_PARSING_EXTENSION); | |||
@@ -1190,10 +1190,9 @@ static bssl::UniquePtr<SSL_CTX> SetupCtx(SSL_CTX *old_ctx, | |||
SSL_CTX_set0_buffer_pool(ssl_ctx.get(), g_pool); | |||
// Enable SSL 3.0 and TLS 1.3 for tests. | |||
// Enable TLS 1.3 for tests. | |||
if (!config->is_dtls && | |||
(!SSL_CTX_set_min_proto_version(ssl_ctx.get(), SSL3_VERSION) || | |||
!SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION))) { | |||
!SSL_CTX_set_max_proto_version(ssl_ctx.get(), TLS1_3_VERSION)) { | |||
return nullptr; | |||
} | |||
@@ -2125,9 +2124,6 @@ static bssl::UniquePtr<SSL> NewSSL(SSL_CTX *ssl_ctx, const TestConfig *config, | |||
if (config->no_tls1) { | |||
SSL_set_options(ssl.get(), SSL_OP_NO_TLSv1); | |||
} | |||
if (config->no_ssl3) { | |||
SSL_set_options(ssl.get(), SSL_OP_NO_SSLv3); | |||
} | |||
if (!config->expected_channel_id.empty() || | |||
config->enable_channel_id) { | |||
SSL_set_tls_channel_id_enabled(ssl.get(), 1); | |||
@@ -409,11 +409,9 @@ class TLSFuzzer { | |||
if (!SSL_CTX_set_strict_cipher_list(ctx_.get(), "ALL:NULL-SHA")) { | |||
return false; | |||
} | |||
if (protocol_ == kTLS) { | |||
if (!SSL_CTX_set_max_proto_version(ctx_.get(), TLS1_3_VERSION) || | |||
!SSL_CTX_set_min_proto_version(ctx_.get(), SSL3_VERSION)) { | |||
return false; | |||
} | |||
if (protocol_ == kTLS && | |||
!SSL_CTX_set_max_proto_version(ctx_.get(), TLS1_3_VERSION)) { | |||
return false; | |||
} | |||
SSL_CTX_set_early_data_enabled(ctx_.get(), 1); | |||
@@ -1353,11 +1353,6 @@ func (vers tlsVersion) wire(protocol protocol) uint16 { | |||
} | |||
var tlsVersions = []tlsVersion{ | |||
{ | |||
name: "SSL3", | |||
version: VersionSSL30, | |||
excludeFlag: "-no-ssl3", | |||
}, | |||
{ | |||
name: "TLS1", | |||
version: VersionTLS10, | |||
@@ -1838,7 +1833,7 @@ read alert 1 0 | |||
}, | |||
{ | |||
name: "DisableEverything", | |||
flags: []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1", "-no-ssl3"}, | |||
flags: []string{"-no-tls13", "-no-tls12", "-no-tls11", "-no-tls1"}, | |||
shouldFail: true, | |||
expectedError: ":NO_SUPPORTED_VERSIONS_ENABLED:", | |||
}, | |||
@@ -3174,33 +3169,22 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto | |||
flags = append(flags, "-cipher", "DEFAULT:NULL-SHA") | |||
} | |||
var shouldServerFail, shouldClientFail bool | |||
if hasComponent(suite.name, "ECDHE") && ver.version == VersionSSL30 { | |||
// BoringSSL clients accept ECDHE on SSLv3, but | |||
// a BoringSSL server will never select it | |||
// because the extension is missing. | |||
shouldServerFail = true | |||
} | |||
var shouldFail bool | |||
if isTLS12Only(suite.name) && ver.version < VersionTLS12 { | |||
shouldClientFail = true | |||
shouldServerFail = true | |||
shouldFail = true | |||
} | |||
if !isTLS13Suite(suite.name) && ver.version >= VersionTLS13 { | |||
shouldClientFail = true | |||
shouldServerFail = true | |||
shouldFail = true | |||
} | |||
if isTLS13Suite(suite.name) && ver.version < VersionTLS13 { | |||
shouldClientFail = true | |||
shouldServerFail = true | |||
shouldFail = true | |||
} | |||
var sendCipherSuite uint16 | |||
var expectedServerError, expectedClientError string | |||
serverCipherSuites := []uint16{suite.id} | |||
if shouldServerFail { | |||
if shouldFail { | |||
expectedServerError = ":NO_SHARED_CIPHER:" | |||
} | |||
if shouldClientFail { | |||
expectedClientError = ":WRONG_CIPHER_RETURNED:" | |||
// Configure the server to select ciphers as normal but | |||
// select an incompatible cipher in ServerHello. | |||
@@ -3208,12 +3192,8 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto | |||
sendCipherSuite = suite.id | |||
} | |||
// For cipher suites and versions where exporters are defined, verify | |||
// that they interoperate. | |||
var exportKeyingMaterial int | |||
if ver.version > VersionSSL30 { | |||
exportKeyingMaterial = 1024 | |||
} | |||
// Verify exporters interoperate. | |||
exportKeyingMaterial := 1024 | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
@@ -3235,7 +3215,7 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto | |||
keyFile: keyFile, | |||
flags: flags, | |||
resumeSession: true, | |||
shouldFail: shouldServerFail, | |||
shouldFail: shouldFail, | |||
expectedError: expectedServerError, | |||
exportKeyingMaterial: exportKeyingMaterial, | |||
}) | |||
@@ -3252,19 +3232,19 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto | |||
PreSharedKey: []byte(psk), | |||
PreSharedKeyIdentity: pskIdentity, | |||
Bugs: ProtocolBugs{ | |||
IgnorePeerCipherPreferences: shouldClientFail, | |||
IgnorePeerCipherPreferences: shouldFail, | |||
SendCipherSuite: sendCipherSuite, | |||
}, | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: flags, | |||
resumeSession: true, | |||
shouldFail: shouldClientFail, | |||
shouldFail: shouldFail, | |||
expectedError: expectedClientError, | |||
exportKeyingMaterial: exportKeyingMaterial, | |||
}) | |||
if shouldClientFail { | |||
if shouldFail { | |||
return | |||
} | |||
@@ -3287,10 +3267,9 @@ func addTestForCipherSuite(suite testCipherSuite, ver tlsVersion, protocol proto | |||
// Test bad records for all ciphers. Bad records are fatal in TLS | |||
// and ignored in DTLS. | |||
var shouldFail bool | |||
shouldFail = protocol == tls | |||
var expectedError string | |||
if protocol == tls { | |||
shouldFail = true | |||
if shouldFail { | |||
expectedError = ":DECRYPTION_FAILED_OR_BAD_RECORD_MAC:" | |||
} | |||
@@ -3796,34 +3775,32 @@ func addClientAuthTests() { | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{"-require-any-client-certificate"}, | |||
}) | |||
if ver.version != VersionSSL30 { | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: ver.name + "-Server-ClientAuth-ECDSA", | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
Certificates: []Certificate{ecdsaP256Certificate}, | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{"-require-any-client-certificate"}, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: clientTest, | |||
name: ver.name + "-Client-ClientAuth-ECDSA", | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
ClientAuth: RequireAnyClientCert, | |||
ClientCAs: certPool, | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile), | |||
"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile), | |||
}, | |||
}) | |||
} | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: ver.name + "-Server-ClientAuth-ECDSA", | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
Certificates: []Certificate{ecdsaP256Certificate}, | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{"-require-any-client-certificate"}, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: clientTest, | |||
name: ver.name + "-Client-ClientAuth-ECDSA", | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
ClientAuth: RequireAnyClientCert, | |||
ClientCAs: certPool, | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, ecdsaP256CertificateFile), | |||
"-key-file", path.Join(*resourceDir, ecdsaP256KeyFile), | |||
}, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
name: "NoClientCertificate-" + ver.name, | |||
@@ -3890,57 +3867,55 @@ func addClientAuthTests() { | |||
expectedLocalError: certificateRequired, | |||
}) | |||
if ver.version != VersionSSL30 { | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SkipClientCertificate-" + ver.name, | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
Bugs: ProtocolBugs{ | |||
SkipClientCertificate: true, | |||
}, | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SkipClientCertificate-" + ver.name, | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
Bugs: ProtocolBugs{ | |||
SkipClientCertificate: true, | |||
}, | |||
// Setting SSL_VERIFY_PEER allows anonymous clients. | |||
flags: []string{"-verify-peer"}, | |||
tls13Variant: ver.tls13Variant, | |||
shouldFail: true, | |||
expectedError: ":UNEXPECTED_MESSAGE:", | |||
}) | |||
}, | |||
// Setting SSL_VERIFY_PEER allows anonymous clients. | |||
flags: []string{"-verify-peer"}, | |||
tls13Variant: ver.tls13Variant, | |||
shouldFail: true, | |||
expectedError: ":UNEXPECTED_MESSAGE:", | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "VerifyPeerIfNoOBC-NoChannelID-" + ver.name, | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
}, | |||
flags: []string{ | |||
"-enable-channel-id", | |||
"-verify-peer-if-no-obc", | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
shouldFail: true, | |||
expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:", | |||
expectedLocalError: certificateRequired, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "VerifyPeerIfNoOBC-NoChannelID-" + ver.name, | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
}, | |||
flags: []string{ | |||
"-enable-channel-id", | |||
"-verify-peer-if-no-obc", | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
shouldFail: true, | |||
expectedError: ":PEER_DID_NOT_RETURN_A_CERTIFICATE:", | |||
expectedLocalError: certificateRequired, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "VerifyPeerIfNoOBC-ChannelID-" + ver.name, | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
ChannelID: channelIDKey, | |||
}, | |||
expectChannelID: true, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{ | |||
"-enable-channel-id", | |||
"-verify-peer-if-no-obc", | |||
}, | |||
}) | |||
} | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "VerifyPeerIfNoOBC-ChannelID-" + ver.name, | |||
config: Config{ | |||
MinVersion: ver.version, | |||
MaxVersion: ver.version, | |||
ChannelID: channelIDKey, | |||
}, | |||
expectChannelID: true, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{ | |||
"-enable-channel-id", | |||
"-verify-peer-if-no-obc", | |||
}, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
@@ -4078,7 +4053,7 @@ func addExtendedMasterSecretTests() { | |||
flags = []string{expectEMSFlag} | |||
} | |||
test := testCase{ | |||
testCases = append(testCases, testCase{ | |||
testType: testType, | |||
name: prefix + "ExtendedMasterSecret-" + ver.name + suffix, | |||
config: Config{ | |||
@@ -4091,12 +4066,7 @@ func addExtendedMasterSecretTests() { | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: flags, | |||
shouldFail: ver.version == VersionSSL30 && with, | |||
} | |||
if test.shouldFail { | |||
test.expectedLocalError = "extended master secret required but not supported by peer" | |||
} | |||
testCases = append(testCases, test) | |||
}) | |||
} | |||
} | |||
} | |||
@@ -4559,23 +4529,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { | |||
flags: []string{"-verify-peer"}, | |||
}) | |||
if config.protocol == tls { | |||
tests = append(tests, testCase{ | |||
testType: clientTest, | |||
name: "ClientAuth-NoCertificate-Client-SSL3", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
ClientAuth: RequestClientCert, | |||
}, | |||
}) | |||
tests = append(tests, testCase{ | |||
testType: serverTest, | |||
name: "ClientAuth-NoCertificate-Server-SSL3", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
}, | |||
// Setting SSL_VERIFY_PEER allows anonymous clients. | |||
flags: []string{"-verify-peer"}, | |||
}) | |||
tests = append(tests, testCase{ | |||
testType: clientTest, | |||
name: "ClientAuth-NoCertificate-Client-TLS13", | |||
@@ -4800,9 +4753,6 @@ func addStateMachineCoverageTests(config stateMachineTestConfig) { | |||
if config.protocol == dtls && !vers.hasDTLS { | |||
continue | |||
} | |||
if vers.version == VersionSSL30 { | |||
continue | |||
} | |||
tests = append(tests, testCase{ | |||
testType: clientTest, | |||
name: "OCSPStapling-Client-" + vers.name, | |||
@@ -5923,6 +5873,46 @@ func addVersionNegotiationTests() { | |||
}, | |||
}, | |||
}) | |||
// SSL 3.0 support has been removed. Test that the shim does not | |||
// support it. | |||
testCases = append(testCases, testCase{ | |||
name: "NoSSL3-Client", | |||
config: Config{ | |||
MinVersion: VersionSSL30, | |||
MaxVersion: VersionSSL30, | |||
}, | |||
shouldFail: true, | |||
expectedLocalError: "tls: client did not offer any supported protocol versions", | |||
}) | |||
testCases = append(testCases, testCase{ | |||
name: "NoSSL3-Client-Unsolicited", | |||
config: Config{ | |||
MinVersion: VersionSSL30, | |||
MaxVersion: VersionSSL30, | |||
Bugs: ProtocolBugs{ | |||
// The above test asserts the client does not | |||
// offer SSL 3.0 in the supported_versions | |||
// list. Additionally assert that it rejects an | |||
// unsolicited SSL 3.0 ServerHello. | |||
NegotiateVersion: VersionSSL30, | |||
}, | |||
}, | |||
shouldFail: true, | |||
expectedError: ":UNSUPPORTED_PROTOCOL:", | |||
expectedLocalError: "remote error: protocol version not supported", | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "NoSSL3-Server", | |||
config: Config{ | |||
MinVersion: VersionSSL30, | |||
MaxVersion: VersionSSL30, | |||
}, | |||
shouldFail: true, | |||
expectedError: ":UNSUPPORTED_PROTOCOL:", | |||
expectedLocalError: "remote error: protocol version not supported", | |||
}) | |||
} | |||
func addMinimumVersionTests() { | |||
@@ -6051,12 +6041,8 @@ func addExtensionTests() { | |||
// halves to EncryptedExtensions in TLS 1.3. Duplicate each of these | |||
// tests for both. Also test interaction with 0-RTT when implemented. | |||
// Repeat extensions tests all versions except SSL 3.0. | |||
// Repeat extensions tests at all versions. | |||
for _, ver := range tlsVersions { | |||
if ver.version == VersionSSL30 { | |||
continue | |||
} | |||
// Test that duplicate extensions are rejected. | |||
testCases = append(testCases, testCase{ | |||
testType: clientTest, | |||
@@ -7227,70 +7213,6 @@ func addExtensionTests() { | |||
flags: []string{"-host-name", "01234567890123456789012345678901234567890123456789012345678901234567890123456789.com"}, | |||
}) | |||
// Extensions should not function in SSL 3.0. | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SSLv3Extensions-NoALPN", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
NextProtos: []string{"foo", "bar", "baz"}, | |||
}, | |||
flags: []string{ | |||
"-select-alpn", "foo", | |||
}, | |||
expectNoNextProto: true, | |||
}) | |||
// Test session tickets separately as they follow a different codepath. | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SSLv3Extensions-NoTickets", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
Bugs: ProtocolBugs{ | |||
// Historically, session tickets in SSL 3.0 | |||
// failed in different ways depending on whether | |||
// the client supported renegotiation_info. | |||
NoRenegotiationInfo: true, | |||
}, | |||
}, | |||
resumeSession: true, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SSLv3Extensions-NoTickets2", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
}, | |||
resumeSession: true, | |||
}) | |||
// But SSL 3.0 does send and process renegotiation_info. | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SSLv3Extensions-RenegotiationInfo", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
Bugs: ProtocolBugs{ | |||
RequireRenegotiationInfo: true, | |||
}, | |||
}, | |||
flags: []string{"-expect-secure-renegotiation"}, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "SSLv3Extensions-RenegotiationInfo-SCSV", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
Bugs: ProtocolBugs{ | |||
NoRenegotiationInfo: true, | |||
SendRenegotiationSCSV: true, | |||
RequireRenegotiationInfo: true, | |||
}, | |||
}, | |||
flags: []string{"-expect-secure-renegotiation"}, | |||
}) | |||
// Test that illegal extensions in TLS 1.3 are rejected by the client if | |||
// in ServerHello. | |||
testCases = append(testCases, testCase{ | |||
@@ -7569,14 +7491,6 @@ func addExtensionTests() { | |||
func addResumptionVersionTests() { | |||
for _, sessionVers := range tlsVersions { | |||
for _, resumeVers := range tlsVersions { | |||
// SSL 3.0 does not have tickets and TLS 1.3 does not | |||
// have session IDs, so skip their cross-resumption | |||
// tests. | |||
if (sessionVers.version >= VersionTLS13 && resumeVers.version == VersionSSL30) || | |||
(resumeVers.version >= VersionTLS13 && sessionVers.version == VersionSSL30) { | |||
continue | |||
} | |||
protocols := []protocol{tls} | |||
if sessionVers.hasDTLS && resumeVers.hasDTLS { | |||
protocols = append(protocols, dtls) | |||
@@ -8400,22 +8314,6 @@ func addRenegotiationTests() { | |||
expectedLocalError: "remote error: no renegotiation", | |||
}) | |||
// Renegotiation is not allowed at SSL 3.0. | |||
testCases = append(testCases, testCase{ | |||
name: "Renegotiate-Client-SSL3", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
}, | |||
renegotiate: 1, | |||
flags: []string{ | |||
"-renegotiate-freely", | |||
"-expect-total-renegotiations", "1", | |||
}, | |||
shouldFail: true, | |||
expectedError: ":NO_RENEGOTIATION:", | |||
expectedLocalError: "remote error: no renegotiation", | |||
}) | |||
// Renegotiation is not allowed when there is an unfinished write. | |||
testCases = append(testCases, testCase{ | |||
name: "Renegotiate-Client-UnfinishedWrite", | |||
@@ -8702,12 +8600,6 @@ func addSignatureAlgorithmTests() { | |||
continue | |||
} | |||
// TODO(davidben): Support ECDSA in SSL 3.0 in Go for testing | |||
// or remove it in C. | |||
if ver.version == VersionSSL30 && alg.cert != testCertRSA { | |||
continue | |||
} | |||
var shouldSignFail, shouldVerifyFail bool | |||
// ecdsa_sha1 does not exist in TLS 1.3. | |||
if ver.version >= VersionTLS13 && alg.id == signatureECDSAWithSHA1 { | |||
@@ -8794,32 +8686,29 @@ func addSignatureAlgorithmTests() { | |||
expectedError: verifyError, | |||
}) | |||
// No signing cipher for SSL 3.0. | |||
if ver.version > VersionSSL30 { | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "ServerAuth-Sign" + suffix, | |||
config: Config{ | |||
MaxVersion: ver.version, | |||
CipherSuites: signingCiphers, | |||
VerifySignatureAlgorithms: []signatureAlgorithm{ | |||
fakeSigAlg1, | |||
alg.id, | |||
fakeSigAlg2, | |||
}, | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)), | |||
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)), | |||
"-enable-all-curves", | |||
"-enable-ed25519", | |||
testCases = append(testCases, testCase{ | |||
testType: serverTest, | |||
name: "ServerAuth-Sign" + suffix, | |||
config: Config{ | |||
MaxVersion: ver.version, | |||
CipherSuites: signingCiphers, | |||
VerifySignatureAlgorithms: []signatureAlgorithm{ | |||
fakeSigAlg1, | |||
alg.id, | |||
fakeSigAlg2, | |||
}, | |||
shouldFail: shouldSignFail, | |||
expectedError: signError, | |||
expectedPeerSignatureAlgorithm: alg.id, | |||
}) | |||
} | |||
}, | |||
tls13Variant: ver.tls13Variant, | |||
flags: []string{ | |||
"-cert-file", path.Join(*resourceDir, getShimCertificate(alg.cert)), | |||
"-key-file", path.Join(*resourceDir, getShimKey(alg.cert)), | |||
"-enable-all-curves", | |||
"-enable-ed25519", | |||
}, | |||
shouldFail: shouldSignFail, | |||
expectedError: signError, | |||
expectedPeerSignatureAlgorithm: alg.id, | |||
}) | |||
testCases = append(testCases, testCase{ | |||
name: "ServerAuth-Verify" + suffix, | |||
@@ -9977,9 +9866,6 @@ func addDTLSRetransmitTests() { | |||
func addExportKeyingMaterialTests() { | |||
for _, vers := range tlsVersions { | |||
if vers.version == VersionSSL30 { | |||
continue | |||
} | |||
testCases = append(testCases, testCase{ | |||
name: "ExportKeyingMaterial-" + vers.name, | |||
config: Config{ | |||
@@ -10247,19 +10133,6 @@ func addExportKeyingMaterialTests() { | |||
} | |||
} | |||
testCases = append(testCases, testCase{ | |||
name: "ExportKeyingMaterial-SSL3", | |||
config: Config{ | |||
MaxVersion: VersionSSL30, | |||
}, | |||
exportKeyingMaterial: 1024, | |||
exportLabel: "label", | |||
exportContext: "context", | |||
useExportContext: true, | |||
shouldFail: true, | |||
expectedError: "failed to export keying material", | |||
}) | |||
// Exporters work during a False Start. | |||
testCases = append(testCases, testCase{ | |||
name: "ExportKeyingMaterial-FalseStart", | |||
@@ -10772,11 +10645,6 @@ const bogusCurve = 0x1234 | |||
func addCurveTests() { | |||
for _, curve := range testCurves { | |||
for _, ver := range tlsVersions { | |||
// SSL 3.0 cannot reliably negotiate curves. | |||
if ver.version == VersionSSL30 { | |||
continue | |||
} | |||
suffix := curve.name + "-" + ver.name | |||
testCases = append(testCases, testCase{ | |||
@@ -59,7 +59,6 @@ const Flag<bool> kBoolFlags[] = { | |||
{ "-no-tls12", &TestConfig::no_tls12 }, | |||
{ "-no-tls11", &TestConfig::no_tls11 }, | |||
{ "-no-tls1", &TestConfig::no_tls1 }, | |||
{ "-no-ssl3", &TestConfig::no_ssl3 }, | |||
{ "-enable-channel-id", &TestConfig::enable_channel_id }, | |||
{ "-shim-writes-first", &TestConfig::shim_writes_first }, | |||
{ "-expect-session-miss", &TestConfig::expect_session_miss }, | |||
@@ -45,7 +45,6 @@ struct TestConfig { | |||
bool no_tls12 = false; | |||
bool no_tls11 = false; | |||
bool no_tls1 = false; | |||
bool no_ssl3 = false; | |||
std::string expected_channel_id; | |||
bool enable_channel_id = false; | |||
std::string send_channel_id; | |||
@@ -256,10 +256,7 @@ bool Listener::Accept(int *out_sock) { | |||
} | |||
bool VersionFromString(uint16_t *out_version, const std::string &version) { | |||
if (version == "ssl3") { | |||
*out_version = SSL3_VERSION; | |||
return true; | |||
} else if (version == "tls1" || version == "tls1.0") { | |||
if (version == "tls1" || version == "tls1.0") { | |||
*out_version = TLS1_VERSION; | |||
return true; | |||
} else if (version == "tls1.1") { | |||