CECPQ1: change from named curve to ciphersuite.
This is easier to deploy, and more obvious. This commit reverts a few
pieces of e25775bc
, but keeps most of it.
Change-Id: If8d657a4221c665349c06041bb12fffca1527a2c
Reviewed-on: https://boringssl-review.googlesource.com/8061
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
parent
d09175ffe3
commit
053931e74e
@ -1098,6 +1098,9 @@ OPENSSL_EXPORT int SSL_CIPHER_is_ECDSA(const SSL_CIPHER *cipher);
|
||||
/* SSL_CIPHER_is_ECDHE returns one if |cipher| uses ECDHE. */
|
||||
OPENSSL_EXPORT int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher);
|
||||
|
||||
/* SSL_CIPHER_is_CECPQ1 returns one if |cipher| uses CECPQ1. */
|
||||
OPENSSL_EXPORT int SSL_CIPHER_is_CECPQ1(const SSL_CIPHER *cipher);
|
||||
|
||||
/* SSL_CIPHER_get_min_version returns the minimum protocol version required
|
||||
* for |cipher|. */
|
||||
OPENSSL_EXPORT uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher);
|
||||
@ -3358,6 +3361,7 @@ OPENSSL_EXPORT const char *SSL_alert_desc_string(int value);
|
||||
#define SSL_TXT_kDHE "kDHE"
|
||||
#define SSL_TXT_kEDH "kEDH"
|
||||
#define SSL_TXT_kECDHE "kECDHE"
|
||||
#define SSL_TXT_kCECPQ1 "kCECPQ1"
|
||||
#define SSL_TXT_kEECDH "kEECDH"
|
||||
#define SSL_TXT_kPSK "kPSK"
|
||||
#define SSL_TXT_aRSA "aRSA"
|
||||
|
@ -441,6 +441,12 @@ extern "C" {
|
||||
#define TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305 \
|
||||
TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
||||
|
||||
/* CECPQ1 ciphersuites. These are specific to BoringSSL and not standard. */
|
||||
#define TLS1_CK_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 0x030016B7
|
||||
#define TLS1_CK_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 0x030016B8
|
||||
#define TLS1_CK_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 0x030016B9
|
||||
#define TLS1_CK_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 0x030016BA
|
||||
|
||||
/* XXX
|
||||
* Inconsistency alert:
|
||||
* The OpenSSL names of ciphers with ephemeral DH here include the string
|
||||
@ -621,6 +627,17 @@ extern "C" {
|
||||
#define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 \
|
||||
TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
|
||||
|
||||
/* CECPQ1 ciphersuites. These are specific to BoringSSL and not standard. */
|
||||
#define TLS1_TXT_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 \
|
||||
"CECPQ1-RSA-CHACHA20-POLY1305-SHA256"
|
||||
#define TLS1_TXT_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 \
|
||||
"CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256"
|
||||
#define TLS1_TXT_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 \
|
||||
"CECPQ1-RSA-AES256-GCM-SHA384"
|
||||
#define TLS1_TXT_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 \
|
||||
"CECPQ1-ECDSA-AES256-GCM-SHA384"
|
||||
|
||||
|
||||
#define TLS_CT_RSA_SIGN 1
|
||||
#define TLS_CT_DSS_SIGN 2
|
||||
#define TLS_CT_RSA_FIXED_DH 3
|
||||
|
@ -167,6 +167,7 @@
|
||||
#define SSL_kECDHE 0x00000004L
|
||||
/* SSL_kPSK is only set for plain PSK, not ECDHE_PSK. */
|
||||
#define SSL_kPSK 0x00000008L
|
||||
#define SSL_kCECPQ1 0x00000010L
|
||||
|
||||
/* Bits for |algorithm_auth| (server authentication). */
|
||||
#define SSL_aRSA 0x00000001L
|
||||
|
@ -1132,7 +1132,8 @@ int ssl3_get_server_key_exchange(SSL *ssl) {
|
||||
if (!CBS_stow(&dh_Ys, &ssl->s3->tmp.peer_key, &peer_key_len)) {
|
||||
goto err;
|
||||
}
|
||||
/* |dh_Ys| has a u16 length prefix, so this fits in a |uint16_t|. */
|
||||
/* |dh_Ys| was initialized with CBS_get_u16_length_prefixed, so peer_key_len
|
||||
* fits in a uint16_t. */
|
||||
assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
|
||||
ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
|
||||
} else if (alg_k & SSL_kECDHE) {
|
||||
@ -1142,7 +1143,8 @@ int ssl3_get_server_key_exchange(SSL *ssl) {
|
||||
CBS point;
|
||||
if (!CBS_get_u8(&server_key_exchange, &group_type) ||
|
||||
group_type != NAMED_CURVE_TYPE ||
|
||||
!CBS_get_u16(&server_key_exchange, &group_id)) {
|
||||
!CBS_get_u16(&server_key_exchange, &group_id) ||
|
||||
!CBS_get_u8_length_prefixed(&server_key_exchange, &point)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
|
||||
goto f_err;
|
||||
@ -1156,22 +1158,33 @@ int ssl3_get_server_key_exchange(SSL *ssl) {
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id)) {
|
||||
/* Initialize ECDH and save the peer public key for later. */
|
||||
size_t peer_key_len;
|
||||
if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
|
||||
!CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) {
|
||||
goto err;
|
||||
}
|
||||
if (!SSL_ECDH_CTX_get_key(&ssl->s3->tmp.ecdh_ctx, &server_key_exchange,
|
||||
&point)) {
|
||||
/* |point| was initialized with CBS_get_u8_length_prefixed, so peer_key_len
|
||||
* fits in a uint16_t. */
|
||||
assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
|
||||
ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
|
||||
} else if (alg_k & SSL_kCECPQ1) {
|
||||
if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, SSL_GROUP_CECPQ1)) {
|
||||
goto err;
|
||||
}
|
||||
CBS key;
|
||||
if (!CBS_get_u16_length_prefixed(&server_key_exchange, &key)) {
|
||||
al = SSL_AD_DECODE_ERROR;
|
||||
OPENSSL_PUT_ERROR(SSL, SSL_R_DECODE_ERROR);
|
||||
goto f_err;
|
||||
}
|
||||
|
||||
/* Initialize ECDH and save the peer public key for later. */
|
||||
size_t peer_key_len;
|
||||
if (!CBS_stow(&point, &ssl->s3->tmp.peer_key, &peer_key_len)) {
|
||||
if (!CBS_stow(&key, &ssl->s3->tmp.peer_key, &peer_key_len)) {
|
||||
goto err;
|
||||
}
|
||||
/* |point| has a u8 or u16 length prefix, so this fits in a |uint16_t|. */
|
||||
/* |key| was initialized with CBS_get_u16_length_prefixed, so peer_key_len
|
||||
* fits in a uint16_t. */
|
||||
assert(sizeof(ssl->s3->tmp.peer_key_len) == 2 && peer_key_len <= 0xffff);
|
||||
ssl->s3->tmp.peer_key_len = (uint16_t)peer_key_len;
|
||||
} else if (!(alg_k & SSL_kPSK)) {
|
||||
@ -1623,7 +1636,7 @@ int ssl3_send_client_key_exchange(SSL *ssl) {
|
||||
!CBB_flush(&cbb)) {
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
|
||||
} else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
|
||||
/* Generate a keypair and serialize the public half. */
|
||||
CBB child;
|
||||
if (!SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &cbb, &child)) {
|
||||
|
@ -1209,7 +1209,7 @@ int ssl3_send_server_key_exchange(SSL *ssl) {
|
||||
!BN_bn2cbb_padded(&child, BN_num_bytes(params->p), params->p) ||
|
||||
!CBB_add_u16_length_prefixed(&cbb, &child) ||
|
||||
!BN_bn2cbb_padded(&child, BN_num_bytes(params->g), params->g) ||
|
||||
!SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &cbb, &child) ||
|
||||
!CBB_add_u16_length_prefixed(&cbb, &child) ||
|
||||
!SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
|
||||
goto err;
|
||||
}
|
||||
@ -1227,7 +1227,13 @@ int ssl3_send_server_key_exchange(SSL *ssl) {
|
||||
if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, group_id) ||
|
||||
!CBB_add_u8(&cbb, NAMED_CURVE_TYPE) ||
|
||||
!CBB_add_u16(&cbb, group_id) ||
|
||||
!SSL_ECDH_CTX_add_key(&ssl->s3->tmp.ecdh_ctx, &cbb, &child) ||
|
||||
!CBB_add_u8_length_prefixed(&cbb, &child) ||
|
||||
!SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
|
||||
goto err;
|
||||
}
|
||||
} else if (alg_k & SSL_kCECPQ1) {
|
||||
if (!SSL_ECDH_CTX_init(&ssl->s3->tmp.ecdh_ctx, SSL_GROUP_CECPQ1) ||
|
||||
!CBB_add_u16_length_prefixed(&cbb, &child) ||
|
||||
!SSL_ECDH_CTX_offer(&ssl->s3->tmp.ecdh_ctx, &child)) {
|
||||
goto err;
|
||||
}
|
||||
@ -1590,7 +1596,7 @@ int ssl3_get_client_key_exchange(SSL *ssl) {
|
||||
|
||||
OPENSSL_free(decrypt_buf);
|
||||
decrypt_buf = NULL;
|
||||
} else if (alg_k & (SSL_kECDHE|SSL_kDHE)) {
|
||||
} else if (alg_k & (SSL_kECDHE|SSL_kDHE|SSL_kCECPQ1)) {
|
||||
/* Parse the ClientKeyExchange. */
|
||||
CBS peer_key;
|
||||
if (!SSL_ECDH_CTX_get_key(&ssl->s3->tmp.ecdh_ctx, &client_key_exchange,
|
||||
|
105
ssl/ssl_cipher.c
105
ssl/ssl_cipher.c
@ -375,6 +375,52 @@ static const SSL_CIPHER kCiphers[] = {
|
||||
SSL_HANDSHAKE_MAC_SHA384,
|
||||
},
|
||||
|
||||
/* CECPQ1 (combined elliptic curve + post-quantum) suites. */
|
||||
|
||||
/* Cipher 16B7 */
|
||||
{
|
||||
TLS1_TXT_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
TLS1_CK_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
SSL_kCECPQ1,
|
||||
SSL_aRSA,
|
||||
SSL_CHACHA20POLY1305,
|
||||
SSL_AEAD,
|
||||
SSL_HANDSHAKE_MAC_SHA256,
|
||||
},
|
||||
|
||||
/* Cipher 16B8 */
|
||||
{
|
||||
TLS1_TXT_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
TLS1_CK_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256,
|
||||
SSL_kCECPQ1,
|
||||
SSL_aECDSA,
|
||||
SSL_CHACHA20POLY1305,
|
||||
SSL_AEAD,
|
||||
SSL_HANDSHAKE_MAC_SHA256,
|
||||
},
|
||||
|
||||
/* Cipher 16B9 */
|
||||
{
|
||||
TLS1_TXT_CECPQ1_RSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS1_CK_CECPQ1_RSA_WITH_AES_256_GCM_SHA384,
|
||||
SSL_kCECPQ1,
|
||||
SSL_aRSA,
|
||||
SSL_AES256GCM,
|
||||
SSL_AEAD,
|
||||
SSL_HANDSHAKE_MAC_SHA384,
|
||||
},
|
||||
|
||||
/* Cipher 16BA */
|
||||
{
|
||||
TLS1_TXT_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
TLS1_CK_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384,
|
||||
SSL_kCECPQ1,
|
||||
SSL_aECDSA,
|
||||
SSL_AES256GCM,
|
||||
SSL_AEAD,
|
||||
SSL_HANDSHAKE_MAC_SHA384,
|
||||
},
|
||||
|
||||
/* Cipher C007 */
|
||||
{
|
||||
TLS1_TXT_ECDHE_ECDSA_WITH_RC4_128_SHA,
|
||||
@ -615,6 +661,7 @@ static const SSL_CIPHER kCiphers[] = {
|
||||
SSL_AEAD,
|
||||
SSL_HANDSHAKE_MAC_SHA256,
|
||||
},
|
||||
|
||||
};
|
||||
|
||||
static const size_t kCiphersLen = sizeof(kCiphers) / sizeof(kCiphers[0]);
|
||||
@ -651,8 +698,9 @@ typedef struct cipher_alias_st {
|
||||
} CIPHER_ALIAS;
|
||||
|
||||
static const CIPHER_ALIAS kCipherAliases[] = {
|
||||
/* "ALL" doesn't include eNULL (must be specifically enabled) */
|
||||
{"ALL", ~0u, ~0u, ~SSL_eNULL, ~0u, 0},
|
||||
/* "ALL" doesn't include eNULL nor kCECPQ1. These must be explicitly
|
||||
* enabled. */
|
||||
{"ALL", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, 0},
|
||||
|
||||
/* The "COMPLEMENTOFDEFAULT" rule is omitted. It matches nothing. */
|
||||
|
||||
@ -667,15 +715,16 @@ static const CIPHER_ALIAS kCipherAliases[] = {
|
||||
{"DH", SSL_kDHE, ~0u, ~0u, ~0u, 0},
|
||||
|
||||
{"kECDHE", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
|
||||
{"kCECPQ1", SSL_kCECPQ1, ~0u, ~0u, ~0u, 0},
|
||||
{"kEECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
|
||||
{"ECDH", SSL_kECDHE, ~0u, ~0u, ~0u, 0},
|
||||
|
||||
{"kPSK", SSL_kPSK, ~0u, ~0u, ~0u, 0},
|
||||
|
||||
/* server authentication aliases */
|
||||
{"aRSA", ~0u, SSL_aRSA, ~SSL_eNULL, ~0u, 0},
|
||||
{"aECDSA", ~0u, SSL_aECDSA, ~0u, ~0u, 0},
|
||||
{"ECDSA", ~0u, SSL_aECDSA, ~0u, ~0u, 0},
|
||||
{"aRSA", ~SSL_kCECPQ1, SSL_aRSA, ~SSL_eNULL, ~0u, 0},
|
||||
{"aECDSA", ~SSL_kCECPQ1, SSL_aECDSA, ~0u, ~0u, 0},
|
||||
{"ECDSA", ~SSL_kCECPQ1, SSL_aECDSA, ~0u, ~0u, 0},
|
||||
{"aPSK", ~0u, SSL_aPSK, ~0u, ~0u, 0},
|
||||
|
||||
/* aliases combining key exchange and server authentication */
|
||||
@ -690,29 +739,29 @@ static const CIPHER_ALIAS kCipherAliases[] = {
|
||||
{"3DES", ~0u, ~0u, SSL_3DES, ~0u, 0},
|
||||
{"RC4", ~0u, ~0u, SSL_RC4, ~0u, 0},
|
||||
{"AES128", ~0u, ~0u, SSL_AES128 | SSL_AES128GCM, ~0u, 0},
|
||||
{"AES256", ~0u, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0},
|
||||
{"AES", ~0u, ~0u, SSL_AES, ~0u, 0},
|
||||
{"AESGCM", ~0u, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0},
|
||||
{"CHACHA20", ~0u, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u,
|
||||
{"AES256", ~SSL_kCECPQ1, ~0u, SSL_AES256 | SSL_AES256GCM, ~0u, 0},
|
||||
{"AES", ~SSL_kCECPQ1, ~0u, SSL_AES, ~0u, 0},
|
||||
{"AESGCM", ~SSL_kCECPQ1, ~0u, SSL_AES128GCM | SSL_AES256GCM, ~0u, 0},
|
||||
{"CHACHA20", ~SSL_kCECPQ1, ~0u, SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_OLD, ~0u,
|
||||
0},
|
||||
|
||||
/* MAC aliases */
|
||||
{"MD5", ~0u, ~0u, ~0u, SSL_MD5, 0},
|
||||
{"SHA1", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
|
||||
{"SHA", ~0u, ~0u, ~SSL_eNULL, SSL_SHA1, 0},
|
||||
{"SHA256", ~0u, ~0u, ~0u, SSL_SHA256, 0},
|
||||
{"SHA384", ~0u, ~0u, ~0u, SSL_SHA384, 0},
|
||||
{"SHA256", ~SSL_kCECPQ1, ~0u, ~0u, SSL_SHA256, 0},
|
||||
{"SHA384", ~SSL_kCECPQ1, ~0u, ~0u, SSL_SHA384, 0},
|
||||
|
||||
/* Legacy protocol minimum version aliases. "TLSv1" is intentionally the
|
||||
* same as "SSLv3". */
|
||||
{"SSLv3", ~0u, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
|
||||
{"TLSv1", ~0u, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
|
||||
{"TLSv1.2", ~0u, ~0u, ~SSL_eNULL, ~0u, TLS1_2_VERSION},
|
||||
{"SSLv3", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
|
||||
{"TLSv1", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, SSL3_VERSION},
|
||||
{"TLSv1.2", ~SSL_kCECPQ1, ~0u, ~SSL_eNULL, ~0u, TLS1_2_VERSION},
|
||||
|
||||
/* Legacy strength classes. */
|
||||
{"MEDIUM", ~0u, ~0u, SSL_RC4, ~0u, 0},
|
||||
{"HIGH", ~0u, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
|
||||
{"FIPS", ~0u, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
|
||||
{"HIGH", ~SSL_kCECPQ1, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
|
||||
{"FIPS", ~SSL_kCECPQ1, ~0u, ~(SSL_eNULL|SSL_RC4), ~0u, 0},
|
||||
};
|
||||
|
||||
static const size_t kCipherAliasesLen =
|
||||
@ -1404,6 +1453,7 @@ ssl_create_cipher_list(const SSL_PROTOCOL_METHOD *ssl_method,
|
||||
|
||||
/* Everything else being equal, prefer ECDHE_ECDSA then ECDHE_RSA over other
|
||||
* key exchange mechanisms */
|
||||
|
||||
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, ~0u, ~0u, 0, CIPHER_ADD, -1,
|
||||
0, &head, &tail);
|
||||
ssl_cipher_apply_rule(0, SSL_kECDHE, ~0u, ~0u, ~0u, 0, CIPHER_ADD, -1, 0,
|
||||
@ -1623,6 +1673,10 @@ int SSL_CIPHER_is_ECDHE(const SSL_CIPHER *cipher) {
|
||||
return (cipher->algorithm_mkey & SSL_kECDHE) != 0;
|
||||
}
|
||||
|
||||
int SSL_CIPHER_is_CECPQ1(const SSL_CIPHER *cipher) {
|
||||
return (cipher->algorithm_mkey & SSL_kCECPQ1) != 0;
|
||||
}
|
||||
|
||||
uint16_t SSL_CIPHER_get_min_version(const SSL_CIPHER *cipher) {
|
||||
if (cipher->algorithm_prf != SSL_HANDSHAKE_MAC_DEFAULT) {
|
||||
/* Cipher suites before TLS 1.2 use the default PRF, while all those added
|
||||
@ -1672,6 +1726,17 @@ const char *SSL_CIPHER_get_kx_name(const SSL_CIPHER *cipher) {
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
case SSL_kCECPQ1:
|
||||
switch (cipher->algorithm_auth) {
|
||||
case SSL_aECDSA:
|
||||
return "CECPQ1_ECDSA";
|
||||
case SSL_aRSA:
|
||||
return "CECPQ1_RSA";
|
||||
default:
|
||||
assert(0);
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
case SSL_kPSK:
|
||||
assert(cipher->algorithm_auth == SSL_aPSK);
|
||||
return "PSK";
|
||||
@ -1826,6 +1891,10 @@ const char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf,
|
||||
kx = "ECDH";
|
||||
break;
|
||||
|
||||
case SSL_kCECPQ1:
|
||||
kx = "CECPQ1";
|
||||
break;
|
||||
|
||||
case SSL_kPSK:
|
||||
kx = "PSK";
|
||||
break;
|
||||
@ -1963,7 +2032,9 @@ int ssl_cipher_uses_certificate_auth(const SSL_CIPHER *cipher) {
|
||||
|
||||
int ssl_cipher_requires_server_key_exchange(const SSL_CIPHER *cipher) {
|
||||
/* Ephemeral Diffie-Hellman key exchanges require a ServerKeyExchange. */
|
||||
if (cipher->algorithm_mkey & SSL_kDHE || cipher->algorithm_mkey & SSL_kECDHE) {
|
||||
if (cipher->algorithm_mkey & SSL_kDHE ||
|
||||
cipher->algorithm_mkey & SSL_kECDHE ||
|
||||
cipher->algorithm_mkey & SSL_kCECPQ1) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1725,6 +1725,9 @@ void ssl_get_compatible_server_ciphers(SSL *ssl, uint32_t *out_mask_k,
|
||||
mask_k |= SSL_kECDHE;
|
||||
}
|
||||
|
||||
/* CECPQ1 ciphers are always acceptable if supported by both sides. */
|
||||
mask_k |= SSL_kCECPQ1;
|
||||
|
||||
/* PSK requires a server callback. */
|
||||
if (ssl->psk_server_callback != NULL) {
|
||||
mask_k |= SSL_kPSK;
|
||||
|
@ -254,6 +254,31 @@ static const char *kMustNotIncludeNull[] = {
|
||||
"TLSv1.2",
|
||||
};
|
||||
|
||||
static const char *kMustNotIncludeCECPQ1[] = {
|
||||
"ALL",
|
||||
"DEFAULT",
|
||||
"MEDIUM",
|
||||
"HIGH",
|
||||
"FIPS",
|
||||
"SHA",
|
||||
"SHA1",
|
||||
"SHA256",
|
||||
"SHA384",
|
||||
"RSA",
|
||||
"SSLv3",
|
||||
"TLSv1",
|
||||
"TLSv1.2",
|
||||
"aRSA",
|
||||
"RSA",
|
||||
"aECDSA",
|
||||
"ECDSA",
|
||||
"AES",
|
||||
"AES128",
|
||||
"AES256",
|
||||
"AESGCM",
|
||||
"CHACHA20",
|
||||
};
|
||||
|
||||
static void PrintCipherPreferenceList(ssl_cipher_preference_list_st *list) {
|
||||
bool in_group = false;
|
||||
for (size_t i = 0; i < sk_SSL_CIPHER_num(list->ciphers); i++) {
|
||||
@ -324,6 +349,24 @@ static bool TestRuleDoesNotIncludeNull(const char *rule) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestRuleDoesNotIncludeCECPQ1(const char *rule) {
|
||||
ScopedSSL_CTX ctx(SSL_CTX_new(TLS_method()));
|
||||
if (!ctx) {
|
||||
return false;
|
||||
}
|
||||
if (!SSL_CTX_set_cipher_list(ctx.get(), rule)) {
|
||||
fprintf(stderr, "Error: cipher rule '%s' failed\n", rule);
|
||||
return false;
|
||||
}
|
||||
for (size_t i = 0; i < sk_SSL_CIPHER_num(ctx->cipher_list->ciphers); i++) {
|
||||
if (SSL_CIPHER_is_CECPQ1(sk_SSL_CIPHER_value(ctx->cipher_list->ciphers, i))) {
|
||||
fprintf(stderr, "Error: cipher rule '%s' includes CECPQ1\n",rule);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool TestCipherRules() {
|
||||
for (const CipherTest &test : kCipherTests) {
|
||||
if (!TestCipherRule(test)) {
|
||||
@ -349,6 +392,12 @@ static bool TestCipherRules() {
|
||||
}
|
||||
}
|
||||
|
||||
for (const char *rule : kMustNotIncludeCECPQ1) {
|
||||
if (!TestRuleDoesNotIncludeCECPQ1(rule)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1313,7 +1313,7 @@ static bool DoExchange(ScopedSSL_SESSION *out_session, SSL_CTX *ssl_ctx,
|
||||
}
|
||||
if (config->enable_all_curves) {
|
||||
static const int kAllCurves[] = {
|
||||
NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519, NID_cecpq1
|
||||
NID_X9_62_prime256v1, NID_secp384r1, NID_secp521r1, NID_X25519,
|
||||
};
|
||||
if (!SSL_set1_curves(ssl.get(), kAllCurves,
|
||||
sizeof(kAllCurves) / sizeof(kAllCurves[0]))) {
|
||||
|
@ -43,6 +43,9 @@ const (
|
||||
// client indicates that it supports ECC with a curve and point format
|
||||
// that we're happy with.
|
||||
suiteECDHE = 1 << iota
|
||||
// suiteCECPQ1 indicates that the cipher suite uses the
|
||||
// experimental, temporary, and non-standard CECPQ1 key agreement.
|
||||
suiteCECPQ1
|
||||
// suiteECDSA indicates that the cipher suite involves an ECDSA
|
||||
// signature and therefore may only be selected when the server's
|
||||
// certificate is ECDSA. If this is not set then the cipher suite is
|
||||
@ -104,6 +107,10 @@ var cipherSuites = []*cipherSuite{
|
||||
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, 32, 48, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA | suiteTLS12 | suiteSHA384, cipherAES, macSHA384, nil},
|
||||
{TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheRSAKA, suiteECDHE, cipherAES, macSHA1, nil},
|
||||
{TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, 32, 20, 16, ecdheECDSAKA, suiteECDHE | suiteECDSA, cipherAES, macSHA1, nil},
|
||||
{TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
|
||||
{TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256, 32, 0, 12, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12, nil, nil, aeadCHACHA20POLY1305},
|
||||
{TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1RSAKA, suiteCECPQ1 | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
|
||||
{TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, cecpq1ECDSAKA, suiteCECPQ1 | suiteECDSA | suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
|
||||
{TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, 16, 0, 4, dheRSAKA, suiteTLS12, nil, nil, aeadAESGCM},
|
||||
{TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, 32, 0, 4, dheRSAKA, suiteTLS12 | suiteSHA384, nil, nil, aeadAESGCM},
|
||||
{TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, 16, 32, 16, dheRSAKA, suiteTLS12, cipherAES, macSHA256, nil},
|
||||
@ -373,6 +380,15 @@ func ecdheECDSAKA(version uint16) keyAgreement {
|
||||
}
|
||||
}
|
||||
|
||||
func cecpq1ECDSAKA(version uint16) keyAgreement {
|
||||
return &cecpq1KeyAgreement{
|
||||
auth: &signedKeyAgreement{
|
||||
sigType: signatureECDSA,
|
||||
version: version,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ecdheRSAKA(version uint16) keyAgreement {
|
||||
return &ecdheKeyAgreement{
|
||||
auth: &signedKeyAgreement{
|
||||
@ -382,6 +398,15 @@ func ecdheRSAKA(version uint16) keyAgreement {
|
||||
}
|
||||
}
|
||||
|
||||
func cecpq1RSAKA(version uint16) keyAgreement {
|
||||
return &cecpq1KeyAgreement{
|
||||
auth: &signedKeyAgreement{
|
||||
sigType: signatureRSA,
|
||||
version: version,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func dheRSAKA(version uint16) keyAgreement {
|
||||
return &dheKeyAgreement{
|
||||
auth: &signedKeyAgreement{
|
||||
@ -472,4 +497,8 @@ const (
|
||||
const (
|
||||
TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc13
|
||||
TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256_OLD uint16 = 0xcc14
|
||||
TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0x16b7
|
||||
TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256 uint16 = 0x16b8
|
||||
TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384 uint16 = 0x16b9
|
||||
TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384 uint16 = 0x16ba
|
||||
)
|
||||
|
@ -103,7 +103,6 @@ const (
|
||||
CurveP384 CurveID = 24
|
||||
CurveP521 CurveID = 25
|
||||
CurveX25519 CurveID = 29
|
||||
CurveCECPQ1 CurveID = 65165
|
||||
)
|
||||
|
||||
// TLS Elliptic Curve Point Formats
|
||||
|
@ -421,8 +421,6 @@ func curveForCurveID(id CurveID) (ecdhCurve, bool) {
|
||||
return &ellipticECDHCurve{curve: elliptic.P521()}, true
|
||||
case CurveX25519:
|
||||
return &x25519ECDHCurve{}, true
|
||||
case CurveCECPQ1:
|
||||
return &cecpq1Curve{}, true
|
||||
default:
|
||||
return nil, false
|
||||
}
|
||||
@ -647,19 +645,15 @@ NextCandidate:
|
||||
}
|
||||
|
||||
// http://tools.ietf.org/html/rfc4492#section-5.4
|
||||
var serverECDHParams []byte
|
||||
serverECDHParams = append(serverECDHParams, byte(3)) // named curve
|
||||
serverECDHParams = append(serverECDHParams, byte(curveid>>8))
|
||||
serverECDHParams = append(serverECDHParams, byte(curveid))
|
||||
serverECDHParams := make([]byte, 1+2+1+len(publicKey))
|
||||
serverECDHParams[0] = 3 // named curve
|
||||
serverECDHParams[1] = byte(curveid >> 8)
|
||||
serverECDHParams[2] = byte(curveid)
|
||||
if config.Bugs.InvalidSKXCurve {
|
||||
serverECDHParams[2] ^= 0xff
|
||||
}
|
||||
if curveid == CurveCECPQ1 {
|
||||
// The larger key size requires an extra length byte.
|
||||
serverECDHParams = append(serverECDHParams, byte(len(publicKey)>>8))
|
||||
}
|
||||
serverECDHParams = append(serverECDHParams, byte(len(publicKey)&0xff))
|
||||
serverECDHParams = append(serverECDHParams, publicKey[:]...)
|
||||
serverECDHParams[3] = byte(len(publicKey))
|
||||
copy(serverECDHParams[4:], publicKey)
|
||||
if config.Bugs.InvalidECDHPoint {
|
||||
serverECDHParams[4] ^= 0xff
|
||||
}
|
||||
@ -668,21 +662,10 @@ NextCandidate:
|
||||
}
|
||||
|
||||
func (ka *ecdheKeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
if len(ckx.ciphertext) == 0 {
|
||||
if len(ckx.ciphertext) == 0 || int(ckx.ciphertext[0]) != len(ckx.ciphertext)-1 {
|
||||
return nil, errClientKeyExchange
|
||||
}
|
||||
peerKeyLen := int(ckx.ciphertext[0])
|
||||
offset := 1
|
||||
if _, postQuantum := ka.curve.(*cecpq1Curve); postQuantum {
|
||||
// The larger key size requires an extra length byte.
|
||||
peerKeyLen = int(ckx.ciphertext[0])<<8 + int(ckx.ciphertext[1])
|
||||
offset = 2
|
||||
}
|
||||
peerKey := ckx.ciphertext[offset:]
|
||||
if peerKeyLen != len(peerKey) {
|
||||
return nil, errClientKeyExchange
|
||||
}
|
||||
return ka.curve.finish(peerKey)
|
||||
return ka.curve.finish(ckx.ciphertext[1:])
|
||||
}
|
||||
|
||||
func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
||||
@ -700,22 +683,15 @@ func (ka *ecdheKeyAgreement) processServerKeyExchange(config *Config, clientHell
|
||||
}
|
||||
|
||||
publicLen := int(skx.key[3])
|
||||
publicOffset := 4
|
||||
if curveid == CurveCECPQ1 {
|
||||
// The larger key size requires an extra length byte.
|
||||
publicLen = int(skx.key[3])<<8 + int(skx.key[4])
|
||||
publicOffset += 1
|
||||
}
|
||||
|
||||
if publicLen+publicOffset > len(skx.key) {
|
||||
if publicLen+4 > len(skx.key) {
|
||||
return errServerKeyExchange
|
||||
}
|
||||
// Save the peer key for later.
|
||||
ka.peerKey = skx.key[publicOffset : publicOffset+publicLen]
|
||||
ka.peerKey = skx.key[4 : 4+publicLen]
|
||||
|
||||
// Check the signature.
|
||||
serverECDHParams := skx.key[:publicOffset+publicLen]
|
||||
sig := skx.key[publicOffset+publicLen:]
|
||||
serverECDHParams := skx.key[:4+publicLen]
|
||||
sig := skx.key[4+publicLen:]
|
||||
return ka.auth.verifyParameters(config, clientHello, serverHello, cert, serverECDHParams, sig)
|
||||
}
|
||||
|
||||
@ -730,14 +706,82 @@ func (ka *ecdheKeyAgreement) generateClientKeyExchange(config *Config, clientHel
|
||||
}
|
||||
|
||||
ckx := new(clientKeyExchangeMsg)
|
||||
if _, postQuantum := ka.curve.(*cecpq1Curve); postQuantum {
|
||||
// The larger key size requires an extra length byte.
|
||||
ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)>>8))
|
||||
}
|
||||
ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)&0xff))
|
||||
ckx.ciphertext = make([]byte, 1+len(publicKey))
|
||||
ckx.ciphertext[0] = byte(len(publicKey))
|
||||
copy(ckx.ciphertext[1:], publicKey)
|
||||
if config.Bugs.InvalidECDHPoint {
|
||||
publicKey[0] ^= 0xff
|
||||
ckx.ciphertext[1] ^= 0xff
|
||||
}
|
||||
|
||||
return preMasterSecret, ckx, nil
|
||||
}
|
||||
|
||||
// cecpq1RSAKeyAgreement is like an ecdheKeyAgreement, but using the cecpq1Curve
|
||||
// pseudo-curve, and without any parameters (e.g. curve name) other than the
|
||||
// keys being exchanged. The signature may either be ECDSA or RSA.
|
||||
type cecpq1KeyAgreement struct {
|
||||
auth keyAgreementAuthentication
|
||||
curve ecdhCurve
|
||||
peerKey []byte
|
||||
}
|
||||
|
||||
func (ka *cecpq1KeyAgreement) generateServerKeyExchange(config *Config, cert *Certificate, clientHello *clientHelloMsg, hello *serverHelloMsg) (*serverKeyExchangeMsg, error) {
|
||||
ka.curve = &cecpq1Curve{}
|
||||
publicKey, err := ka.curve.offer(config.rand())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var params []byte
|
||||
params = append(params, byte(len(publicKey)>>8))
|
||||
params = append(params, byte(len(publicKey)&0xff))
|
||||
params = append(params, publicKey[:]...)
|
||||
|
||||
return ka.auth.signParameters(config, cert, clientHello, hello, params)
|
||||
}
|
||||
|
||||
func (ka *cecpq1KeyAgreement) processClientKeyExchange(config *Config, cert *Certificate, ckx *clientKeyExchangeMsg, version uint16) ([]byte, error) {
|
||||
if len(ckx.ciphertext) < 2 {
|
||||
return nil, errClientKeyExchange
|
||||
}
|
||||
peerKeyLen := int(ckx.ciphertext[0])<<8 + int(ckx.ciphertext[1])
|
||||
peerKey := ckx.ciphertext[2:]
|
||||
if peerKeyLen != len(peerKey) {
|
||||
return nil, errClientKeyExchange
|
||||
}
|
||||
return ka.curve.finish(peerKey)
|
||||
}
|
||||
|
||||
func (ka *cecpq1KeyAgreement) processServerKeyExchange(config *Config, clientHello *clientHelloMsg, serverHello *serverHelloMsg, cert *x509.Certificate, skx *serverKeyExchangeMsg) error {
|
||||
if len(skx.key) < 2 {
|
||||
return errServerKeyExchange
|
||||
}
|
||||
peerKeyLen := int(skx.key[0])<<8 + int(skx.key[1])
|
||||
// Save the peer key for later.
|
||||
if len(skx.key) < 2+peerKeyLen {
|
||||
return errServerKeyExchange
|
||||
}
|
||||
ka.peerKey = skx.key[2 : 2+peerKeyLen]
|
||||
if peerKeyLen != len(ka.peerKey) {
|
||||
return errServerKeyExchange
|
||||
}
|
||||
|
||||
// Check the signature.
|
||||
params := skx.key[:2+peerKeyLen]
|
||||
sig := skx.key[2+peerKeyLen:]
|
||||
return ka.auth.verifyParameters(config, clientHello, serverHello, cert, params, sig)
|
||||
}
|
||||
|
||||
func (ka *cecpq1KeyAgreement) generateClientKeyExchange(config *Config, clientHello *clientHelloMsg, cert *x509.Certificate) ([]byte, *clientKeyExchangeMsg, error) {
|
||||
curve := &cecpq1Curve{}
|
||||
publicKey, preMasterSecret, err := curve.accept(config.rand(), ka.peerKey)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
ckx := new(clientKeyExchangeMsg)
|
||||
ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)>>8))
|
||||
ckx.ciphertext = append(ckx.ciphertext, byte(len(publicKey)&0xff))
|
||||
ckx.ciphertext = append(ckx.ciphertext, publicKey[:]...)
|
||||
|
||||
return preMasterSecret, ckx, nil
|
||||
|
@ -915,6 +915,10 @@ var testCipherSuites = []struct {
|
||||
{"ECDHE-RSA-CHACHA20-POLY1305", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256},
|
||||
{"ECDHE-RSA-CHACHA20-POLY1305-OLD", TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256_OLD},
|
||||
{"ECDHE-RSA-RC4-SHA", TLS_ECDHE_RSA_WITH_RC4_128_SHA},
|
||||
{"CECPQ1-RSA-CHACHA20-POLY1305-SHA256", TLS_CECPQ1_RSA_WITH_CHACHA20_POLY1305_SHA256},
|
||||
{"CECPQ1-ECDSA-CHACHA20-POLY1305-SHA256", TLS_CECPQ1_ECDSA_WITH_CHACHA20_POLY1305_SHA256},
|
||||
{"CECPQ1-RSA-AES256-GCM-SHA384", TLS_CECPQ1_RSA_WITH_AES_256_GCM_SHA384},
|
||||
{"CECPQ1-ECDSA-AES256-GCM-SHA384", TLS_CECPQ1_ECDSA_WITH_AES_256_GCM_SHA384},
|
||||
{"PSK-AES128-CBC-SHA", TLS_PSK_WITH_AES_128_CBC_SHA},
|
||||
{"PSK-AES256-CBC-SHA", TLS_PSK_WITH_AES_256_CBC_SHA},
|
||||
{"ECDHE-PSK-AES128-CBC-SHA", TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA},
|
||||
@ -2295,6 +2299,10 @@ func addCipherSuiteTests() {
|
||||
// NULL ciphers must be explicitly enabled.
|
||||
flags = append(flags, "-cipher", "DEFAULT:NULL-SHA")
|
||||
}
|
||||
if hasComponent(suite.name, "CECPQ1") {
|
||||
// CECPQ1 ciphers must be explicitly enabled.
|
||||
flags = append(flags, "-cipher", "DEFAULT:kCECPQ1")
|
||||
}
|
||||
|
||||
for _, ver := range tlsVersions {
|
||||
if ver.version < VersionTLS12 && isTLS12Only(suite.name) {
|
||||
@ -5020,7 +5028,6 @@ var testCurves = []struct {
|
||||
{"P-384", CurveP384},
|
||||
{"P-521", CurveP521},
|
||||
{"X25519", CurveX25519},
|
||||
{"CECPQ1", CurveCECPQ1},
|
||||
}
|
||||
|
||||
func addCurveTests() {
|
||||
|
Loading…
Reference in New Issue
Block a user