Add 1.1.1e-dev patch.
This commit is contained in:
@@ -0,0 +1,509 @@
|
|||||||
|
diff --git a/crypto/evp/c_allc.c b/crypto/evp/c_allc.c
|
||||||
|
index 086b3c4d51..5699901f7d 100644
|
||||||
|
--- a/crypto/evp/c_allc.c
|
||||||
|
+++ b/crypto/evp/c_allc.c
|
||||||
|
@@ -261,6 +261,7 @@ void openssl_add_all_ciphers_int(void)
|
||||||
|
EVP_add_cipher(EVP_chacha20());
|
||||||
|
# ifndef OPENSSL_NO_POLY1305
|
||||||
|
EVP_add_cipher(EVP_chacha20_poly1305());
|
||||||
|
+ EVP_add_cipher(EVP_chacha20_poly1305_draft());
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
diff --git a/crypto/evp/e_chacha20_poly1305.c b/crypto/evp/e_chacha20_poly1305.c
|
||||||
|
index 600365d2f0..fce66d074d 100644
|
||||||
|
--- a/crypto/evp/e_chacha20_poly1305.c
|
||||||
|
+++ b/crypto/evp/e_chacha20_poly1305.c
|
||||||
|
@@ -156,6 +156,7 @@ typedef struct {
|
||||||
|
struct { uint64_t aad, text; } len;
|
||||||
|
int aad, mac_inited, tag_len, nonce_len;
|
||||||
|
size_t tls_payload_length;
|
||||||
|
+ unsigned char draft:1;
|
||||||
|
} EVP_CHACHA_AEAD_CTX;
|
||||||
|
|
||||||
|
# define NO_TLS_PAYLOAD_LENGTH ((size_t)-1)
|
||||||
|
@@ -176,6 +177,7 @@ static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
|
||||||
|
actx->aad = 0;
|
||||||
|
actx->mac_inited = 0;
|
||||||
|
actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
|
||||||
|
+ actx->draft = 0;
|
||||||
|
|
||||||
|
if (iv != NULL) {
|
||||||
|
unsigned char temp[CHACHA_CTR_SIZE] = { 0 };
|
||||||
|
@@ -197,6 +199,27 @@ static int chacha20_poly1305_init_key(EVP_CIPHER_CTX *ctx,
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int chacha20_poly1305_draft_init_key(EVP_CIPHER_CTX *ctx,
|
||||||
|
+ const unsigned char *inkey,
|
||||||
|
+ const unsigned char *iv, int enc)
|
||||||
|
+{
|
||||||
|
+ EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
|
||||||
|
+
|
||||||
|
+ if (!inkey)
|
||||||
|
+ return 1;
|
||||||
|
+
|
||||||
|
+ actx->len.aad = 0;
|
||||||
|
+ actx->len.text = 0;
|
||||||
|
+ actx->aad = 0;
|
||||||
|
+ actx->mac_inited = 0;
|
||||||
|
+ actx->tls_payload_length = NO_TLS_PAYLOAD_LENGTH;
|
||||||
|
+ actx->draft = 1;
|
||||||
|
+
|
||||||
|
+ chacha_init_key(ctx, inkey, NULL, enc);
|
||||||
|
+
|
||||||
|
+ return 1;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
# if !defined(OPENSSL_SMALL_FOOTPRINT)
|
||||||
|
|
||||||
|
# if defined(POLY1305_ASM) && (defined(__x86_64) || defined(__x86_64__) || \
|
||||||
|
@@ -367,10 +390,11 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||||
|
{
|
||||||
|
EVP_CHACHA_AEAD_CTX *actx = aead_data(ctx);
|
||||||
|
size_t rem, plen = actx->tls_payload_length;
|
||||||
|
+ uint64_t thirteen = EVP_AEAD_TLS1_AAD_LEN;
|
||||||
|
|
||||||
|
if (!actx->mac_inited) {
|
||||||
|
# if !defined(OPENSSL_SMALL_FOOTPRINT)
|
||||||
|
- if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL)
|
||||||
|
+ if (plen != NO_TLS_PAYLOAD_LENGTH && out != NULL && !actx->draft)
|
||||||
|
return chacha20_poly1305_tls_cipher(ctx, out, in, len);
|
||||||
|
# endif
|
||||||
|
actx->key.counter[0] = 0;
|
||||||
|
@@ -397,9 +421,14 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||||
|
return len;
|
||||||
|
} else { /* plain- or ciphertext */
|
||||||
|
if (actx->aad) { /* wrap up aad */
|
||||||
|
- if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
|
||||||
|
- Poly1305_Update(POLY1305_ctx(actx), zero,
|
||||||
|
- POLY1305_BLOCK_SIZE - rem);
|
||||||
|
+ if (actx->draft) {
|
||||||
|
+ thirteen = actx->len.aad;
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), (const unsigned char *)&thirteen, sizeof(thirteen));
|
||||||
|
+ } else {
|
||||||
|
+ if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), zero,
|
||||||
|
+ POLY1305_BLOCK_SIZE - rem);
|
||||||
|
+ }
|
||||||
|
actx->aad = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -432,40 +461,52 @@ static int chacha20_poly1305_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
|
||||||
|
} is_endian = { 1 };
|
||||||
|
unsigned char temp[POLY1305_BLOCK_SIZE];
|
||||||
|
|
||||||
|
+ if (actx->draft) {
|
||||||
|
+ thirteen = actx->len.text;
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), (const unsigned char *)&thirteen, sizeof(thirteen));
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (actx->aad) { /* wrap up aad */
|
||||||
|
- if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
|
||||||
|
- Poly1305_Update(POLY1305_ctx(actx), zero,
|
||||||
|
- POLY1305_BLOCK_SIZE - rem);
|
||||||
|
+ if (actx->draft) {
|
||||||
|
+ thirteen = actx->len.aad;
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), (const unsigned char *)&thirteen, sizeof(thirteen));
|
||||||
|
+ } else {
|
||||||
|
+ if ((rem = (size_t)actx->len.aad % POLY1305_BLOCK_SIZE))
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), zero,
|
||||||
|
+ POLY1305_BLOCK_SIZE - rem);
|
||||||
|
+ }
|
||||||
|
actx->aad = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
|
||||||
|
- Poly1305_Update(POLY1305_ctx(actx), zero,
|
||||||
|
- POLY1305_BLOCK_SIZE - rem);
|
||||||
|
+ if (!actx->draft) {
|
||||||
|
+ if ((rem = (size_t)actx->len.text % POLY1305_BLOCK_SIZE))
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), zero,
|
||||||
|
+ POLY1305_BLOCK_SIZE - rem);
|
||||||
|
|
||||||
|
- if (is_endian.little) {
|
||||||
|
- Poly1305_Update(POLY1305_ctx(actx),
|
||||||
|
- (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
|
||||||
|
- } else {
|
||||||
|
- temp[0] = (unsigned char)(actx->len.aad);
|
||||||
|
- temp[1] = (unsigned char)(actx->len.aad>>8);
|
||||||
|
- temp[2] = (unsigned char)(actx->len.aad>>16);
|
||||||
|
- temp[3] = (unsigned char)(actx->len.aad>>24);
|
||||||
|
- temp[4] = (unsigned char)(actx->len.aad>>32);
|
||||||
|
- temp[5] = (unsigned char)(actx->len.aad>>40);
|
||||||
|
- temp[6] = (unsigned char)(actx->len.aad>>48);
|
||||||
|
- temp[7] = (unsigned char)(actx->len.aad>>56);
|
||||||
|
-
|
||||||
|
- temp[8] = (unsigned char)(actx->len.text);
|
||||||
|
- temp[9] = (unsigned char)(actx->len.text>>8);
|
||||||
|
- temp[10] = (unsigned char)(actx->len.text>>16);
|
||||||
|
- temp[11] = (unsigned char)(actx->len.text>>24);
|
||||||
|
- temp[12] = (unsigned char)(actx->len.text>>32);
|
||||||
|
- temp[13] = (unsigned char)(actx->len.text>>40);
|
||||||
|
- temp[14] = (unsigned char)(actx->len.text>>48);
|
||||||
|
- temp[15] = (unsigned char)(actx->len.text>>56);
|
||||||
|
-
|
||||||
|
- Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
|
||||||
|
+ if (is_endian.little) {
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx),
|
||||||
|
+ (unsigned char *)&actx->len, POLY1305_BLOCK_SIZE);
|
||||||
|
+ } else {
|
||||||
|
+ temp[0] = (unsigned char)(actx->len.aad);
|
||||||
|
+ temp[1] = (unsigned char)(actx->len.aad>>8);
|
||||||
|
+ temp[2] = (unsigned char)(actx->len.aad>>16);
|
||||||
|
+ temp[3] = (unsigned char)(actx->len.aad>>24);
|
||||||
|
+ temp[4] = (unsigned char)(actx->len.aad>>32);
|
||||||
|
+ temp[5] = (unsigned char)(actx->len.aad>>40);
|
||||||
|
+ temp[6] = (unsigned char)(actx->len.aad>>48);
|
||||||
|
+ temp[7] = (unsigned char)(actx->len.aad>>56);
|
||||||
|
+
|
||||||
|
+ temp[8] = (unsigned char)(actx->len.text);
|
||||||
|
+ temp[9] = (unsigned char)(actx->len.text>>8);
|
||||||
|
+ temp[10] = (unsigned char)(actx->len.text>>16);
|
||||||
|
+ temp[11] = (unsigned char)(actx->len.text>>24);
|
||||||
|
+ temp[12] = (unsigned char)(actx->len.text>>32);
|
||||||
|
+ temp[13] = (unsigned char)(actx->len.text>>40);
|
||||||
|
+ temp[14] = (unsigned char)(actx->len.text>>48);
|
||||||
|
+ temp[15] = (unsigned char)(actx->len.text>>56);
|
||||||
|
+
|
||||||
|
+ Poly1305_Update(POLY1305_ctx(actx), temp, POLY1305_BLOCK_SIZE);
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
Poly1305_Final(POLY1305_ctx(actx), ctx->encrypt ? actx->tag
|
||||||
|
: temp);
|
||||||
|
@@ -535,12 +576,14 @@ static int chacha20_poly1305_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg,
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case EVP_CTRL_AEAD_SET_IVLEN:
|
||||||
|
+ if (actx->draft) return -1;
|
||||||
|
if (arg <= 0 || arg > CHACHA20_POLY1305_MAX_IVLEN)
|
||||||
|
return 0;
|
||||||
|
actx->nonce_len = arg;
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
case EVP_CTRL_AEAD_SET_IV_FIXED:
|
||||||
|
+ if (actx->draft) return -1;
|
||||||
|
if (arg != 12)
|
||||||
|
return 0;
|
||||||
|
actx->nonce[0] = actx->key.counter[1]
|
||||||
|
@@ -624,9 +667,32 @@ static EVP_CIPHER chacha20_poly1305 = {
|
||||||
|
NULL /* app_data */
|
||||||
|
};
|
||||||
|
|
||||||
|
+static EVP_CIPHER chacha20_poly1305_draft = {
|
||||||
|
+ NID_chacha20_poly1305_draft,
|
||||||
|
+ 1, /* block_size */
|
||||||
|
+ CHACHA_KEY_SIZE, /* key_len */
|
||||||
|
+ 0, /* iv_len, none */
|
||||||
|
+ EVP_CIPH_FLAG_AEAD_CIPHER | EVP_CIPH_CUSTOM_IV |
|
||||||
|
+ EVP_CIPH_ALWAYS_CALL_INIT | EVP_CIPH_CTRL_INIT |
|
||||||
|
+ EVP_CIPH_CUSTOM_COPY | EVP_CIPH_FLAG_CUSTOM_CIPHER,
|
||||||
|
+ chacha20_poly1305_draft_init_key,
|
||||||
|
+ chacha20_poly1305_cipher,
|
||||||
|
+ chacha20_poly1305_cleanup,
|
||||||
|
+ 0, /* 0 moves context-specific structure allocation to ctrl */
|
||||||
|
+ NULL, /* set_asn1_parameters */
|
||||||
|
+ NULL, /* get_asn1_parameters */
|
||||||
|
+ chacha20_poly1305_ctrl,
|
||||||
|
+ NULL /* app_data */
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
const EVP_CIPHER *EVP_chacha20_poly1305(void)
|
||||||
|
{
|
||||||
|
return(&chacha20_poly1305);
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+const EVP_CIPHER *EVP_chacha20_poly1305_draft(void)
|
||||||
|
+{
|
||||||
|
+ return(&chacha20_poly1305_draft);
|
||||||
|
+}
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
diff --git a/crypto/objects/obj_dat.h b/crypto/objects/obj_dat.h
|
||||||
|
index ea91db660b..f2479dcfb8 100644
|
||||||
|
--- a/crypto/objects/obj_dat.h
|
||||||
|
+++ b/crypto/objects/obj_dat.h
|
||||||
|
@@ -1078,7 +1078,7 @@ static const unsigned char so[7762] = {
|
||||||
|
0x2A,0x86,0x48,0x86,0xF7,0x0D,0x02,0x0D, /* [ 7753] OBJ_hmacWithSHA512_256 */
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define NUM_NID 1195
|
||||||
|
+#define NUM_NID 1196
|
||||||
|
static const ASN1_OBJECT nid_objs[NUM_NID] = {
|
||||||
|
{"UNDEF", "undefined", NID_undef},
|
||||||
|
{"rsadsi", "RSA Data Security, Inc.", NID_rsadsi, 6, &so[0]},
|
||||||
|
@@ -2275,9 +2275,10 @@ static const ASN1_OBJECT nid_objs[NUM_NID] = {
|
||||||
|
{"magma-mac", "magma-mac", NID_magma_mac},
|
||||||
|
{"hmacWithSHA512-224", "hmacWithSHA512-224", NID_hmacWithSHA512_224, 8, &so[7745]},
|
||||||
|
{"hmacWithSHA512-256", "hmacWithSHA512-256", NID_hmacWithSHA512_256, 8, &so[7753]},
|
||||||
|
+ {"ChaCha20-Poly1305-D", "chacha20-poly1305-draft", NID_chacha20_poly1305_draft},
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define NUM_SN 1186
|
||||||
|
+#define NUM_SN 1187
|
||||||
|
static const unsigned int sn_objs[NUM_SN] = {
|
||||||
|
364, /* "AD_DVCS" */
|
||||||
|
419, /* "AES-128-CBC" */
|
||||||
|
@@ -2395,6 +2396,7 @@ static const unsigned int sn_objs[NUM_SN] = {
|
||||||
|
417, /* "CSPName" */
|
||||||
|
1019, /* "ChaCha20" */
|
||||||
|
1018, /* "ChaCha20-Poly1305" */
|
||||||
|
+ 1195, /* "ChaCha20-Poly1305-D" */
|
||||||
|
367, /* "CrlID" */
|
||||||
|
391, /* "DC" */
|
||||||
|
31, /* "DES-CBC" */
|
||||||
|
@@ -3467,7 +3469,7 @@ static const unsigned int sn_objs[NUM_SN] = {
|
||||||
|
1093, /* "x509ExtAdmission" */
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define NUM_LN 1186
|
||||||
|
+#define NUM_LN 1187
|
||||||
|
static const unsigned int ln_objs[NUM_LN] = {
|
||||||
|
363, /* "AD Time Stamping" */
|
||||||
|
405, /* "ANSI X9.62" */
|
||||||
|
@@ -3846,6 +3848,7 @@ static const unsigned int ln_objs[NUM_LN] = {
|
||||||
|
883, /* "certificateRevocationList" */
|
||||||
|
1019, /* "chacha20" */
|
||||||
|
1018, /* "chacha20-poly1305" */
|
||||||
|
+ 1195, /* "chacha20-poly1305-draft" */
|
||||||
|
54, /* "challengePassword" */
|
||||||
|
407, /* "characteristic-two-field" */
|
||||||
|
395, /* "clearance" */
|
||||||
|
diff --git a/crypto/objects/obj_mac.num b/crypto/objects/obj_mac.num
|
||||||
|
index 1b6a9c61a1..c81ca25a53 100644
|
||||||
|
--- a/crypto/objects/obj_mac.num
|
||||||
|
+++ b/crypto/objects/obj_mac.num
|
||||||
|
@@ -1192,3 +1192,4 @@ magma_cfb 1191
|
||||||
|
magma_mac 1192
|
||||||
|
hmacWithSHA512_224 1193
|
||||||
|
hmacWithSHA512_256 1194
|
||||||
|
+chacha20_poly1305_draft 1195
|
||||||
|
diff --git a/crypto/objects/objects.txt b/crypto/objects/objects.txt
|
||||||
|
index 5b2bb54eb9..b6523a6993 100644
|
||||||
|
--- a/crypto/objects/objects.txt
|
||||||
|
+++ b/crypto/objects/objects.txt
|
||||||
|
@@ -1534,6 +1534,7 @@ sm-scheme 104 7 : SM4-CTR : sm4-ctr
|
||||||
|
: AES-192-CBC-HMAC-SHA256 : aes-192-cbc-hmac-sha256
|
||||||
|
: AES-256-CBC-HMAC-SHA256 : aes-256-cbc-hmac-sha256
|
||||||
|
: ChaCha20-Poly1305 : chacha20-poly1305
|
||||||
|
+ : ChaCha20-Poly1305-D : chacha20-poly1305-draft
|
||||||
|
: ChaCha20 : chacha20
|
||||||
|
|
||||||
|
ISO-US 10046 2 1 : dhpublicnumber : X9.42 DH
|
||||||
|
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
|
||||||
|
index dd1117d0fe..accc766b3b 100644
|
||||||
|
--- a/include/openssl/evp.h
|
||||||
|
+++ b/include/openssl/evp.h
|
||||||
|
@@ -915,6 +915,7 @@ const EVP_CIPHER *EVP_camellia_256_ctr(void);
|
||||||
|
const EVP_CIPHER *EVP_chacha20(void);
|
||||||
|
# ifndef OPENSSL_NO_POLY1305
|
||||||
|
const EVP_CIPHER *EVP_chacha20_poly1305(void);
|
||||||
|
+const EVP_CIPHER *EVP_chacha20_poly1305_draft(void);
|
||||||
|
# endif
|
||||||
|
# endif
|
||||||
|
|
||||||
|
diff --git a/include/openssl/obj_mac.h b/include/openssl/obj_mac.h
|
||||||
|
index 47dafe48d0..18805c7562 100644
|
||||||
|
--- a/include/openssl/obj_mac.h
|
||||||
|
+++ b/include/openssl/obj_mac.h
|
||||||
|
@@ -4807,6 +4807,10 @@
|
||||||
|
#define LN_chacha20_poly1305 "chacha20-poly1305"
|
||||||
|
#define NID_chacha20_poly1305 1018
|
||||||
|
|
||||||
|
+#define SN_chacha20_poly1305_draft "ChaCha20-Poly1305-D"
|
||||||
|
+#define LN_chacha20_poly1305_draft "chacha20-poly1305-draft"
|
||||||
|
+#define NID_chacha20_poly1305_draft 1195
|
||||||
|
+
|
||||||
|
#define SN_chacha20 "ChaCha20"
|
||||||
|
#define LN_chacha20 "chacha20"
|
||||||
|
#define NID_chacha20 1019
|
||||||
|
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
|
||||||
|
index 6724ccf2d2..0365760200 100644
|
||||||
|
--- a/include/openssl/ssl.h
|
||||||
|
+++ b/include/openssl/ssl.h
|
||||||
|
@@ -125,6 +125,7 @@ extern "C" {
|
||||||
|
# define SSL_TXT_CAMELLIA256 "CAMELLIA256"
|
||||||
|
# define SSL_TXT_CAMELLIA "CAMELLIA"
|
||||||
|
# define SSL_TXT_CHACHA20 "CHACHA20"
|
||||||
|
+# define SSL_TXT_CHACHA20_D "CHACHA20-D"
|
||||||
|
# define SSL_TXT_GOST "GOST89"
|
||||||
|
# define SSL_TXT_ARIA "ARIA"
|
||||||
|
# define SSL_TXT_ARIA_GCM "ARIAGCM"
|
||||||
|
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
|
||||||
|
index e13b5dd4bc..53d43c121e 100644
|
||||||
|
--- a/include/openssl/tls1.h
|
||||||
|
+++ b/include/openssl/tls1.h
|
||||||
|
@@ -597,7 +597,12 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
|
||||||
|
# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 0x0300C09A
|
||||||
|
# define TLS1_CK_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 0x0300C09B
|
||||||
|
|
||||||
|
-/* draft-ietf-tls-chacha20-poly1305-03 */
|
||||||
|
+/* Chacha20-Poly1305-Draft ciphersuites from draft-agl-tls-chacha20poly1305-04 */
|
||||||
|
+# define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_D 0x0300CC13
|
||||||
|
+# define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_D 0x0300CC14
|
||||||
|
+# define TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305_D 0x0300CC15
|
||||||
|
+
|
||||||
|
+/* Chacha20-Poly1305 ciphersuites from RFC7905 */
|
||||||
|
# define TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCA8
|
||||||
|
# define TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 0x0300CCA9
|
||||||
|
# define TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305 0x0300CCAA
|
||||||
|
@@ -762,6 +767,9 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
|
||||||
|
# define TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305 "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
# define TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
# define TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
+# define TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305_D "OLD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
+# define TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305_D "OLD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
+# define TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_D "OLD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
# define TLS1_RFC_PSK_WITH_CHACHA20_POLY1305 "TLS_PSK_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
# define TLS1_RFC_ECDHE_PSK_WITH_CHACHA20_POLY1305 "TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
# define TLS1_RFC_DHE_PSK_WITH_CHACHA20_POLY1305 "TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256"
|
||||||
|
@@ -1090,7 +1098,12 @@ __owur int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain)
|
||||||
|
# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 "ECDH-RSA-CAMELLIA128-SHA256"
|
||||||
|
# define TLS1_TXT_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 "ECDH-RSA-CAMELLIA256-SHA384"
|
||||||
|
|
||||||
|
-/* draft-ietf-tls-chacha20-poly1305-03 */
|
||||||
|
+/* Chacha20-Poly1305-Draft ciphersuites from draft-agl-tls-chacha20poly1305-04 */
|
||||||
|
+# define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_D "ECDHE-RSA-CHACHA20-POLY1305-OLD"
|
||||||
|
+# define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_D "ECDHE-ECDSA-CHACHA20-POLY1305-OLD"
|
||||||
|
+# define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305_D "DHE-RSA-CHACHA20-POLY1305-OLD"
|
||||||
|
+
|
||||||
|
+/* Chacha20-Poly1305 ciphersuites from RFC7905 */
|
||||||
|
# define TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305 "ECDHE-RSA-CHACHA20-POLY1305"
|
||||||
|
# define TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305 "ECDHE-ECDSA-CHACHA20-POLY1305"
|
||||||
|
# define TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305 "DHE-RSA-CHACHA20-POLY1305"
|
||||||
|
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
|
||||||
|
index d7dbf99954..ee3293b5ce 100644
|
||||||
|
--- a/ssl/s3_lib.c
|
||||||
|
+++ b/ssl/s3_lib.c
|
||||||
|
@@ -2082,6 +2082,54 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
256,
|
||||||
|
256,
|
||||||
|
},
|
||||||
|
+ {
|
||||||
|
+ 1,
|
||||||
|
+ TLS1_TXT_DHE_RSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ TLS1_RFC_DHE_RSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ TLS1_CK_DHE_RSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ SSL_kDHE,
|
||||||
|
+ SSL_aRSA,
|
||||||
|
+ SSL_CHACHA20POLY1305_D,
|
||||||
|
+ SSL_AEAD,
|
||||||
|
+ TLS1_2_VERSION, TLS1_2_VERSION,
|
||||||
|
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
|
||||||
|
+ SSL_HIGH,
|
||||||
|
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
|
||||||
|
+ 256,
|
||||||
|
+ 256,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 1,
|
||||||
|
+ TLS1_TXT_ECDHE_RSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ TLS1_RFC_ECDHE_RSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ TLS1_CK_ECDHE_RSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ SSL_kECDHE,
|
||||||
|
+ SSL_aRSA,
|
||||||
|
+ SSL_CHACHA20POLY1305_D,
|
||||||
|
+ SSL_AEAD,
|
||||||
|
+ TLS1_2_VERSION, TLS1_2_VERSION,
|
||||||
|
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
|
||||||
|
+ SSL_HIGH,
|
||||||
|
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
|
||||||
|
+ 256,
|
||||||
|
+ 256,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ 1,
|
||||||
|
+ TLS1_TXT_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ TLS1_RFC_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ TLS1_CK_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_D,
|
||||||
|
+ SSL_kECDHE,
|
||||||
|
+ SSL_aECDSA,
|
||||||
|
+ SSL_CHACHA20POLY1305_D,
|
||||||
|
+ SSL_AEAD,
|
||||||
|
+ TLS1_2_VERSION, TLS1_2_VERSION,
|
||||||
|
+ DTLS1_2_VERSION, DTLS1_2_VERSION,
|
||||||
|
+ SSL_HIGH,
|
||||||
|
+ SSL_HANDSHAKE_MAC_SHA256 | TLS1_PRF_SHA256,
|
||||||
|
+ 256,
|
||||||
|
+ 256,
|
||||||
|
+ },
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
TLS1_TXT_PSK_WITH_CHACHA20_POLY1305,
|
||||||
|
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
|
||||||
|
index b60d67aa0d..ce750c4425 100644
|
||||||
|
--- a/ssl/ssl_ciph.c
|
||||||
|
+++ b/ssl/ssl_ciph.c
|
||||||
|
@@ -43,7 +43,8 @@
|
||||||
|
#define SSL_ENC_CHACHA_IDX 19
|
||||||
|
#define SSL_ENC_ARIA128GCM_IDX 20
|
||||||
|
#define SSL_ENC_ARIA256GCM_IDX 21
|
||||||
|
-#define SSL_ENC_NUM_IDX 22
|
||||||
|
+#define SSL_ENC_CHACHA20_D_IDX 22
|
||||||
|
+#define SSL_ENC_NUM_IDX 23
|
||||||
|
|
||||||
|
/* NB: make sure indices in these tables match values above */
|
||||||
|
|
||||||
|
@@ -76,6 +77,7 @@ static const ssl_cipher_table ssl_cipher_table_cipher[SSL_ENC_NUM_IDX] = {
|
||||||
|
{SSL_CHACHA20POLY1305, NID_chacha20_poly1305}, /* SSL_ENC_CHACHA_IDX 19 */
|
||||||
|
{SSL_ARIA128GCM, NID_aria_128_gcm}, /* SSL_ENC_ARIA128GCM_IDX 20 */
|
||||||
|
{SSL_ARIA256GCM, NID_aria_256_gcm}, /* SSL_ENC_ARIA256GCM_IDX 21 */
|
||||||
|
+ {SSL_CHACHA20POLY1305_D, NID_chacha20_poly1305_draft}, /* SSL_ENC_CHACHA20POLY1305_IDX 22 */
|
||||||
|
};
|
||||||
|
|
||||||
|
static const EVP_CIPHER *ssl_cipher_methods[SSL_ENC_NUM_IDX];
|
||||||
|
@@ -275,6 +277,7 @@ static const SSL_CIPHER cipher_aliases[] = {
|
||||||
|
{0, SSL_TXT_CAMELLIA256, NULL, 0, 0, 0, SSL_CAMELLIA256},
|
||||||
|
{0, SSL_TXT_CAMELLIA, NULL, 0, 0, 0, SSL_CAMELLIA},
|
||||||
|
{0, SSL_TXT_CHACHA20, NULL, 0, 0, 0, SSL_CHACHA20},
|
||||||
|
+ {0, SSL_TXT_CHACHA20_D, NULL, 0, 0, 0, SSL_CHACHA20POLY1305_D},
|
||||||
|
|
||||||
|
{0, SSL_TXT_ARIA, NULL, 0, 0, 0, SSL_ARIA},
|
||||||
|
{0, SSL_TXT_ARIA_GCM, NULL, 0, 0, 0, SSL_ARIA128GCM | SSL_ARIA256GCM},
|
||||||
|
@@ -1791,6 +1794,9 @@ char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
|
||||||
|
case SSL_CHACHA20POLY1305:
|
||||||
|
enc = "CHACHA20/POLY1305(256)";
|
||||||
|
break;
|
||||||
|
+ case SSL_CHACHA20POLY1305_D:
|
||||||
|
+ enc = "CHACHA20/POLY1305-Draft(256)";
|
||||||
|
+ break;
|
||||||
|
default:
|
||||||
|
enc = "unknown";
|
||||||
|
break;
|
||||||
|
@@ -2115,7 +2121,7 @@ int ssl_cipher_get_overhead(const SSL_CIPHER *c, size_t *mac_overhead,
|
||||||
|
out = EVP_CCM_TLS_EXPLICIT_IV_LEN + 16;
|
||||||
|
} else if (c->algorithm_enc & (SSL_AES128CCM8 | SSL_AES256CCM8)) {
|
||||||
|
out = EVP_CCM_TLS_EXPLICIT_IV_LEN + 8;
|
||||||
|
- } else if (c->algorithm_enc & SSL_CHACHA20POLY1305) {
|
||||||
|
+ } else if (c->algorithm_enc & (SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_D)) {
|
||||||
|
out = 16;
|
||||||
|
} else if (c->algorithm_mac & SSL_AEAD) {
|
||||||
|
/* We're supposed to have handled all the AEAD modes above */
|
||||||
|
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
|
||||||
|
index fa0f6d018c..f2a95c263a 100644
|
||||||
|
--- a/ssl/ssl_local.h
|
||||||
|
+++ b/ssl/ssl_local.h
|
||||||
|
@@ -230,12 +230,13 @@
|
||||||
|
# define SSL_CHACHA20POLY1305 0x00080000U
|
||||||
|
# define SSL_ARIA128GCM 0x00100000U
|
||||||
|
# define SSL_ARIA256GCM 0x00200000U
|
||||||
|
+# define SSL_CHACHA20POLY1305_D 0x00400000U
|
||||||
|
|
||||||
|
# define SSL_AESGCM (SSL_AES128GCM | SSL_AES256GCM)
|
||||||
|
# define SSL_AESCCM (SSL_AES128CCM | SSL_AES256CCM | SSL_AES128CCM8 | SSL_AES256CCM8)
|
||||||
|
# define SSL_AES (SSL_AES128|SSL_AES256|SSL_AESGCM|SSL_AESCCM)
|
||||||
|
# define SSL_CAMELLIA (SSL_CAMELLIA128|SSL_CAMELLIA256)
|
||||||
|
-# define SSL_CHACHA20 (SSL_CHACHA20POLY1305)
|
||||||
|
+# define SSL_CHACHA20 (SSL_CHACHA20POLY1305 | SSL_CHACHA20POLY1305_D)
|
||||||
|
# define SSL_ARIAGCM (SSL_ARIA128GCM | SSL_ARIA256GCM)
|
||||||
|
# define SSL_ARIA (SSL_ARIAGCM)
|
||||||
|
|
||||||
|
diff --git a/util/libcrypto.num b/util/libcrypto.num
|
||||||
|
index bf8b803c4c..d90d510096 100644
|
||||||
|
--- a/util/libcrypto.num
|
||||||
|
+++ b/util/libcrypto.num
|
||||||
|
@@ -4582,3 +4582,4 @@ OPENSSL_INIT_set_config_file_flags 4535 1_1_1b EXIST::FUNCTION:STDIO
|
||||||
|
EVP_PKEY_get0_engine 4536 1_1_1c EXIST::FUNCTION:ENGINE
|
||||||
|
X509_get0_authority_serial 4537 1_1_1d EXIST::FUNCTION:
|
||||||
|
X509_get0_authority_issuer 4538 1_1_1d EXIST::FUNCTION:
|
||||||
|
+EVP_chacha20_poly1305_draft 4539 1_1_1d EXIST::FUNCTION:CHACHA,POLY1305
|
||||||
@@ -0,0 +1,1075 @@
|
|||||||
|
diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod
|
||||||
|
index faf9e53814..428df515f1 100644
|
||||||
|
--- a/doc/man1/ciphers.pod
|
||||||
|
+++ b/doc/man1/ciphers.pod
|
||||||
|
@@ -400,6 +400,21 @@ permissible.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
+=head1 EQUAL PREFERENCE GROUPS
|
||||||
|
+
|
||||||
|
+If configuring a server, one may also configure equal-preference groups to
|
||||||
|
+partially respect the client's preferences when
|
||||||
|
+B<SSL_OP_CIPHER_SERVER_PREFERENCE> is enabled. Ciphers in an equal-preference
|
||||||
|
+group have equal priority and use the client order. This may be used to
|
||||||
|
+enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305
|
||||||
|
+based on client preferences. An equal-preference is specified with square
|
||||||
|
+brackets, combining multiple selectors separated by |. For example:
|
||||||
|
+
|
||||||
|
+ [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]
|
||||||
|
+
|
||||||
|
+ Once an equal-preference group is used, future directives must be
|
||||||
|
+ opcode-less.
|
||||||
|
+
|
||||||
|
=head1 CIPHER SUITE NAMES
|
||||||
|
|
||||||
|
The following lists give the SSL or TLS cipher suites names from the
|
||||||
|
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
|
||||||
|
index 6724ccf2d2..81a5538977 100644
|
||||||
|
--- a/include/openssl/ssl.h
|
||||||
|
+++ b/include/openssl/ssl.h
|
||||||
|
@@ -173,12 +173,12 @@ extern "C" {
|
||||||
|
# define SSL_DEFAULT_CIPHER_LIST "ALL:!COMPLEMENTOFDEFAULT:!eNULL"
|
||||||
|
/* This is the default set of TLSv1.3 ciphersuites */
|
||||||
|
# if !defined(OPENSSL_NO_CHACHA) && !defined(OPENSSL_NO_POLY1305)
|
||||||
|
-# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
|
||||||
|
+# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_128_GCM_SHA256:" \
|
||||||
|
"TLS_CHACHA20_POLY1305_SHA256:" \
|
||||||
|
- "TLS_AES_128_GCM_SHA256"
|
||||||
|
+ "TLS_AES_256_GCM_SHA384"
|
||||||
|
# else
|
||||||
|
-# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_256_GCM_SHA384:" \
|
||||||
|
- "TLS_AES_128_GCM_SHA256"
|
||||||
|
+# define TLS_DEFAULT_CIPHERSUITES "TLS_AES_128_GCM_SHA256:" \
|
||||||
|
+ "TLS_AES_256_GCM_SHA384"
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* As of OpenSSL 1.0.0, ssl_create_cipher_list() in ssl/ssl_ciph.c always
|
||||||
|
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
|
||||||
|
index 3d6850dea3..a3ab4b925f 100644
|
||||||
|
--- a/include/openssl/sslerr.h
|
||||||
|
+++ b/include/openssl/sslerr.h
|
||||||
|
@@ -600,6 +600,8 @@ int ERR_load_SSL_strings(void);
|
||||||
|
# define SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION 209
|
||||||
|
# define SSL_R_MISSING_TMP_DH_KEY 171
|
||||||
|
# define SSL_R_MISSING_TMP_ECDH_KEY 311
|
||||||
|
+# define SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS 101
|
||||||
|
+# define SSL_R_NESTED_GROUP 108
|
||||||
|
# define SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA 293
|
||||||
|
# define SSL_R_NOT_ON_RECORD_BOUNDARY 182
|
||||||
|
# define SSL_R_NOT_REPLACING_CERTIFICATE 289
|
||||||
|
@@ -731,9 +733,11 @@ int ERR_load_SSL_strings(void);
|
||||||
|
# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239
|
||||||
|
# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242
|
||||||
|
# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
|
||||||
|
+# define SSL_R_UNEXPECTED_GROUP_CLOSE 109
|
||||||
|
# define SSL_R_UNEXPECTED_CCS_MESSAGE 262
|
||||||
|
# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178
|
||||||
|
# define SSL_R_UNEXPECTED_MESSAGE 244
|
||||||
|
+# define SSL_R_UNEXPECTED_OPERATOR_IN_GROUP 110
|
||||||
|
# define SSL_R_UNEXPECTED_RECORD 245
|
||||||
|
# define SSL_R_UNINITIALIZED 276
|
||||||
|
# define SSL_R_UNKNOWN_ALERT_TYPE 246
|
||||||
|
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
|
||||||
|
index 066bf47221..517eda6630 100644
|
||||||
|
--- a/ssl/s3_lib.c
|
||||||
|
+++ b/ssl/s3_lib.c
|
||||||
|
@@ -167,7 +167,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
SSL_aRSA,
|
||||||
|
SSL_3DES,
|
||||||
|
SSL_SHA1,
|
||||||
|
- SSL3_VERSION, TLS1_2_VERSION,
|
||||||
|
+ SSL3_VERSION, TLS1_VERSION,
|
||||||
|
DTLS1_BAD_VER, DTLS1_2_VERSION,
|
||||||
|
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
|
||||||
|
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
|
||||||
|
@@ -232,7 +232,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
SSL_aRSA,
|
||||||
|
SSL_AES128,
|
||||||
|
SSL_SHA1,
|
||||||
|
- SSL3_VERSION, TLS1_2_VERSION,
|
||||||
|
+ SSL3_VERSION, TLS1_VERSION,
|
||||||
|
DTLS1_BAD_VER, DTLS1_2_VERSION,
|
||||||
|
SSL_HIGH | SSL_FIPS,
|
||||||
|
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
|
||||||
|
@@ -296,7 +296,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
SSL_aRSA,
|
||||||
|
SSL_AES256,
|
||||||
|
SSL_SHA1,
|
||||||
|
- SSL3_VERSION, TLS1_2_VERSION,
|
||||||
|
+ SSL3_VERSION, TLS1_VERSION,
|
||||||
|
DTLS1_BAD_VER, DTLS1_2_VERSION,
|
||||||
|
SSL_HIGH | SSL_FIPS,
|
||||||
|
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
|
||||||
|
@@ -4124,6 +4124,17 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_get_cipher_preferences(SSL *s)
|
||||||
|
+{
|
||||||
|
+ if (s->cipher_list != NULL)
|
||||||
|
+ return (s->cipher_list);
|
||||||
|
+
|
||||||
|
+ if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL))
|
||||||
|
+ return (s->ctx->cipher_list);
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* ssl3_choose_cipher - choose a cipher from those offered by the client
|
||||||
|
* @s: SSL connection
|
||||||
|
@@ -4133,16 +4144,24 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
|
||||||
|
* Returns the selected cipher or NULL when no common ciphers.
|
||||||
|
*/
|
||||||
|
const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
- STACK_OF(SSL_CIPHER) *srvr)
|
||||||
|
+ struct ssl_cipher_preference_list_st
|
||||||
|
+ *server_pref)
|
||||||
|
{
|
||||||
|
const SSL_CIPHER *c, *ret = NULL;
|
||||||
|
- STACK_OF(SSL_CIPHER) *prio, *allow;
|
||||||
|
- int i, ii, ok, prefer_sha256 = 0;
|
||||||
|
+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
|
||||||
|
+ int i, ii, ok, prefer_sha256 = 0, safari_ec = 0;
|
||||||
|
unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0;
|
||||||
|
const EVP_MD *mdsha256 = EVP_sha256();
|
||||||
|
-#ifndef OPENSSL_NO_CHACHA
|
||||||
|
- STACK_OF(SSL_CIPHER) *prio_chacha = NULL;
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
+ /* in_group_flags will either be NULL, or will point to an array of
|
||||||
|
+ * bytes which indicate equal-preference groups in the |prio| stack.
|
||||||
|
+ * See the comment about |in_group_flags| in the
|
||||||
|
+ * |ssl_cipher_preference_list_st| struct. */
|
||||||
|
+ const uint8_t *in_group_flags;
|
||||||
|
+
|
||||||
|
+ /* group_min contains the minimal index so far found in a group, or -1
|
||||||
|
+ * if no such value exists yet. */
|
||||||
|
+ int group_min = -1;
|
||||||
|
|
||||||
|
/* Let's see which ciphers we can support */
|
||||||
|
|
||||||
|
@@ -4169,54 +4188,13 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* SUITE-B takes precedence over server preference and ChaCha priortiy */
|
||||||
|
- if (tls1_suiteb(s)) {
|
||||||
|
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
|
||||||
|
prio = srvr;
|
||||||
|
+ in_group_flags = server_pref->in_group_flags;
|
||||||
|
allow = clnt;
|
||||||
|
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
|
||||||
|
- prio = srvr;
|
||||||
|
- allow = clnt;
|
||||||
|
-#ifndef OPENSSL_NO_CHACHA
|
||||||
|
- /* If ChaCha20 is at the top of the client preference list,
|
||||||
|
- and there are ChaCha20 ciphers in the server list, then
|
||||||
|
- temporarily prioritize all ChaCha20 ciphers in the servers list. */
|
||||||
|
- if (s->options & SSL_OP_PRIORITIZE_CHACHA && sk_SSL_CIPHER_num(clnt) > 0) {
|
||||||
|
- c = sk_SSL_CIPHER_value(clnt, 0);
|
||||||
|
- if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
|
||||||
|
- /* ChaCha20 is client preferred, check server... */
|
||||||
|
- int num = sk_SSL_CIPHER_num(srvr);
|
||||||
|
- int found = 0;
|
||||||
|
- for (i = 0; i < num; i++) {
|
||||||
|
- c = sk_SSL_CIPHER_value(srvr, i);
|
||||||
|
- if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
|
||||||
|
- found = 1;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (found) {
|
||||||
|
- prio_chacha = sk_SSL_CIPHER_new_reserve(NULL, num);
|
||||||
|
- /* if reserve fails, then there's likely a memory issue */
|
||||||
|
- if (prio_chacha != NULL) {
|
||||||
|
- /* Put all ChaCha20 at the top, starting with the one we just found */
|
||||||
|
- sk_SSL_CIPHER_push(prio_chacha, c);
|
||||||
|
- for (i++; i < num; i++) {
|
||||||
|
- c = sk_SSL_CIPHER_value(srvr, i);
|
||||||
|
- if (c->algorithm_enc == SSL_CHACHA20POLY1305)
|
||||||
|
- sk_SSL_CIPHER_push(prio_chacha, c);
|
||||||
|
- }
|
||||||
|
- /* Pull in the rest */
|
||||||
|
- for (i = 0; i < num; i++) {
|
||||||
|
- c = sk_SSL_CIPHER_value(srvr, i);
|
||||||
|
- if (c->algorithm_enc != SSL_CHACHA20POLY1305)
|
||||||
|
- sk_SSL_CIPHER_push(prio_chacha, c);
|
||||||
|
- }
|
||||||
|
- prio = prio_chacha;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-# endif
|
||||||
|
} else {
|
||||||
|
prio = clnt;
|
||||||
|
+ in_group_flags = NULL;
|
||||||
|
allow = srvr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -4247,14 +4225,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
|
||||||
|
c = sk_SSL_CIPHER_value(prio, i);
|
||||||
|
|
||||||
|
+ ok = 1;
|
||||||
|
+
|
||||||
|
/* Skip ciphers not supported by the protocol version */
|
||||||
|
if (!SSL_IS_DTLS(s) &&
|
||||||
|
((s->version < c->min_tls) || (s->version > c->max_tls)))
|
||||||
|
- continue;
|
||||||
|
+ ok = 0;
|
||||||
|
if (SSL_IS_DTLS(s) &&
|
||||||
|
(DTLS_VERSION_LT(s->version, c->min_dtls) ||
|
||||||
|
DTLS_VERSION_GT(s->version, c->max_dtls)))
|
||||||
|
- continue;
|
||||||
|
+ ok = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since TLS 1.3 ciphersuites can be used with any auth or
|
||||||
|
@@ -4276,10 +4256,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
#ifndef OPENSSL_NO_PSK
|
||||||
|
/* with PSK there must be server callback set */
|
||||||
|
if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
|
||||||
|
- continue;
|
||||||
|
+ ok = 0;
|
||||||
|
#endif /* OPENSSL_NO_PSK */
|
||||||
|
|
||||||
|
- ok = (alg_k & mask_k) && (alg_a & mask_a);
|
||||||
|
+ ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
|
||||||
|
#ifdef CIPHER_DEBUG
|
||||||
|
fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
|
||||||
|
alg_a, mask_k, mask_a, (void *)c, c->name);
|
||||||
|
@@ -4296,6 +4276,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
continue;
|
||||||
|
+
|
||||||
|
+ safari_ec = 0;
|
||||||
|
+#if !defined(OPENSSL_NO_EC)
|
||||||
|
+ if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)) {
|
||||||
|
+ if (s->s3->is_probably_safari)
|
||||||
|
+ safari_ec = 1;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
ii = sk_SSL_CIPHER_find(allow, c);
|
||||||
|
if (ii >= 0) {
|
||||||
|
@@ -4303,14 +4291,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
|
||||||
|
c->strength_bits, 0, (void *)c))
|
||||||
|
continue;
|
||||||
|
-#if !defined(OPENSSL_NO_EC)
|
||||||
|
- if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
|
||||||
|
- && s->s3->is_probably_safari) {
|
||||||
|
- if (!ret)
|
||||||
|
- ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
if (prefer_sha256) {
|
||||||
|
const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
|
||||||
|
@@ -4322,13 +4303,38 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
ret = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
+
|
||||||
|
+ if (in_group_flags != NULL && in_group_flags[i] == 1) {
|
||||||
|
+ /* This element of |prio| is in a group. Update
|
||||||
|
+ * the minimum index found so far and continue
|
||||||
|
+ * looking. */
|
||||||
|
+ if (group_min == -1 || group_min > ii)
|
||||||
|
+ group_min = ii;
|
||||||
|
+ } else {
|
||||||
|
+ if (group_min != -1 && group_min < ii)
|
||||||
|
+ ii = group_min;
|
||||||
|
+ if (safari_ec) {
|
||||||
|
+ if (!ret)
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (in_group_flags != NULL && !in_group_flags[i] && group_min != -1) {
|
||||||
|
+ /* We are about to leave a group, but we found a match
|
||||||
|
+ * in it, so that's our answer. */
|
||||||
|
+ if (safari_ec) {
|
||||||
|
+ if (!ret)
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, group_min);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, group_min);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-#ifndef OPENSSL_NO_CHACHA
|
||||||
|
- sk_SSL_CIPHER_free(prio_chacha);
|
||||||
|
-#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
|
||||||
|
index 27a1b2ec68..9880a0b363 100644
|
||||||
|
--- a/ssl/ssl_ciph.c
|
||||||
|
+++ b/ssl/ssl_ciph.c
|
||||||
|
@@ -192,6 +192,7 @@ typedef struct cipher_order_st {
|
||||||
|
const SSL_CIPHER *cipher;
|
||||||
|
int active;
|
||||||
|
int dead;
|
||||||
|
+ int in_group;
|
||||||
|
struct cipher_order_st *next, *prev;
|
||||||
|
} CIPHER_ORDER;
|
||||||
|
|
||||||
|
@@ -681,6 +682,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
|
||||||
|
co_list[co_list_num].next = NULL;
|
||||||
|
co_list[co_list_num].prev = NULL;
|
||||||
|
co_list[co_list_num].active = 0;
|
||||||
|
+ co_list[co_list_num].in_group = 0;
|
||||||
|
co_list_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -774,8 +776,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
uint32_t alg_auth, uint32_t alg_enc,
|
||||||
|
uint32_t alg_mac, int min_tls,
|
||||||
|
uint32_t algo_strength, int rule,
|
||||||
|
- int32_t strength_bits, CIPHER_ORDER **head_p,
|
||||||
|
- CIPHER_ORDER **tail_p)
|
||||||
|
+ int32_t strength_bits, int in_group,
|
||||||
|
+ CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
|
||||||
|
{
|
||||||
|
CIPHER_ORDER *head, *tail, *curr, *next, *last;
|
||||||
|
const SSL_CIPHER *cp;
|
||||||
|
@@ -783,9 +785,9 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
|
||||||
|
#ifdef CIPHER_DEBUG
|
||||||
|
fprintf(stderr,
|
||||||
|
- "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
|
||||||
|
+ "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d) g:%d\n",
|
||||||
|
rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
|
||||||
|
- algo_strength, strength_bits);
|
||||||
|
+ algo_strength, strength_bits, in_group);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
|
||||||
|
@@ -862,6 +864,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
if (!curr->active) {
|
||||||
|
ll_append_tail(&head, curr, &tail);
|
||||||
|
curr->active = 1;
|
||||||
|
+ curr->in_group = in_group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Move the added cipher to this location */
|
||||||
|
@@ -869,6 +872,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
/* reverse == 0 */
|
||||||
|
if (curr->active) {
|
||||||
|
ll_append_tail(&head, curr, &tail);
|
||||||
|
+ curr->in_group = 0;
|
||||||
|
}
|
||||||
|
} else if (rule == CIPHER_DEL) {
|
||||||
|
/* reverse == 1 */
|
||||||
|
@@ -880,6 +884,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
*/
|
||||||
|
ll_append_head(&head, curr, &tail);
|
||||||
|
curr->active = 0;
|
||||||
|
+ curr->in_group = 0;
|
||||||
|
}
|
||||||
|
} else if (rule == CIPHER_BUMP) {
|
||||||
|
if (curr->active)
|
||||||
|
@@ -947,8 +952,8 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
|
||||||
|
*/
|
||||||
|
for (i = max_strength_bits; i >= 0; i--)
|
||||||
|
if (number_uses[i] > 0)
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p,
|
||||||
|
- tail_p);
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0,
|
||||||
|
+ head_p, tail_p);
|
||||||
|
|
||||||
|
OPENSSL_free(number_uses);
|
||||||
|
return 1;
|
||||||
|
@@ -962,7 +967,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
|
||||||
|
int min_tls;
|
||||||
|
const char *l, *buf;
|
||||||
|
- int j, multi, found, rule, retval, ok, buflen;
|
||||||
|
+ int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0;
|
||||||
|
uint32_t cipher_id = 0;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
@@ -973,18 +978,66 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
|
||||||
|
if (ch == '\0')
|
||||||
|
break; /* done */
|
||||||
|
- if (ch == '-') {
|
||||||
|
+ if (in_group) {
|
||||||
|
+ if (ch == ']') {
|
||||||
|
+ if (!in_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_UNEXPECTED_GROUP_CLOSE);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (*tail_p)
|
||||||
|
+ (*tail_p)->in_group = 0;
|
||||||
|
+ in_group = 0;
|
||||||
|
+ l++;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (ch == '|') {
|
||||||
|
+ rule = CIPHER_ADD;
|
||||||
|
+ l++;
|
||||||
|
+ continue;
|
||||||
|
+ } else if (!(ch >= 'a' && ch <= 'z')
|
||||||
|
+ && !(ch >= 'A' && ch <= 'Z')
|
||||||
|
+ && !(ch >= '0' && ch <= '9')) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
+ } else {
|
||||||
|
+ rule = CIPHER_ADD;
|
||||||
|
+ }
|
||||||
|
+ } else if (ch == '-') {
|
||||||
|
rule = CIPHER_DEL;
|
||||||
|
l++;
|
||||||
|
} else if (ch == '+') {
|
||||||
|
rule = CIPHER_ORD;
|
||||||
|
l++;
|
||||||
|
+ } else if (ch == '!' && has_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
} else if (ch == '!') {
|
||||||
|
rule = CIPHER_KILL;
|
||||||
|
l++;
|
||||||
|
+ } else if (ch == '@' && has_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
} else if (ch == '@') {
|
||||||
|
rule = CIPHER_SPECIAL;
|
||||||
|
l++;
|
||||||
|
+ } else if (ch == '[') {
|
||||||
|
+ if (in_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_NESTED_GROUP);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ in_group = 1;
|
||||||
|
+ has_group = 1;
|
||||||
|
+ l++;
|
||||||
|
+ continue;
|
||||||
|
} else {
|
||||||
|
rule = CIPHER_ADD;
|
||||||
|
}
|
||||||
|
@@ -1026,7 +1079,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
* alphanumeric, so we call this an error.
|
||||||
|
*/
|
||||||
|
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
|
||||||
|
- retval = found = 0;
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
l++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -1205,8 +1258,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
} else if (found) {
|
||||||
|
ssl_cipher_apply_rule(cipher_id,
|
||||||
|
alg_mkey, alg_auth, alg_enc, alg_mac,
|
||||||
|
- min_tls, algo_strength, rule, -1, head_p,
|
||||||
|
- tail_p);
|
||||||
|
+ min_tls, algo_strength, rule, -1, in_group,
|
||||||
|
+ head_p, tail_p);
|
||||||
|
} else {
|
||||||
|
while ((*l != '\0') && !ITEM_SEP(*l))
|
||||||
|
l++;
|
||||||
|
@@ -1215,6 +1268,11 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
break; /* done */
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (in_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
|
||||||
|
+ retval = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1378,7 +1436,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
|
||||||
|
int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str);
|
||||||
|
|
||||||
|
if (ret && ctx->cipher_list != NULL)
|
||||||
|
- return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id,
|
||||||
|
+ return update_cipher_list(&ctx->cipher_list->ciphers, &ctx->cipher_list_by_id,
|
||||||
|
ctx->tls13_ciphersuites);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
@@ -1391,10 +1449,10 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
|
||||||
|
|
||||||
|
if (s->cipher_list == NULL) {
|
||||||
|
if ((cipher_list = SSL_get_ciphers(s)) != NULL)
|
||||||
|
- s->cipher_list = sk_SSL_CIPHER_dup(cipher_list);
|
||||||
|
+ s->cipher_list->ciphers = sk_SSL_CIPHER_dup(cipher_list);
|
||||||
|
}
|
||||||
|
if (ret && s->cipher_list != NULL)
|
||||||
|
- return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id,
|
||||||
|
+ return update_cipher_list(&s->cipher_list->ciphers, &s->cipher_list_by_id,
|
||||||
|
s->tls13_ciphersuites);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
@@ -1402,17 +1460,20 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
|
||||||
|
|
||||||
|
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
|
||||||
|
- STACK_OF(SSL_CIPHER) **cipher_list,
|
||||||
|
+ struct ssl_cipher_preference_list_st **cipher_list,
|
||||||
|
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
|
||||||
|
const char *rule_str,
|
||||||
|
CERT *c)
|
||||||
|
{
|
||||||
|
- int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i;
|
||||||
|
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i, tls13_len;
|
||||||
|
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
|
||||||
|
- STACK_OF(SSL_CIPHER) *cipherstack;
|
||||||
|
+ STACK_OF(SSL_CIPHER) *cipherstack = NULL;
|
||||||
|
const char *rule_p;
|
||||||
|
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
|
||||||
|
- const SSL_CIPHER **ca_list = NULL;
|
||||||
|
+ const SSL_CIPHER **ca_list = NULL, *tmp = NULL;
|
||||||
|
+ uint8_t *in_group_flags = NULL;
|
||||||
|
+ unsigned int num_in_group_flags = 0;
|
||||||
|
+ struct ssl_cipher_preference_list_st *pref_list = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return with error if nothing to do.
|
||||||
|
@@ -1461,16 +1522,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* preference).
|
||||||
|
*/
|
||||||
|
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
|
||||||
|
- -1, &head, &tail);
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
|
||||||
|
- &tail);
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
|
||||||
|
- &tail);
|
||||||
|
+ -1, 0, &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0,
|
||||||
|
+ &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0,
|
||||||
|
+ &head, &tail);
|
||||||
|
|
||||||
|
/* Within each strength group, we prefer GCM over CHACHA... */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1479,13 +1540,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* strength.
|
||||||
|
*/
|
||||||
|
ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
|
||||||
|
- -1, &head, &tail);
|
||||||
|
+ -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/* Temporarily enable everything else for sorting */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/* Low priority for MD5 */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1493,16 +1554,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* disabled. (For applications that allow them, they aren't too bad, but
|
||||||
|
* we prefer authenticated ciphers.)
|
||||||
|
*/
|
||||||
|
- ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
/* RC4 is sort-of broken -- move to the end */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1518,7 +1579,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
|
||||||
|
* TODO(openssl-team): is there an easier way to accomplish all this?
|
||||||
|
*/
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1534,15 +1595,15 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* Because we now bump ciphers to the top of the list, we proceed in
|
||||||
|
* reverse order of preference.
|
||||||
|
*/
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
|
||||||
|
- CIPHER_BUMP, -1, &head, &tail);
|
||||||
|
+ CIPHER_BUMP, -1, 0, &head, &tail);
|
||||||
|
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
|
||||||
|
- CIPHER_BUMP, -1, &head, &tail);
|
||||||
|
+ CIPHER_BUMP, -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/* Now disable everything (maintaining the ordering!) */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We also need cipher aliases for selecting based on the rule_str.
|
||||||
|
@@ -1556,9 +1617,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
|
||||||
|
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
|
||||||
|
if (ca_list == NULL) {
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
|
||||||
|
- return NULL; /* Failure */
|
||||||
|
+ goto err; /* Failure */
|
||||||
|
}
|
||||||
|
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
|
||||||
|
disabled_mkey, disabled_auth, disabled_enc,
|
||||||
|
@@ -1583,27 +1643,35 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
|
||||||
|
OPENSSL_free(ca_list); /* Not needed anymore */
|
||||||
|
|
||||||
|
- if (!ok) { /* Rule processing failure */
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if (!ok)
|
||||||
|
+ goto err; /* Rule processing failure */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate new "cipherstack" for the result, return with error
|
||||||
|
* if we cannot get one.
|
||||||
|
*/
|
||||||
|
- if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ in_group_flags = OPENSSL_malloc(num_of_ciphers);
|
||||||
|
+ if (!in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
|
||||||
|
/* Add TLSv1.3 ciphers first - we always prefer those if possible */
|
||||||
|
- for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
|
||||||
|
+ tls13_len = sk_SSL_CIPHER_num(tls13_ciphersuites);
|
||||||
|
+ for (i = 0; i < tls13_len; i++) {
|
||||||
|
+ tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i);
|
||||||
|
if (!sk_SSL_CIPHER_push(cipherstack,
|
||||||
|
- sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
|
||||||
|
- sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
- return NULL;
|
||||||
|
+ tmp))
|
||||||
|
+ goto err;
|
||||||
|
+ /* Temporary - AES128, CHACHA20 priority adjustment of TLS 1.3. */
|
||||||
|
+ if (tmp->algorithm_enc == SSL_AES128GCM &&
|
||||||
|
+ tls13_len > (i + 1)) {
|
||||||
|
+ tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i + 1);
|
||||||
|
+ in_group_flags[num_in_group_flags++] = (tmp->algorithm_enc == SSL_CHACHA20POLY1305) ? 1 : 0;
|
||||||
|
}
|
||||||
|
+ else
|
||||||
|
+ in_group_flags[num_in_group_flags++] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1612,26 +1680,50 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
*/
|
||||||
|
for (curr = head; curr != NULL; curr = curr->next) {
|
||||||
|
if (curr->active) {
|
||||||
|
- if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
- sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher))
|
||||||
|
+ goto err;
|
||||||
|
+ in_group_flags[num_in_group_flags++] = curr->in_group;
|
||||||
|
#ifdef CIPHER_DEBUG
|
||||||
|
fprintf(stderr, "<%s>\n", curr->cipher->name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- OPENSSL_free(co_list); /* Not needed any longer */
|
||||||
|
|
||||||
|
- if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
|
||||||
|
- sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
- sk_SSL_CIPHER_free(*cipher_list);
|
||||||
|
- *cipher_list = cipherstack;
|
||||||
|
+ OPENSSL_free(co_list); /* Not needed any longer */
|
||||||
|
+ co_list = NULL;
|
||||||
|
+
|
||||||
|
+ if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack))
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
|
||||||
|
+ if (!pref_list)
|
||||||
|
+ goto err;
|
||||||
|
+ pref_list->ciphers = cipherstack;
|
||||||
|
+ pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
|
||||||
|
+ if (!pref_list->in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
+ memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
|
||||||
|
+ OPENSSL_free(in_group_flags);
|
||||||
|
+ in_group_flags = NULL;
|
||||||
|
+ if (*cipher_list != NULL)
|
||||||
|
+ ssl_cipher_preference_list_free(*cipher_list);
|
||||||
|
+ *cipher_list = pref_list;
|
||||||
|
+ pref_list = NULL;
|
||||||
|
|
||||||
|
return cipherstack;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (co_list)
|
||||||
|
+ OPENSSL_free(co_list);
|
||||||
|
+ if (in_group_flags)
|
||||||
|
+ OPENSSL_free(in_group_flags);
|
||||||
|
+ if (cipherstack)
|
||||||
|
+ sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
+ if (pref_list && pref_list->in_group_flags)
|
||||||
|
+ OPENSSL_free(pref_list->in_group_flags);
|
||||||
|
+ if (pref_list)
|
||||||
|
+ OPENSSL_free(pref_list);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
|
||||||
|
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
|
||||||
|
index 4b12ed1485..cd1a95d1d2 100644
|
||||||
|
--- a/ssl/ssl_err.c
|
||||||
|
+++ b/ssl/ssl_err.c
|
||||||
|
@@ -965,6 +965,9 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_DH_KEY), "missing tmp dh key"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_ECDH_KEY),
|
||||||
|
"missing tmp ecdh key"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS),
|
||||||
|
+ "mixed special operator with groups"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NESTED_GROUP), "nested group"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA),
|
||||||
|
"mixed handshake and non handshake data"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_ON_RECORD_BOUNDARY),
|
||||||
|
@@ -1201,11 +1204,14 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
||||||
|
"unable to load ssl3 md5 routines"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
|
||||||
|
"unable to load ssl3 sha1 routines"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_GROUP_CLOSE), "unexpected group close"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_CCS_MESSAGE),
|
||||||
|
"unexpected ccs message"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
|
||||||
|
"unexpected end of early data"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP),
|
||||||
|
+ "unexpected operator in group"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "unexpected record"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_ALERT_TYPE), "unknown alert type"},
|
||||||
|
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
|
||||||
|
index ac820cf9fe..141308584c 100644
|
||||||
|
--- a/ssl/ssl_lib.c
|
||||||
|
+++ b/ssl/ssl_lib.c
|
||||||
|
@@ -1122,6 +1122,71 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
|
||||||
|
return X509_VERIFY_PARAM_set1(ssl->param, vpm);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void ssl_cipher_preference_list_free(struct ssl_cipher_preference_list_st
|
||||||
|
+ *cipher_list)
|
||||||
|
+{
|
||||||
|
+ sk_SSL_CIPHER_free(cipher_list->ciphers);
|
||||||
|
+ OPENSSL_free(cipher_list->in_group_flags);
|
||||||
|
+ OPENSSL_free(cipher_list);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct ssl_cipher_preference_list_st*
|
||||||
|
+ssl_cipher_preference_list_dup(struct ssl_cipher_preference_list_st
|
||||||
|
+ *cipher_list)
|
||||||
|
+{
|
||||||
|
+ struct ssl_cipher_preference_list_st* ret = NULL;
|
||||||
|
+ size_t n = sk_SSL_CIPHER_num(cipher_list->ciphers);
|
||||||
|
+
|
||||||
|
+ ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
|
||||||
|
+ if (!ret)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->ciphers = NULL;
|
||||||
|
+ ret->in_group_flags = NULL;
|
||||||
|
+ ret->ciphers = sk_SSL_CIPHER_dup(cipher_list->ciphers);
|
||||||
|
+ if (!ret->ciphers)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->in_group_flags = OPENSSL_malloc(n);
|
||||||
|
+ if (!ret->in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
+ memcpy(ret->in_group_flags, cipher_list->in_group_flags, n);
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (ret->ciphers)
|
||||||
|
+ sk_SSL_CIPHER_free(ret->ciphers);
|
||||||
|
+ if (ret)
|
||||||
|
+ OPENSSL_free(ret);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct ssl_cipher_preference_list_st*
|
||||||
|
+ssl_cipher_preference_list_from_ciphers(STACK_OF(SSL_CIPHER) *ciphers)
|
||||||
|
+{
|
||||||
|
+ struct ssl_cipher_preference_list_st* ret = NULL;
|
||||||
|
+ size_t n = sk_SSL_CIPHER_num(ciphers);
|
||||||
|
+
|
||||||
|
+ ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
|
||||||
|
+ if (!ret)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->ciphers = NULL;
|
||||||
|
+ ret->in_group_flags = NULL;
|
||||||
|
+ ret->ciphers = sk_SSL_CIPHER_dup(ciphers);
|
||||||
|
+ if (!ret->ciphers)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->in_group_flags = OPENSSL_malloc(n);
|
||||||
|
+ if (!ret->in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
+ memset(ret->in_group_flags, 0, n);
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (ret->ciphers)
|
||||||
|
+ sk_SSL_CIPHER_free(ret->ciphers);
|
||||||
|
+ if (ret)
|
||||||
|
+ OPENSSL_free(ret);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
|
||||||
|
{
|
||||||
|
return ctx->param;
|
||||||
|
@@ -1162,7 +1227,8 @@ void SSL_free(SSL *s)
|
||||||
|
BUF_MEM_free(s->init_buf);
|
||||||
|
|
||||||
|
/* add extra stuff */
|
||||||
|
- sk_SSL_CIPHER_free(s->cipher_list);
|
||||||
|
+ if (s->cipher_list != NULL)
|
||||||
|
+ ssl_cipher_preference_list_free(s->cipher_list);
|
||||||
|
sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||||
|
sk_SSL_CIPHER_free(s->tls13_ciphersuites);
|
||||||
|
sk_SSL_CIPHER_free(s->peer_ciphers);
|
||||||
|
@@ -2436,9 +2502,9 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
|
||||||
|
{
|
||||||
|
if (s != NULL) {
|
||||||
|
if (s->cipher_list != NULL) {
|
||||||
|
- return s->cipher_list;
|
||||||
|
+ return (s->cipher_list->ciphers);
|
||||||
|
} else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) {
|
||||||
|
- return s->ctx->cipher_list;
|
||||||
|
+ return (s->ctx->cipher_list->ciphers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
@@ -2512,8 +2578,8 @@ const char *SSL_get_cipher_list(const SSL *s, int n)
|
||||||
|
* preference */
|
||||||
|
STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx)
|
||||||
|
{
|
||||||
|
- if (ctx != NULL)
|
||||||
|
- return ctx->cipher_list;
|
||||||
|
+ if (ctx != NULL && ctx->cipher_list != NULL)
|
||||||
|
+ return ctx->cipher_list->ciphers;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2963,7 +3029,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
|
||||||
|
ret->tls13_ciphersuites,
|
||||||
|
&ret->cipher_list, &ret->cipher_list_by_id,
|
||||||
|
SSL_DEFAULT_CIPHER_LIST, ret->cert)
|
||||||
|
- || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
|
||||||
|
+ || sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) {
|
||||||
|
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
@@ -3139,7 +3205,7 @@ void SSL_CTX_free(SSL_CTX *a)
|
||||||
|
#ifndef OPENSSL_NO_CT
|
||||||
|
CTLOG_STORE_free(a->ctlog_store);
|
||||||
|
#endif
|
||||||
|
- sk_SSL_CIPHER_free(a->cipher_list);
|
||||||
|
+ ssl_cipher_preference_list_free(a->cipher_list);
|
||||||
|
sk_SSL_CIPHER_free(a->cipher_list_by_id);
|
||||||
|
sk_SSL_CIPHER_free(a->tls13_ciphersuites);
|
||||||
|
ssl_cert_free(a->cert);
|
||||||
|
@@ -3817,13 +3883,15 @@ SSL *SSL_dup(SSL *s)
|
||||||
|
|
||||||
|
/* dup the cipher_list and cipher_list_by_id stacks */
|
||||||
|
if (s->cipher_list != NULL) {
|
||||||
|
- if ((ret->cipher_list = sk_SSL_CIPHER_dup(s->cipher_list)) == NULL)
|
||||||
|
+ ret->cipher_list = ssl_cipher_preference_list_dup(s->cipher_list);
|
||||||
|
+ if (ret->cipher_list == NULL)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
- if (s->cipher_list_by_id != NULL)
|
||||||
|
- if ((ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id))
|
||||||
|
- == NULL)
|
||||||
|
+ if (s->cipher_list_by_id != NULL) {
|
||||||
|
+ ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id);
|
||||||
|
+ if (ret->cipher_list_by_id == NULL)
|
||||||
|
goto err;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Dup the client_CA list */
|
||||||
|
if (!dup_ca_names(&ret->ca_names, s->ca_names)
|
||||||
|
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
|
||||||
|
index 25875c9f6d..23a6093580 100644
|
||||||
|
--- a/ssl/ssl_local.h
|
||||||
|
+++ b/ssl/ssl_local.h
|
||||||
|
@@ -733,9 +733,46 @@ typedef struct ssl_ctx_ext_secure_st {
|
||||||
|
unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
|
||||||
|
} SSL_CTX_EXT_SECURE;
|
||||||
|
|
||||||
|
+/* ssl_cipher_preference_list_st contains a list of SSL_CIPHERs with
|
||||||
|
+ * equal-preference groups. For TLS clients, the groups are moot because the
|
||||||
|
+ * server picks the cipher and groups cannot be expressed on the wire. However,
|
||||||
|
+ * for servers, the equal-preference groups allow the client's preferences to
|
||||||
|
+ * be partially respected. (This only has an effect with
|
||||||
|
+ * SSL_OP_CIPHER_SERVER_PREFERENCE).
|
||||||
|
+ *
|
||||||
|
+ * The equal-preference groups are expressed by grouping SSL_CIPHERs together.
|
||||||
|
+ * All elements of a group have the same priority: no ordering is expressed
|
||||||
|
+ * within a group.
|
||||||
|
+ *
|
||||||
|
+ * The values in |ciphers| are in one-to-one correspondence with
|
||||||
|
+ * |in_group_flags|. (That is, sk_SSL_CIPHER_num(ciphers) is the number of
|
||||||
|
+ * bytes in |in_group_flags|.) The bytes in |in_group_flags| are either 1, to
|
||||||
|
+ * indicate that the corresponding SSL_CIPHER is not the last element of a
|
||||||
|
+ * group, or 0 to indicate that it is.
|
||||||
|
+ *
|
||||||
|
+ * For example, if |in_group_flags| contains all zeros then that indicates a
|
||||||
|
+ * traditional, fully-ordered preference. Every SSL_CIPHER is the last element
|
||||||
|
+ * of the group (i.e. they are all in a one-element group).
|
||||||
|
+ *
|
||||||
|
+ * For a more complex example, consider:
|
||||||
|
+ * ciphers: A B C D E F
|
||||||
|
+ * in_group_flags: 1 1 0 0 1 0
|
||||||
|
+ *
|
||||||
|
+ * That would express the following, order:
|
||||||
|
+ *
|
||||||
|
+ * A E
|
||||||
|
+ * B -> D -> F
|
||||||
|
+ * C
|
||||||
|
+ */
|
||||||
|
+struct ssl_cipher_preference_list_st {
|
||||||
|
+ STACK_OF(SSL_CIPHER) *ciphers;
|
||||||
|
+ uint8_t *in_group_flags;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
struct ssl_ctx_st {
|
||||||
|
const SSL_METHOD *method;
|
||||||
|
- STACK_OF(SSL_CIPHER) *cipher_list;
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list;
|
||||||
|
/* same as above but sorted for lookup */
|
||||||
|
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
|
||||||
|
/* TLSv1.3 specific ciphersuites */
|
||||||
|
@@ -1131,7 +1168,7 @@ struct ssl_st {
|
||||||
|
SSL_DANE dane;
|
||||||
|
/* crypto */
|
||||||
|
STACK_OF(SSL_CIPHER) *peer_ciphers;
|
||||||
|
- STACK_OF(SSL_CIPHER) *cipher_list;
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list;
|
||||||
|
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
|
||||||
|
/* TLSv1.3 specific ciphersuites */
|
||||||
|
STACK_OF(SSL_CIPHER) *tls13_ciphersuites;
|
||||||
|
@@ -2269,7 +2306,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
|
||||||
|
const SSL_CIPHER *const *bp);
|
||||||
|
__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
|
||||||
|
- STACK_OF(SSL_CIPHER) **cipher_list,
|
||||||
|
+ struct ssl_cipher_preference_list_st **cipher_list,
|
||||||
|
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
|
||||||
|
const char *rule_str,
|
||||||
|
CERT *c);
|
||||||
|
@@ -2279,6 +2316,13 @@ __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
|
||||||
|
STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
|
||||||
|
int fatal);
|
||||||
|
void ssl_update_cache(SSL *s, int mode);
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_cipher_preference_list_dup(
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list);
|
||||||
|
+void ssl_cipher_preference_list_free(
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list);
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_cipher_preference_list_from_ciphers(
|
||||||
|
+ STACK_OF(SSL_CIPHER) *ciphers);
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_get_cipher_preferences(SSL *s);
|
||||||
|
__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
|
||||||
|
const EVP_MD **md, int *mac_pkey_type,
|
||||||
|
size_t *mac_secret_size, SSL_COMP **comp,
|
||||||
|
@@ -2362,7 +2406,7 @@ __owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
|
||||||
|
CERT_PKEY *cpk);
|
||||||
|
__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
|
||||||
|
STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
- STACK_OF(SSL_CIPHER) *srvr);
|
||||||
|
+ struct ssl_cipher_preference_list_st *srvr);
|
||||||
|
__owur int ssl3_digest_cached_records(SSL *s, int keep);
|
||||||
|
__owur int ssl3_new(SSL *s);
|
||||||
|
void ssl3_free(SSL *s);
|
||||||
|
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
|
||||||
|
index 8cf9c40d15..46391a7f05 100644
|
||||||
|
--- a/ssl/statem/statem_srvr.c
|
||||||
|
+++ b/ssl/statem/statem_srvr.c
|
||||||
|
@@ -1748,7 +1748,7 @@ static int tls_early_post_process_client_hello(SSL *s)
|
||||||
|
/* For TLSv1.3 we must select the ciphersuite *before* session resumption */
|
||||||
|
if (SSL_IS_TLS13(s)) {
|
||||||
|
const SSL_CIPHER *cipher =
|
||||||
|
- ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
|
||||||
|
+ ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s));
|
||||||
|
|
||||||
|
if (cipher == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
|
@@ -1929,7 +1929,7 @@ static int tls_early_post_process_client_hello(SSL *s)
|
||||||
|
/* check if some cipher was preferred by call back */
|
||||||
|
if (pref_cipher == NULL)
|
||||||
|
pref_cipher = ssl3_choose_cipher(s, s->peer_ciphers,
|
||||||
|
- SSL_get_ciphers(s));
|
||||||
|
+ ssl_get_cipher_preferences(s));
|
||||||
|
if (pref_cipher == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
|
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||||
|
@@ -1938,8 +1938,9 @@ static int tls_early_post_process_client_hello(SSL *s)
|
||||||
|
}
|
||||||
|
|
||||||
|
s->session->cipher = pref_cipher;
|
||||||
|
- sk_SSL_CIPHER_free(s->cipher_list);
|
||||||
|
- s->cipher_list = sk_SSL_CIPHER_dup(s->peer_ciphers);
|
||||||
|
+ ssl_cipher_preference_list_free(s->cipher_list);
|
||||||
|
+ s->cipher_list = ssl_cipher_preference_list_from_ciphers(
|
||||||
|
+ s->peer_ciphers);
|
||||||
|
sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||||
|
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->peer_ciphers);
|
||||||
|
}
|
||||||
|
@@ -2251,7 +2252,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
|
||||||
|
/* In TLSv1.3 we selected the ciphersuite before resumption */
|
||||||
|
if (!SSL_IS_TLS13(s)) {
|
||||||
|
cipher =
|
||||||
|
- ssl3_choose_cipher(s, s->peer_ciphers, SSL_get_ciphers(s));
|
||||||
|
+ ssl3_choose_cipher(s, s->peer_ciphers, ssl_get_cipher_preferences(s));
|
||||||
|
|
||||||
|
if (cipher == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
@@ -0,0 +1,1110 @@
|
|||||||
|
diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod
|
||||||
|
index faf9e53814..428df515f1 100644
|
||||||
|
--- a/doc/man1/ciphers.pod
|
||||||
|
+++ b/doc/man1/ciphers.pod
|
||||||
|
@@ -400,6 +400,21 @@ permissible.
|
||||||
|
|
||||||
|
=back
|
||||||
|
|
||||||
|
+=head1 EQUAL PREFERENCE GROUPS
|
||||||
|
+
|
||||||
|
+If configuring a server, one may also configure equal-preference groups to
|
||||||
|
+partially respect the client's preferences when
|
||||||
|
+B<SSL_OP_CIPHER_SERVER_PREFERENCE> is enabled. Ciphers in an equal-preference
|
||||||
|
+group have equal priority and use the client order. This may be used to
|
||||||
|
+enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305
|
||||||
|
+based on client preferences. An equal-preference is specified with square
|
||||||
|
+brackets, combining multiple selectors separated by |. For example:
|
||||||
|
+
|
||||||
|
+ [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]
|
||||||
|
+
|
||||||
|
+ Once an equal-preference group is used, future directives must be
|
||||||
|
+ opcode-less.
|
||||||
|
+
|
||||||
|
=head1 CIPHER SUITE NAMES
|
||||||
|
|
||||||
|
The following lists give the SSL or TLS cipher suites names from the
|
||||||
|
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
|
||||||
|
index 3d6850dea3..a3ab4b925f 100644
|
||||||
|
--- a/include/openssl/sslerr.h
|
||||||
|
+++ b/include/openssl/sslerr.h
|
||||||
|
@@ -600,6 +600,8 @@ int ERR_load_SSL_strings(void);
|
||||||
|
# define SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION 209
|
||||||
|
# define SSL_R_MISSING_TMP_DH_KEY 171
|
||||||
|
# define SSL_R_MISSING_TMP_ECDH_KEY 311
|
||||||
|
+# define SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS 101
|
||||||
|
+# define SSL_R_NESTED_GROUP 108
|
||||||
|
# define SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA 293
|
||||||
|
# define SSL_R_NOT_ON_RECORD_BOUNDARY 182
|
||||||
|
# define SSL_R_NOT_REPLACING_CERTIFICATE 289
|
||||||
|
@@ -731,9 +733,11 @@ int ERR_load_SSL_strings(void);
|
||||||
|
# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239
|
||||||
|
# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242
|
||||||
|
# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
|
||||||
|
+# define SSL_R_UNEXPECTED_GROUP_CLOSE 109
|
||||||
|
# define SSL_R_UNEXPECTED_CCS_MESSAGE 262
|
||||||
|
# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178
|
||||||
|
# define SSL_R_UNEXPECTED_MESSAGE 244
|
||||||
|
+# define SSL_R_UNEXPECTED_OPERATOR_IN_GROUP 110
|
||||||
|
# define SSL_R_UNEXPECTED_RECORD 245
|
||||||
|
# define SSL_R_UNINITIALIZED 276
|
||||||
|
# define SSL_R_UNKNOWN_ALERT_TYPE 246
|
||||||
|
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
|
||||||
|
index 066bf47221..6d56b27473 100644
|
||||||
|
--- a/ssl/s3_lib.c
|
||||||
|
+++ b/ssl/s3_lib.c
|
||||||
|
@@ -31,7 +31,25 @@ const unsigned char tls12downgrade[] = {
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The list of available TLSv1.3 ciphers */
|
||||||
|
+/* Since nginx can not set the TLS 1.3 cipher, remove it temporarily. */
|
||||||
|
static SSL_CIPHER tls13_ciphers[] = {
|
||||||
|
+ {
|
||||||
|
+ 0,
|
||||||
|
+ }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * The list of available ciphers, mostly organized into the following
|
||||||
|
+ * groups:
|
||||||
|
+ * Always there
|
||||||
|
+ * EC
|
||||||
|
+ * PSK
|
||||||
|
+ * SRP (within that: RSA EC PSK)
|
||||||
|
+ * Cipher families: Chacha/poly, Camellia, Gost, IDEA, SEED
|
||||||
|
+ * Weak ciphers
|
||||||
|
+ */
|
||||||
|
+static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
+ /* TLSv1.3 ciphers */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
TLS1_3_RFC_AES_128_GCM_SHA256,
|
||||||
|
@@ -111,20 +129,8 @@ static SSL_CIPHER tls13_ciphers[] = {
|
||||||
|
SSL_HANDSHAKE_MAC_SHA256,
|
||||||
|
128,
|
||||||
|
128,
|
||||||
|
- }
|
||||||
|
-};
|
||||||
|
-
|
||||||
|
-/*
|
||||||
|
- * The list of available ciphers, mostly organized into the following
|
||||||
|
- * groups:
|
||||||
|
- * Always there
|
||||||
|
- * EC
|
||||||
|
- * PSK
|
||||||
|
- * SRP (within that: RSA EC PSK)
|
||||||
|
- * Cipher families: Chacha/poly, Camellia, Gost, IDEA, SEED
|
||||||
|
- * Weak ciphers
|
||||||
|
- */
|
||||||
|
-static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
+ },
|
||||||
|
+ /* List of cipher below TLSv1.3 */
|
||||||
|
{
|
||||||
|
1,
|
||||||
|
SSL3_TXT_RSA_NULL_MD5,
|
||||||
|
@@ -167,7 +173,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
SSL_aRSA,
|
||||||
|
SSL_3DES,
|
||||||
|
SSL_SHA1,
|
||||||
|
- SSL3_VERSION, TLS1_2_VERSION,
|
||||||
|
+ SSL3_VERSION, TLS1_VERSION,
|
||||||
|
DTLS1_BAD_VER, DTLS1_2_VERSION,
|
||||||
|
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
|
||||||
|
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
|
||||||
|
@@ -232,7 +238,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
SSL_aRSA,
|
||||||
|
SSL_AES128,
|
||||||
|
SSL_SHA1,
|
||||||
|
- SSL3_VERSION, TLS1_2_VERSION,
|
||||||
|
+ SSL3_VERSION, TLS1_VERSION,
|
||||||
|
DTLS1_BAD_VER, DTLS1_2_VERSION,
|
||||||
|
SSL_HIGH | SSL_FIPS,
|
||||||
|
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
|
||||||
|
@@ -296,7 +302,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
|
||||||
|
SSL_aRSA,
|
||||||
|
SSL_AES256,
|
||||||
|
SSL_SHA1,
|
||||||
|
- SSL3_VERSION, TLS1_2_VERSION,
|
||||||
|
+ SSL3_VERSION, TLS1_VERSION,
|
||||||
|
DTLS1_BAD_VER, DTLS1_2_VERSION,
|
||||||
|
SSL_HIGH | SSL_FIPS,
|
||||||
|
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
|
||||||
|
@@ -4124,6 +4130,17 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_get_cipher_preferences(SSL *s)
|
||||||
|
+{
|
||||||
|
+ if (s->cipher_list != NULL)
|
||||||
|
+ return (s->cipher_list);
|
||||||
|
+
|
||||||
|
+ if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL))
|
||||||
|
+ return (s->ctx->cipher_list);
|
||||||
|
+
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
/*
|
||||||
|
* ssl3_choose_cipher - choose a cipher from those offered by the client
|
||||||
|
* @s: SSL connection
|
||||||
|
@@ -4133,16 +4150,24 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
|
||||||
|
* Returns the selected cipher or NULL when no common ciphers.
|
||||||
|
*/
|
||||||
|
const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
- STACK_OF(SSL_CIPHER) *srvr)
|
||||||
|
+ struct ssl_cipher_preference_list_st
|
||||||
|
+ *server_pref)
|
||||||
|
{
|
||||||
|
const SSL_CIPHER *c, *ret = NULL;
|
||||||
|
- STACK_OF(SSL_CIPHER) *prio, *allow;
|
||||||
|
- int i, ii, ok, prefer_sha256 = 0;
|
||||||
|
+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
|
||||||
|
+ int i, ii, ok, prefer_sha256 = 0, safari_ec = 0;
|
||||||
|
unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0;
|
||||||
|
const EVP_MD *mdsha256 = EVP_sha256();
|
||||||
|
-#ifndef OPENSSL_NO_CHACHA
|
||||||
|
- STACK_OF(SSL_CIPHER) *prio_chacha = NULL;
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
+ /* in_group_flags will either be NULL, or will point to an array of
|
||||||
|
+ * bytes which indicate equal-preference groups in the |prio| stack.
|
||||||
|
+ * See the comment about |in_group_flags| in the
|
||||||
|
+ * |ssl_cipher_preference_list_st| struct. */
|
||||||
|
+ const uint8_t *in_group_flags;
|
||||||
|
+
|
||||||
|
+ /* group_min contains the minimal index so far found in a group, or -1
|
||||||
|
+ * if no such value exists yet. */
|
||||||
|
+ int group_min = -1;
|
||||||
|
|
||||||
|
/* Let's see which ciphers we can support */
|
||||||
|
|
||||||
|
@@ -4169,54 +4194,13 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* SUITE-B takes precedence over server preference and ChaCha priortiy */
|
||||||
|
- if (tls1_suiteb(s)) {
|
||||||
|
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
|
||||||
|
prio = srvr;
|
||||||
|
+ in_group_flags = server_pref->in_group_flags;
|
||||||
|
allow = clnt;
|
||||||
|
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
|
||||||
|
- prio = srvr;
|
||||||
|
- allow = clnt;
|
||||||
|
-#ifndef OPENSSL_NO_CHACHA
|
||||||
|
- /* If ChaCha20 is at the top of the client preference list,
|
||||||
|
- and there are ChaCha20 ciphers in the server list, then
|
||||||
|
- temporarily prioritize all ChaCha20 ciphers in the servers list. */
|
||||||
|
- if (s->options & SSL_OP_PRIORITIZE_CHACHA && sk_SSL_CIPHER_num(clnt) > 0) {
|
||||||
|
- c = sk_SSL_CIPHER_value(clnt, 0);
|
||||||
|
- if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
|
||||||
|
- /* ChaCha20 is client preferred, check server... */
|
||||||
|
- int num = sk_SSL_CIPHER_num(srvr);
|
||||||
|
- int found = 0;
|
||||||
|
- for (i = 0; i < num; i++) {
|
||||||
|
- c = sk_SSL_CIPHER_value(srvr, i);
|
||||||
|
- if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
|
||||||
|
- found = 1;
|
||||||
|
- break;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- if (found) {
|
||||||
|
- prio_chacha = sk_SSL_CIPHER_new_reserve(NULL, num);
|
||||||
|
- /* if reserve fails, then there's likely a memory issue */
|
||||||
|
- if (prio_chacha != NULL) {
|
||||||
|
- /* Put all ChaCha20 at the top, starting with the one we just found */
|
||||||
|
- sk_SSL_CIPHER_push(prio_chacha, c);
|
||||||
|
- for (i++; i < num; i++) {
|
||||||
|
- c = sk_SSL_CIPHER_value(srvr, i);
|
||||||
|
- if (c->algorithm_enc == SSL_CHACHA20POLY1305)
|
||||||
|
- sk_SSL_CIPHER_push(prio_chacha, c);
|
||||||
|
- }
|
||||||
|
- /* Pull in the rest */
|
||||||
|
- for (i = 0; i < num; i++) {
|
||||||
|
- c = sk_SSL_CIPHER_value(srvr, i);
|
||||||
|
- if (c->algorithm_enc != SSL_CHACHA20POLY1305)
|
||||||
|
- sk_SSL_CIPHER_push(prio_chacha, c);
|
||||||
|
- }
|
||||||
|
- prio = prio_chacha;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-# endif
|
||||||
|
} else {
|
||||||
|
prio = clnt;
|
||||||
|
+ in_group_flags = NULL;
|
||||||
|
allow = srvr;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -4247,14 +4231,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
|
||||||
|
c = sk_SSL_CIPHER_value(prio, i);
|
||||||
|
|
||||||
|
+ ok = 1;
|
||||||
|
+
|
||||||
|
/* Skip ciphers not supported by the protocol version */
|
||||||
|
if (!SSL_IS_DTLS(s) &&
|
||||||
|
((s->version < c->min_tls) || (s->version > c->max_tls)))
|
||||||
|
- continue;
|
||||||
|
+ ok = 0;
|
||||||
|
if (SSL_IS_DTLS(s) &&
|
||||||
|
(DTLS_VERSION_LT(s->version, c->min_dtls) ||
|
||||||
|
DTLS_VERSION_GT(s->version, c->max_dtls)))
|
||||||
|
- continue;
|
||||||
|
+ ok = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Since TLS 1.3 ciphersuites can be used with any auth or
|
||||||
|
@@ -4276,10 +4262,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
#ifndef OPENSSL_NO_PSK
|
||||||
|
/* with PSK there must be server callback set */
|
||||||
|
if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
|
||||||
|
- continue;
|
||||||
|
+ ok = 0;
|
||||||
|
#endif /* OPENSSL_NO_PSK */
|
||||||
|
|
||||||
|
- ok = (alg_k & mask_k) && (alg_a & mask_a);
|
||||||
|
+ ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
|
||||||
|
#ifdef CIPHER_DEBUG
|
||||||
|
fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
|
||||||
|
alg_a, mask_k, mask_a, (void *)c, c->name);
|
||||||
|
@@ -4296,6 +4282,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
|
||||||
|
if (!ok)
|
||||||
|
continue;
|
||||||
|
+
|
||||||
|
+ safari_ec = 0;
|
||||||
|
+#if !defined(OPENSSL_NO_EC)
|
||||||
|
+ if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)) {
|
||||||
|
+ if (s->s3->is_probably_safari)
|
||||||
|
+ safari_ec = 1;
|
||||||
|
+ }
|
||||||
|
+#endif
|
||||||
|
}
|
||||||
|
ii = sk_SSL_CIPHER_find(allow, c);
|
||||||
|
if (ii >= 0) {
|
||||||
|
@@ -4303,14 +4297,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
|
||||||
|
c->strength_bits, 0, (void *)c))
|
||||||
|
continue;
|
||||||
|
-#if !defined(OPENSSL_NO_EC)
|
||||||
|
- if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
|
||||||
|
- && s->s3->is_probably_safari) {
|
||||||
|
- if (!ret)
|
||||||
|
- ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
- continue;
|
||||||
|
- }
|
||||||
|
-#endif
|
||||||
|
+
|
||||||
|
if (prefer_sha256) {
|
||||||
|
const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
|
||||||
|
@@ -4322,13 +4309,38 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
ret = tmp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
- ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
+
|
||||||
|
+ if (in_group_flags != NULL && in_group_flags[i] == 1) {
|
||||||
|
+ /* This element of |prio| is in a group. Update
|
||||||
|
+ * the minimum index found so far and continue
|
||||||
|
+ * looking. */
|
||||||
|
+ if (group_min == -1 || group_min > ii)
|
||||||
|
+ group_min = ii;
|
||||||
|
+ } else {
|
||||||
|
+ if (group_min != -1 && group_min < ii)
|
||||||
|
+ ii = group_min;
|
||||||
|
+ if (safari_ec) {
|
||||||
|
+ if (!ret)
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, ii);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (in_group_flags != NULL && !in_group_flags[i] && group_min != -1) {
|
||||||
|
+ /* We are about to leave a group, but we found a match
|
||||||
|
+ * in it, so that's our answer. */
|
||||||
|
+ if (safari_ec) {
|
||||||
|
+ if (!ret)
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, group_min);
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ ret = sk_SSL_CIPHER_value(allow, group_min);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-#ifndef OPENSSL_NO_CHACHA
|
||||||
|
- sk_SSL_CIPHER_free(prio_chacha);
|
||||||
|
-#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
|
||||||
|
index 27a1b2ec68..111a39229a 100644
|
||||||
|
--- a/ssl/ssl_ciph.c
|
||||||
|
+++ b/ssl/ssl_ciph.c
|
||||||
|
@@ -192,6 +192,7 @@ typedef struct cipher_order_st {
|
||||||
|
const SSL_CIPHER *cipher;
|
||||||
|
int active;
|
||||||
|
int dead;
|
||||||
|
+ int in_group;
|
||||||
|
struct cipher_order_st *next, *prev;
|
||||||
|
} CIPHER_ORDER;
|
||||||
|
|
||||||
|
@@ -296,6 +297,7 @@ static const SSL_CIPHER cipher_aliases[] = {
|
||||||
|
{0, SSL_TXT_TLSV1, NULL, 0, 0, 0, 0, 0, TLS1_VERSION},
|
||||||
|
{0, "TLSv1.0", NULL, 0, 0, 0, 0, 0, TLS1_VERSION},
|
||||||
|
{0, SSL_TXT_TLSV1_2, NULL, 0, 0, 0, 0, 0, TLS1_2_VERSION},
|
||||||
|
+ {0, "TLS13", NULL, 0, 0, 0, 0, 0, TLS1_3_VERSION},
|
||||||
|
|
||||||
|
/* strength classes */
|
||||||
|
{0, SSL_TXT_LOW, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_LOW},
|
||||||
|
@@ -681,6 +683,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
|
||||||
|
co_list[co_list_num].next = NULL;
|
||||||
|
co_list[co_list_num].prev = NULL;
|
||||||
|
co_list[co_list_num].active = 0;
|
||||||
|
+ co_list[co_list_num].in_group = 0;
|
||||||
|
co_list_num++;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -774,8 +777,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
uint32_t alg_auth, uint32_t alg_enc,
|
||||||
|
uint32_t alg_mac, int min_tls,
|
||||||
|
uint32_t algo_strength, int rule,
|
||||||
|
- int32_t strength_bits, CIPHER_ORDER **head_p,
|
||||||
|
- CIPHER_ORDER **tail_p)
|
||||||
|
+ int32_t strength_bits, int in_group,
|
||||||
|
+ CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
|
||||||
|
{
|
||||||
|
CIPHER_ORDER *head, *tail, *curr, *next, *last;
|
||||||
|
const SSL_CIPHER *cp;
|
||||||
|
@@ -783,9 +786,9 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
|
||||||
|
#ifdef CIPHER_DEBUG
|
||||||
|
fprintf(stderr,
|
||||||
|
- "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
|
||||||
|
+ "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d) g:%d\n",
|
||||||
|
rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
|
||||||
|
- algo_strength, strength_bits);
|
||||||
|
+ algo_strength, strength_bits, in_group);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
|
||||||
|
@@ -862,6 +865,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
if (!curr->active) {
|
||||||
|
ll_append_tail(&head, curr, &tail);
|
||||||
|
curr->active = 1;
|
||||||
|
+ curr->in_group = in_group;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Move the added cipher to this location */
|
||||||
|
@@ -869,6 +873,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
/* reverse == 0 */
|
||||||
|
if (curr->active) {
|
||||||
|
ll_append_tail(&head, curr, &tail);
|
||||||
|
+ curr->in_group = 0;
|
||||||
|
}
|
||||||
|
} else if (rule == CIPHER_DEL) {
|
||||||
|
/* reverse == 1 */
|
||||||
|
@@ -880,6 +885,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
|
||||||
|
*/
|
||||||
|
ll_append_head(&head, curr, &tail);
|
||||||
|
curr->active = 0;
|
||||||
|
+ curr->in_group = 0;
|
||||||
|
}
|
||||||
|
} else if (rule == CIPHER_BUMP) {
|
||||||
|
if (curr->active)
|
||||||
|
@@ -947,8 +953,8 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
|
||||||
|
*/
|
||||||
|
for (i = max_strength_bits; i >= 0; i--)
|
||||||
|
if (number_uses[i] > 0)
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p,
|
||||||
|
- tail_p);
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0,
|
||||||
|
+ head_p, tail_p);
|
||||||
|
|
||||||
|
OPENSSL_free(number_uses);
|
||||||
|
return 1;
|
||||||
|
@@ -962,7 +968,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
|
||||||
|
int min_tls;
|
||||||
|
const char *l, *buf;
|
||||||
|
- int j, multi, found, rule, retval, ok, buflen;
|
||||||
|
+ int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0;
|
||||||
|
uint32_t cipher_id = 0;
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
@@ -973,18 +979,66 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
|
||||||
|
if (ch == '\0')
|
||||||
|
break; /* done */
|
||||||
|
- if (ch == '-') {
|
||||||
|
+ if (in_group) {
|
||||||
|
+ if (ch == ']') {
|
||||||
|
+ if (!in_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_UNEXPECTED_GROUP_CLOSE);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ if (*tail_p)
|
||||||
|
+ (*tail_p)->in_group = 0;
|
||||||
|
+ in_group = 0;
|
||||||
|
+ l++;
|
||||||
|
+ continue;
|
||||||
|
+ }
|
||||||
|
+ if (ch == '|') {
|
||||||
|
+ rule = CIPHER_ADD;
|
||||||
|
+ l++;
|
||||||
|
+ continue;
|
||||||
|
+ } else if (!(ch >= 'a' && ch <= 'z')
|
||||||
|
+ && !(ch >= 'A' && ch <= 'Z')
|
||||||
|
+ && !(ch >= '0' && ch <= '9')) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
+ } else {
|
||||||
|
+ rule = CIPHER_ADD;
|
||||||
|
+ }
|
||||||
|
+ } else if (ch == '-') {
|
||||||
|
rule = CIPHER_DEL;
|
||||||
|
l++;
|
||||||
|
} else if (ch == '+') {
|
||||||
|
rule = CIPHER_ORD;
|
||||||
|
l++;
|
||||||
|
+ } else if (ch == '!' && has_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
} else if (ch == '!') {
|
||||||
|
rule = CIPHER_KILL;
|
||||||
|
l++;
|
||||||
|
+ } else if (ch == '@' && has_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
|
||||||
|
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
} else if (ch == '@') {
|
||||||
|
rule = CIPHER_SPECIAL;
|
||||||
|
l++;
|
||||||
|
+ } else if (ch == '[') {
|
||||||
|
+ if (in_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_NESTED_GROUP);
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ in_group = 1;
|
||||||
|
+ has_group = 1;
|
||||||
|
+ l++;
|
||||||
|
+ continue;
|
||||||
|
} else {
|
||||||
|
rule = CIPHER_ADD;
|
||||||
|
}
|
||||||
|
@@ -1009,7 +1063,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
while (((ch >= 'A') && (ch <= 'Z')) ||
|
||||||
|
((ch >= '0') && (ch <= '9')) ||
|
||||||
|
((ch >= 'a') && (ch <= 'z')) ||
|
||||||
|
- (ch == '-') || (ch == '.') || (ch == '='))
|
||||||
|
+ (ch == '-') || (ch == '.') || (ch == '=') || (ch == '_'))
|
||||||
|
#else
|
||||||
|
while (isalnum((unsigned char)ch) || (ch == '-') || (ch == '.')
|
||||||
|
|| (ch == '='))
|
||||||
|
@@ -1026,7 +1080,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
* alphanumeric, so we call this an error.
|
||||||
|
*/
|
||||||
|
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
|
||||||
|
- retval = found = 0;
|
||||||
|
+ retval = found = in_group = 0;
|
||||||
|
l++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
@@ -1205,8 +1259,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
} else if (found) {
|
||||||
|
ssl_cipher_apply_rule(cipher_id,
|
||||||
|
alg_mkey, alg_auth, alg_enc, alg_mac,
|
||||||
|
- min_tls, algo_strength, rule, -1, head_p,
|
||||||
|
- tail_p);
|
||||||
|
+ min_tls, algo_strength, rule, -1, in_group,
|
||||||
|
+ head_p, tail_p);
|
||||||
|
} else {
|
||||||
|
while ((*l != '\0') && !ITEM_SEP(*l))
|
||||||
|
l++;
|
||||||
|
@@ -1215,6 +1269,11 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
|
||||||
|
break; /* done */
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (in_group) {
|
||||||
|
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
|
||||||
|
+ retval = 0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1378,7 +1437,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
|
||||||
|
int ret = set_ciphersuites(&(ctx->tls13_ciphersuites), str);
|
||||||
|
|
||||||
|
if (ret && ctx->cipher_list != NULL)
|
||||||
|
- return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id,
|
||||||
|
+ return update_cipher_list(&ctx->cipher_list->ciphers, &ctx->cipher_list_by_id,
|
||||||
|
ctx->tls13_ciphersuites);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
@@ -1391,10 +1450,10 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
|
||||||
|
|
||||||
|
if (s->cipher_list == NULL) {
|
||||||
|
if ((cipher_list = SSL_get_ciphers(s)) != NULL)
|
||||||
|
- s->cipher_list = sk_SSL_CIPHER_dup(cipher_list);
|
||||||
|
+ s->cipher_list->ciphers = sk_SSL_CIPHER_dup(cipher_list);
|
||||||
|
}
|
||||||
|
if (ret && s->cipher_list != NULL)
|
||||||
|
- return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id,
|
||||||
|
+ return update_cipher_list(&s->cipher_list->ciphers, &s->cipher_list_by_id,
|
||||||
|
s->tls13_ciphersuites);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
@@ -1402,17 +1461,20 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
|
||||||
|
|
||||||
|
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
|
||||||
|
- STACK_OF(SSL_CIPHER) **cipher_list,
|
||||||
|
+ struct ssl_cipher_preference_list_st **cipher_list,
|
||||||
|
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
|
||||||
|
const char *rule_str,
|
||||||
|
CERT *c)
|
||||||
|
{
|
||||||
|
- int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i;
|
||||||
|
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
|
||||||
|
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
|
||||||
|
- STACK_OF(SSL_CIPHER) *cipherstack;
|
||||||
|
+ STACK_OF(SSL_CIPHER) *cipherstack = NULL;
|
||||||
|
const char *rule_p;
|
||||||
|
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
|
||||||
|
const SSL_CIPHER **ca_list = NULL;
|
||||||
|
+ uint8_t *in_group_flags = NULL;
|
||||||
|
+ unsigned int num_in_group_flags = 0;
|
||||||
|
+ struct ssl_cipher_preference_list_st *pref_list = NULL;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return with error if nothing to do.
|
||||||
|
@@ -1461,16 +1523,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* preference).
|
||||||
|
*/
|
||||||
|
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
|
||||||
|
- -1, &head, &tail);
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
|
||||||
|
- &tail);
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
|
||||||
|
- &tail);
|
||||||
|
+ -1, 0, &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0,
|
||||||
|
+ &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0,
|
||||||
|
+ &head, &tail);
|
||||||
|
|
||||||
|
/* Within each strength group, we prefer GCM over CHACHA... */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1479,13 +1541,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* strength.
|
||||||
|
*/
|
||||||
|
ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
|
||||||
|
- -1, &head, &tail);
|
||||||
|
+ -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/* Temporarily enable everything else for sorting */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/* Low priority for MD5 */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1493,16 +1555,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* disabled. (For applications that allow them, they aren't too bad, but
|
||||||
|
* we prefer authenticated ciphers.)
|
||||||
|
*/
|
||||||
|
- ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
- ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
/* RC4 is sort-of broken -- move to the end */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
|
||||||
|
&tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1518,7 +1580,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
|
||||||
|
* TODO(openssl-team): is there an easier way to accomplish all this?
|
||||||
|
*/
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
@@ -1534,15 +1596,18 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
* Because we now bump ciphers to the top of the list, we proceed in
|
||||||
|
* reverse order of preference.
|
||||||
|
*/
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1,
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1, 0,
|
||||||
|
&head, &tail);
|
||||||
|
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
|
||||||
|
- CIPHER_BUMP, -1, &head, &tail);
|
||||||
|
+ CIPHER_BUMP, -1, 0, &head, &tail);
|
||||||
|
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
|
||||||
|
- CIPHER_BUMP, -1, &head, &tail);
|
||||||
|
+ CIPHER_BUMP, -1, 0, &head, &tail);
|
||||||
|
+
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_3_VERSION, 0, CIPHER_BUMP, -1, 0,
|
||||||
|
+ &head, &tail);
|
||||||
|
|
||||||
|
/* Now disable everything (maintaining the ordering!) */
|
||||||
|
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
|
||||||
|
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We also need cipher aliases for selecting based on the rule_str.
|
||||||
|
@@ -1556,9 +1621,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
|
||||||
|
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
|
||||||
|
if (ca_list == NULL) {
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
|
||||||
|
- return NULL; /* Failure */
|
||||||
|
+ goto err; /* Failure */
|
||||||
|
}
|
||||||
|
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
|
||||||
|
disabled_mkey, disabled_auth, disabled_enc,
|
||||||
|
@@ -1583,28 +1647,19 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
|
||||||
|
OPENSSL_free(ca_list); /* Not needed anymore */
|
||||||
|
|
||||||
|
- if (!ok) { /* Rule processing failure */
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if (!ok)
|
||||||
|
+ goto err; /* Rule processing failure */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate new "cipherstack" for the result, return with error
|
||||||
|
* if we cannot get one.
|
||||||
|
*/
|
||||||
|
- if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
|
||||||
|
+ goto err;
|
||||||
|
|
||||||
|
- /* Add TLSv1.3 ciphers first - we always prefer those if possible */
|
||||||
|
- for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
|
||||||
|
- if (!sk_SSL_CIPHER_push(cipherstack,
|
||||||
|
- sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
|
||||||
|
- sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ in_group_flags = OPENSSL_malloc(num_of_ciphers);
|
||||||
|
+ if (!in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The cipher selection for the list is done. The ciphers are added
|
||||||
|
@@ -1612,26 +1667,50 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
*/
|
||||||
|
for (curr = head; curr != NULL; curr = curr->next) {
|
||||||
|
if (curr->active) {
|
||||||
|
- if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
|
||||||
|
- OPENSSL_free(co_list);
|
||||||
|
- sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
+ if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher))
|
||||||
|
+ goto err;
|
||||||
|
+ in_group_flags[num_in_group_flags++] = curr->in_group;
|
||||||
|
#ifdef CIPHER_DEBUG
|
||||||
|
fprintf(stderr, "<%s>\n", curr->cipher->name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
- OPENSSL_free(co_list); /* Not needed any longer */
|
||||||
|
|
||||||
|
- if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
|
||||||
|
- sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
- return NULL;
|
||||||
|
- }
|
||||||
|
- sk_SSL_CIPHER_free(*cipher_list);
|
||||||
|
- *cipher_list = cipherstack;
|
||||||
|
+ OPENSSL_free(co_list); /* Not needed any longer */
|
||||||
|
+ co_list = NULL;
|
||||||
|
+
|
||||||
|
+ if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack))
|
||||||
|
+ goto err;
|
||||||
|
+
|
||||||
|
+ pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
|
||||||
|
+ if (!pref_list)
|
||||||
|
+ goto err;
|
||||||
|
+ pref_list->ciphers = cipherstack;
|
||||||
|
+ pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
|
||||||
|
+ if (!pref_list->in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
+ memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
|
||||||
|
+ OPENSSL_free(in_group_flags);
|
||||||
|
+ in_group_flags = NULL;
|
||||||
|
+ if (*cipher_list != NULL)
|
||||||
|
+ ssl_cipher_preference_list_free(*cipher_list);
|
||||||
|
+ *cipher_list = pref_list;
|
||||||
|
+ pref_list = NULL;
|
||||||
|
|
||||||
|
return cipherstack;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (co_list)
|
||||||
|
+ OPENSSL_free(co_list);
|
||||||
|
+ if (in_group_flags)
|
||||||
|
+ OPENSSL_free(in_group_flags);
|
||||||
|
+ if (cipherstack)
|
||||||
|
+ sk_SSL_CIPHER_free(cipherstack);
|
||||||
|
+ if (pref_list && pref_list->in_group_flags)
|
||||||
|
+ OPENSSL_free(pref_list->in_group_flags);
|
||||||
|
+ if (pref_list)
|
||||||
|
+ OPENSSL_free(pref_list);
|
||||||
|
+ return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
|
||||||
|
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
|
||||||
|
index 4b12ed1485..cd1a95d1d2 100644
|
||||||
|
--- a/ssl/ssl_err.c
|
||||||
|
+++ b/ssl/ssl_err.c
|
||||||
|
@@ -965,6 +965,9 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_DH_KEY), "missing tmp dh key"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_ECDH_KEY),
|
||||||
|
"missing tmp ecdh key"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS),
|
||||||
|
+ "mixed special operator with groups"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NESTED_GROUP), "nested group"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_HANDSHAKE_AND_NON_HANDSHAKE_DATA),
|
||||||
|
"mixed handshake and non handshake data"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_ON_RECORD_BOUNDARY),
|
||||||
|
@@ -1201,11 +1204,14 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
|
||||||
|
"unable to load ssl3 md5 routines"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
|
||||||
|
"unable to load ssl3 sha1 routines"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_GROUP_CLOSE), "unexpected group close"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_CCS_MESSAGE),
|
||||||
|
"unexpected ccs message"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
|
||||||
|
"unexpected end of early data"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
|
||||||
|
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP),
|
||||||
|
+ "unexpected operator in group"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "unexpected record"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"},
|
||||||
|
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_ALERT_TYPE), "unknown alert type"},
|
||||||
|
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
|
||||||
|
index ac820cf9fe..141308584c 100644
|
||||||
|
--- a/ssl/ssl_lib.c
|
||||||
|
+++ b/ssl/ssl_lib.c
|
||||||
|
@@ -1122,6 +1122,71 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
|
||||||
|
return X509_VERIFY_PARAM_set1(ssl->param, vpm);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void ssl_cipher_preference_list_free(struct ssl_cipher_preference_list_st
|
||||||
|
+ *cipher_list)
|
||||||
|
+{
|
||||||
|
+ sk_SSL_CIPHER_free(cipher_list->ciphers);
|
||||||
|
+ OPENSSL_free(cipher_list->in_group_flags);
|
||||||
|
+ OPENSSL_free(cipher_list);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct ssl_cipher_preference_list_st*
|
||||||
|
+ssl_cipher_preference_list_dup(struct ssl_cipher_preference_list_st
|
||||||
|
+ *cipher_list)
|
||||||
|
+{
|
||||||
|
+ struct ssl_cipher_preference_list_st* ret = NULL;
|
||||||
|
+ size_t n = sk_SSL_CIPHER_num(cipher_list->ciphers);
|
||||||
|
+
|
||||||
|
+ ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
|
||||||
|
+ if (!ret)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->ciphers = NULL;
|
||||||
|
+ ret->in_group_flags = NULL;
|
||||||
|
+ ret->ciphers = sk_SSL_CIPHER_dup(cipher_list->ciphers);
|
||||||
|
+ if (!ret->ciphers)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->in_group_flags = OPENSSL_malloc(n);
|
||||||
|
+ if (!ret->in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
+ memcpy(ret->in_group_flags, cipher_list->in_group_flags, n);
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (ret->ciphers)
|
||||||
|
+ sk_SSL_CIPHER_free(ret->ciphers);
|
||||||
|
+ if (ret)
|
||||||
|
+ OPENSSL_free(ret);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct ssl_cipher_preference_list_st*
|
||||||
|
+ssl_cipher_preference_list_from_ciphers(STACK_OF(SSL_CIPHER) *ciphers)
|
||||||
|
+{
|
||||||
|
+ struct ssl_cipher_preference_list_st* ret = NULL;
|
||||||
|
+ size_t n = sk_SSL_CIPHER_num(ciphers);
|
||||||
|
+
|
||||||
|
+ ret = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
|
||||||
|
+ if (!ret)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->ciphers = NULL;
|
||||||
|
+ ret->in_group_flags = NULL;
|
||||||
|
+ ret->ciphers = sk_SSL_CIPHER_dup(ciphers);
|
||||||
|
+ if (!ret->ciphers)
|
||||||
|
+ goto err;
|
||||||
|
+ ret->in_group_flags = OPENSSL_malloc(n);
|
||||||
|
+ if (!ret->in_group_flags)
|
||||||
|
+ goto err;
|
||||||
|
+ memset(ret->in_group_flags, 0, n);
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+err:
|
||||||
|
+ if (ret->ciphers)
|
||||||
|
+ sk_SSL_CIPHER_free(ret->ciphers);
|
||||||
|
+ if (ret)
|
||||||
|
+ OPENSSL_free(ret);
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
|
||||||
|
{
|
||||||
|
return ctx->param;
|
||||||
|
@@ -1162,7 +1227,8 @@ void SSL_free(SSL *s)
|
||||||
|
BUF_MEM_free(s->init_buf);
|
||||||
|
|
||||||
|
/* add extra stuff */
|
||||||
|
- sk_SSL_CIPHER_free(s->cipher_list);
|
||||||
|
+ if (s->cipher_list != NULL)
|
||||||
|
+ ssl_cipher_preference_list_free(s->cipher_list);
|
||||||
|
sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||||
|
sk_SSL_CIPHER_free(s->tls13_ciphersuites);
|
||||||
|
sk_SSL_CIPHER_free(s->peer_ciphers);
|
||||||
|
@@ -2436,9 +2502,9 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
|
||||||
|
{
|
||||||
|
if (s != NULL) {
|
||||||
|
if (s->cipher_list != NULL) {
|
||||||
|
- return s->cipher_list;
|
||||||
|
+ return (s->cipher_list->ciphers);
|
||||||
|
} else if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL)) {
|
||||||
|
- return s->ctx->cipher_list;
|
||||||
|
+ return (s->ctx->cipher_list->ciphers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
@@ -2512,8 +2578,8 @@ const char *SSL_get_cipher_list(const SSL *s, int n)
|
||||||
|
* preference */
|
||||||
|
STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx)
|
||||||
|
{
|
||||||
|
- if (ctx != NULL)
|
||||||
|
- return ctx->cipher_list;
|
||||||
|
+ if (ctx != NULL && ctx->cipher_list != NULL)
|
||||||
|
+ return ctx->cipher_list->ciphers;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -2963,7 +3029,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
|
||||||
|
ret->tls13_ciphersuites,
|
||||||
|
&ret->cipher_list, &ret->cipher_list_by_id,
|
||||||
|
SSL_DEFAULT_CIPHER_LIST, ret->cert)
|
||||||
|
- || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
|
||||||
|
+ || sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) {
|
||||||
|
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
|
||||||
|
goto err2;
|
||||||
|
}
|
||||||
|
@@ -3139,7 +3205,7 @@ void SSL_CTX_free(SSL_CTX *a)
|
||||||
|
#ifndef OPENSSL_NO_CT
|
||||||
|
CTLOG_STORE_free(a->ctlog_store);
|
||||||
|
#endif
|
||||||
|
- sk_SSL_CIPHER_free(a->cipher_list);
|
||||||
|
+ ssl_cipher_preference_list_free(a->cipher_list);
|
||||||
|
sk_SSL_CIPHER_free(a->cipher_list_by_id);
|
||||||
|
sk_SSL_CIPHER_free(a->tls13_ciphersuites);
|
||||||
|
ssl_cert_free(a->cert);
|
||||||
|
@@ -3817,13 +3883,15 @@ SSL *SSL_dup(SSL *s)
|
||||||
|
|
||||||
|
/* dup the cipher_list and cipher_list_by_id stacks */
|
||||||
|
if (s->cipher_list != NULL) {
|
||||||
|
- if ((ret->cipher_list = sk_SSL_CIPHER_dup(s->cipher_list)) == NULL)
|
||||||
|
+ ret->cipher_list = ssl_cipher_preference_list_dup(s->cipher_list);
|
||||||
|
+ if (ret->cipher_list == NULL)
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
- if (s->cipher_list_by_id != NULL)
|
||||||
|
- if ((ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id))
|
||||||
|
- == NULL)
|
||||||
|
+ if (s->cipher_list_by_id != NULL) {
|
||||||
|
+ ret->cipher_list_by_id = sk_SSL_CIPHER_dup(s->cipher_list_by_id);
|
||||||
|
+ if (ret->cipher_list_by_id == NULL)
|
||||||
|
goto err;
|
||||||
|
+ }
|
||||||
|
|
||||||
|
/* Dup the client_CA list */
|
||||||
|
if (!dup_ca_names(&ret->ca_names, s->ca_names)
|
||||||
|
diff --git a/ssl/ssl_local.h b/ssl/ssl_local.h
|
||||||
|
index 25875c9f6d..23a6093580 100644
|
||||||
|
--- a/ssl/ssl_local.h
|
||||||
|
+++ b/ssl/ssl_local.h
|
||||||
|
@@ -733,9 +733,46 @@ typedef struct ssl_ctx_ext_secure_st {
|
||||||
|
unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
|
||||||
|
} SSL_CTX_EXT_SECURE;
|
||||||
|
|
||||||
|
+/* ssl_cipher_preference_list_st contains a list of SSL_CIPHERs with
|
||||||
|
+ * equal-preference groups. For TLS clients, the groups are moot because the
|
||||||
|
+ * server picks the cipher and groups cannot be expressed on the wire. However,
|
||||||
|
+ * for servers, the equal-preference groups allow the client's preferences to
|
||||||
|
+ * be partially respected. (This only has an effect with
|
||||||
|
+ * SSL_OP_CIPHER_SERVER_PREFERENCE).
|
||||||
|
+ *
|
||||||
|
+ * The equal-preference groups are expressed by grouping SSL_CIPHERs together.
|
||||||
|
+ * All elements of a group have the same priority: no ordering is expressed
|
||||||
|
+ * within a group.
|
||||||
|
+ *
|
||||||
|
+ * The values in |ciphers| are in one-to-one correspondence with
|
||||||
|
+ * |in_group_flags|. (That is, sk_SSL_CIPHER_num(ciphers) is the number of
|
||||||
|
+ * bytes in |in_group_flags|.) The bytes in |in_group_flags| are either 1, to
|
||||||
|
+ * indicate that the corresponding SSL_CIPHER is not the last element of a
|
||||||
|
+ * group, or 0 to indicate that it is.
|
||||||
|
+ *
|
||||||
|
+ * For example, if |in_group_flags| contains all zeros then that indicates a
|
||||||
|
+ * traditional, fully-ordered preference. Every SSL_CIPHER is the last element
|
||||||
|
+ * of the group (i.e. they are all in a one-element group).
|
||||||
|
+ *
|
||||||
|
+ * For a more complex example, consider:
|
||||||
|
+ * ciphers: A B C D E F
|
||||||
|
+ * in_group_flags: 1 1 0 0 1 0
|
||||||
|
+ *
|
||||||
|
+ * That would express the following, order:
|
||||||
|
+ *
|
||||||
|
+ * A E
|
||||||
|
+ * B -> D -> F
|
||||||
|
+ * C
|
||||||
|
+ */
|
||||||
|
+struct ssl_cipher_preference_list_st {
|
||||||
|
+ STACK_OF(SSL_CIPHER) *ciphers;
|
||||||
|
+ uint8_t *in_group_flags;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+
|
||||||
|
struct ssl_ctx_st {
|
||||||
|
const SSL_METHOD *method;
|
||||||
|
- STACK_OF(SSL_CIPHER) *cipher_list;
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list;
|
||||||
|
/* same as above but sorted for lookup */
|
||||||
|
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
|
||||||
|
/* TLSv1.3 specific ciphersuites */
|
||||||
|
@@ -1131,7 +1168,7 @@ struct ssl_st {
|
||||||
|
SSL_DANE dane;
|
||||||
|
/* crypto */
|
||||||
|
STACK_OF(SSL_CIPHER) *peer_ciphers;
|
||||||
|
- STACK_OF(SSL_CIPHER) *cipher_list;
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list;
|
||||||
|
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
|
||||||
|
/* TLSv1.3 specific ciphersuites */
|
||||||
|
STACK_OF(SSL_CIPHER) *tls13_ciphersuites;
|
||||||
|
@@ -2269,7 +2306,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
|
||||||
|
const SSL_CIPHER *const *bp);
|
||||||
|
__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
|
||||||
|
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
|
||||||
|
- STACK_OF(SSL_CIPHER) **cipher_list,
|
||||||
|
+ struct ssl_cipher_preference_list_st **cipher_list,
|
||||||
|
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
|
||||||
|
const char *rule_str,
|
||||||
|
CERT *c);
|
||||||
|
@@ -2279,6 +2316,13 @@ __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
|
||||||
|
STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
|
||||||
|
int fatal);
|
||||||
|
void ssl_update_cache(SSL *s, int mode);
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_cipher_preference_list_dup(
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list);
|
||||||
|
+void ssl_cipher_preference_list_free(
|
||||||
|
+ struct ssl_cipher_preference_list_st *cipher_list);
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_cipher_preference_list_from_ciphers(
|
||||||
|
+ STACK_OF(SSL_CIPHER) *ciphers);
|
||||||
|
+struct ssl_cipher_preference_list_st* ssl_get_cipher_preferences(SSL *s);
|
||||||
|
__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
|
||||||
|
const EVP_MD **md, int *mac_pkey_type,
|
||||||
|
size_t *mac_secret_size, SSL_COMP **comp,
|
||||||
|
@@ -2362,7 +2406,7 @@ __owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
|
||||||
|
CERT_PKEY *cpk);
|
||||||
|
__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
|
||||||
|
STACK_OF(SSL_CIPHER) *clnt,
|
||||||
|
- STACK_OF(SSL_CIPHER) *srvr);
|
||||||
|
+ struct ssl_cipher_preference_list_st *srvr);
|
||||||
|
__owur int ssl3_digest_cached_records(SSL *s, int keep);
|
||||||
|
__owur int ssl3_new(SSL *s);
|
||||||
|
void ssl3_free(SSL *s);
|
||||||
|
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
|
||||||
|
index 8cf9c40d15..46391a7f05 100644
|
||||||
|
--- a/ssl/statem/statem_srvr.c
|
||||||
|
+++ b/ssl/statem/statem_srvr.c
|
||||||
|
@@ -1748,7 +1748,7 @@ static int tls_early_post_process_client_hello(SSL *s)
|
||||||
|
/* For TLSv1.3 we must select the ciphersuite *before* session resumption */
|
||||||
|
if (SSL_IS_TLS13(s)) {
|
||||||
|
const SSL_CIPHER *cipher =
|
||||||
|
- ssl3_choose_cipher(s, ciphers, SSL_get_ciphers(s));
|
||||||
|
+ ssl3_choose_cipher(s, ciphers, ssl_get_cipher_preferences(s));
|
||||||
|
|
||||||
|
if (cipher == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
|
@@ -1929,7 +1929,7 @@ static int tls_early_post_process_client_hello(SSL *s)
|
||||||
|
/* check if some cipher was preferred by call back */
|
||||||
|
if (pref_cipher == NULL)
|
||||||
|
pref_cipher = ssl3_choose_cipher(s, s->peer_ciphers,
|
||||||
|
- SSL_get_ciphers(s));
|
||||||
|
+ ssl_get_cipher_preferences(s));
|
||||||
|
if (pref_cipher == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
|
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
|
||||||
|
@@ -1938,8 +1938,9 @@ static int tls_early_post_process_client_hello(SSL *s)
|
||||||
|
}
|
||||||
|
|
||||||
|
s->session->cipher = pref_cipher;
|
||||||
|
- sk_SSL_CIPHER_free(s->cipher_list);
|
||||||
|
- s->cipher_list = sk_SSL_CIPHER_dup(s->peer_ciphers);
|
||||||
|
+ ssl_cipher_preference_list_free(s->cipher_list);
|
||||||
|
+ s->cipher_list = ssl_cipher_preference_list_from_ciphers(
|
||||||
|
+ s->peer_ciphers);
|
||||||
|
sk_SSL_CIPHER_free(s->cipher_list_by_id);
|
||||||
|
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->peer_ciphers);
|
||||||
|
}
|
||||||
|
@@ -2251,7 +2252,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
|
||||||
|
/* In TLSv1.3 we selected the ciphersuite before resumption */
|
||||||
|
if (!SSL_IS_TLS13(s)) {
|
||||||
|
cipher =
|
||||||
|
- ssl3_choose_cipher(s, s->peer_ciphers, SSL_get_ciphers(s));
|
||||||
|
+ ssl3_choose_cipher(s, s->peer_ciphers, ssl_get_cipher_preferences(s));
|
||||||
|
|
||||||
|
if (cipher == NULL) {
|
||||||
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
|
||||||
Reference in New Issue
Block a user