diff --git a/README.md b/README.md index 41185c6..d86912b 100644 --- a/README.md +++ b/README.md @@ -29,32 +29,27 @@ Default support is in bold type. - [Google(Gmail)](https://gmail.com/) : _TLSv1.3_ draft 23, **28** - [NSS TLS 1.3(Mozilla)](https://tls13.crypto.mozilla.org/) : _TLSv1.3_ draft **28** -[Compatible OpenSSL-1.1.1-pre10-dev (OpenSSL, 22668 commits)](https://github.com/openssl/openssl/tree/2fe3e2b68272e803a6e35259a49919d57205418b) +[Compatible OpenSSL-1.1.1 (OpenSSL, 22764 commits)](https://github.com/openssl/openssl/tree/1708e3e85b4a86bae26860aa5d2913fc8eff6086) ## Patch files You can find the _OpenSSL 1.1.0h_ patch is [here.](https://gitlab.com/buik/openssl/blob/openssl-patch/openssl-1.1/OpenSSL1.1h-equal-preference-cipher-groups.patch) Here is the basic patch content. -- Support TLS 1.3 draft 23 + 26 + 28 **(Pre9~10) + final** (Not support pre2 - 26, 28, final) - - Server: draft 23 + 26 + 28 - - Client: draft 23 + 26 + 27 + 28 - - (pre9~10)Server: draft 23 + 26 + 28 + final - - (pre9~10)Client: draft 23 + 26 + 27 + 28 + final +- Support TLS 1.3 draft 23 + 26 + 28 + final + - Server: draft 23 + 26 + 28 + final + - Client: draft 23 + 26 + 27 + 28 + final - BoringSSL's Equal Preference Patch - Weak 3DES and not using ECDHE ciphers is not used in TLSv1.1 or later. | Patch file name | Patch list | | :--- | :--- | -| openssl-equal-pre2.patch | **_Not support_** draft **26, 28**. | -| openssl-equal-pre7.patch
openssl-equal-pre8.patch | TLS 1.3 cipher settings **_can not_** be changed on _nginx_. | -| openssl-equal-pre7_ciphers.patch
openssl-equal-pre8_ciphers.patch | TLS 1.3 cipher settings **_can_** be changed on _nginx_. | -| openssl-equal-pre9.patch
openssl-equal-pre10.patch | Support **final (TLS 1.3)**, TLS 1.3 cipher settings **_can not_** be changed on _nginx_. | -| openssl-equal-pre9_ciphers.patch
openssl-equal-pre10_ciphers.patch | Support **final (TLS 1.3)**, TLS 1.3 cipher settings **_can_** be changed on _nginx_. | +| openssl-equal-1.1.1.patch | Support **final (TLS 1.3)**, TLS 1.3 cipher settings **_can not_** be changed on _nginx_. | +| openssl-equal-1.1.1_ciphers.patch | Support **final (TLS 1.3)**, TLS 1.3 cipher settings **_can_** be changed on _nginx_. | **The "_ciphers" patch file is a temporary change to the TLS 1.3 configuration.** -Example of setting TLS 1.3 cipher in nginx (pre7 or higher): +Example of setting TLS 1.3 cipher in nginx: | Example | Ciphers | | :--- | :--- | @@ -118,17 +113,12 @@ ssl_ecdh_curve X25519:P-256:P-384; ssl_prefer_server_ciphers on; ``` -### OpenSSL-1.1.1-pre2 ciphers (draft 23) -``` -[TLS13-AES-128-GCM-SHA256|TLS13-AES-256-GCM-SHA384|TLS13-CHACHA20-POLY1305-SHA256]:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES -``` - -### OpenSSL-1.1.1-pre7 - 10 ciphers (draft 23, 26, 28, **(pre9-10) - final**) +### OpenSSL-1.1.1 ciphers (draft 23, 26, 28, final) ``` [EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES ``` -### OpenSSL-1.1.1-pre7 - 10_ciphers ciphers (draft 23, 26, 28, **(pre9-10) - final**) +### OpenSSL-1.1.1_ciphers ciphers (draft 23, 26, 28, final) ``` [TLS13+AESGCM+AES128|TLS13+AESGCM+AES256|TLS13+CHACHA20]:[EECDH+ECDSA+AESGCM+AES128|EECDH+ECDSA+CHACHA20]:EECDH+ECDSA+AESGCM+AES256:EECDH+ECDSA+AES128+SHA:EECDH+ECDSA+AES256+SHA:[EECDH+aRSA+AESGCM+AES128|EECDH+aRSA+CHACHA20]:EECDH+aRSA+AESGCM+AES256:EECDH+aRSA+AES128+SHA:EECDH+aRSA+AES256+SHA:RSA+AES128+SHA:RSA+AES256+SHA:RSA+3DES ``` diff --git a/openssl-equal-pre10.patch b/openssl-equal-1.1.1.patch similarity index 100% rename from openssl-equal-pre10.patch rename to openssl-equal-1.1.1.patch diff --git a/openssl-equal-pre10_ciphers.patch b/openssl-equal-1.1.1_ciphers.patch similarity index 100% rename from openssl-equal-pre10_ciphers.patch rename to openssl-equal-1.1.1_ciphers.patch diff --git a/openssl-equal-pre2.patch b/openssl-equal-pre2.patch deleted file mode 100644 index ea8f3f3..0000000 --- a/openssl-equal-pre2.patch +++ /dev/null @@ -1,1026 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 129f76600f..1fe218770a 100644 ---- a/doc/man1/ciphers.pod -+++ b/doc/man1/ciphers.pod -@@ -405,6 +405,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 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 1a02268846..a3b58191e3 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -575,6 +575,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_SERVER 284 - # define SSL_R_NO_APPLICATION_PROTOCOL 235 -@@ -700,9 +702,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 8f0d3e12d1..ab87ca05a6 100644 ---- a/ssl/s3_lib.c -+++ b/ssl/s3_lib.c -@@ -82,7 +82,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, -@@ -147,7 +147,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, -@@ -211,7 +211,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, -@@ -4085,6 +4085,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 -@@ -4094,15 +4105,23 @@ 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; -+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow; -+ int i, ii, ok, safari_ec; - unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0; --#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 */ - -@@ -4129,54 +4148,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; - } - -@@ -4188,14 +4166,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 -@@ -4217,10 +4197,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); -@@ -4237,6 +4217,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) { -@@ -4244,21 +4232,38 @@ 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 (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, ii); -+ ret = sk_SSL_CIPHER_value(allow, group_min); - continue; - } --#endif -- ret = sk_SSL_CIPHER_value(allow, ii); -+ 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 d31aeb7783..8db2ffe005 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -189,6 +189,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; - } - -@@ -1274,17 +1332,19 @@ static int check_suiteb_cipher_list(const SSL_METHOD *meth, CERT *c, - } - #endif - --STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK_OF(SSL_CIPHER) -- **cipher_list, STACK_OF(SSL_CIPHER) -- **cipher_list_by_id, -- const char *rule_str, CERT *c) -+STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, -+ 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; - uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac; -- STACK_OF(SSL_CIPHER) *cipherstack, *tmp_cipher_list; -+ STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = 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. -@@ -1333,16 +1393,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - * 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); - - /* -@@ -1351,13 +1411,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - * 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); - - /* -@@ -1365,16 +1425,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - * 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); - - /* -@@ -1390,7 +1450,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - * 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); - - /* -@@ -1406,15 +1466,15 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - * 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. -@@ -1428,9 +1488,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - 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, -@@ -1455,19 +1514,19 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - - 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; - - /* - * The cipher selection for the list is done. The ciphers are added -@@ -1475,32 +1534,65 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, STACK - */ - 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 */ -+ co_list = NULL; - - tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); -- if (tmp_cipher_list == NULL) { -- sk_SSL_CIPHER_free(cipherstack); -- return NULL; -+ if (tmp_cipher_list == NULL) -+ 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; -+ -+ if (cipher_list_by_id != NULL) { -+ if (*cipher_list_by_id != NULL) -+ sk_SSL_CIPHER_free(*cipher_list_by_id); -+ *cipher_list_by_id = tmp_cipher_list; -+ tmp_cipher_list = NULL; -+ (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, -+ ssl_cipher_ptr_id_cmp); -+ sk_SSL_CIPHER_sort(*cipher_list_by_id); -+ } else { -+ sk_SSL_CIPHER_free(tmp_cipher_list); -+ tmp_cipher_list = NULL; - } -- sk_SSL_CIPHER_free(*cipher_list); -- *cipher_list = cipherstack; -- if (*cipher_list_by_id != NULL) -- sk_SSL_CIPHER_free(*cipher_list_by_id); -- *cipher_list_by_id = tmp_cipher_list; -- (void)sk_SSL_CIPHER_set_cmp_func(*cipher_list_by_id, ssl_cipher_ptr_id_cmp); -- -- sk_SSL_CIPHER_sort(*cipher_list_by_id); -+ - 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 (tmp_cipher_list) -+ sk_SSL_CIPHER_free(tmp_cipher_list); -+ 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 f0bde60994..35e804e308 100644 ---- a/ssl/ssl_err.c -+++ b/ssl/ssl_err.c -@@ -931,6 +931,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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_SERVER), "not server"}, -@@ -1155,11 +1158,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 59b507e788..3bd2af95ea 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1113,6 +1113,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; -@@ -1154,7 +1219,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); - - /* Make the next call work :-) */ -@@ -2434,9 +2500,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; -@@ -2510,8 +2576,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; - } - -@@ -2918,7 +2984,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) - if (!ssl_create_cipher_list(ret->method, - &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; - } -@@ -3061,7 +3127,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); - ssl_cert_free(a->cert); - sk_X509_NAME_pop_free(a->ca_names, X509_NAME_free); -@@ -3672,13 +3738,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 0dd2a7b727..c05ac8b797 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -732,9 +732,46 @@ DEFINE_LHASH_OF(X509_NAME); - - # define TLSEXT_KEYNAME_LENGTH 16 - -+/* 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; - struct x509_store_st /* X509_STORE */ *cert_store; -@@ -1090,7 +1127,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- STACK_OF(SSL_CIPHER) *cipher_list; -+ struct ssl_cipher_preference_list_st *cipher_list; - STACK_OF(SSL_CIPHER) *cipher_list_by_id; - /* - * These are the ones being used, the ones in SSL_SESSION are the ones to -@@ -2182,17 +2219,23 @@ DECLARE_OBJ_BSEARCH_GLOBAL_CMP_FN(SSL_CIPHER, SSL_CIPHER, ssl_cipher_id); - __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 *meth, -- STACK_OF(SSL_CIPHER) **pref, -- STACK_OF(SSL_CIPHER) -- **sorted, -+ struct ssl_cipher_preference_list_st **pref, -+ STACK_OF(SSL_CIPHER) **sorted, - const char *rule_str, -- CERT *c); -+ CERT *c); - __owur int ssl_cache_cipherlist(SSL *s, PACKET *cipher_suites, int sslv2format); - __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites, - STACK_OF(SSL_CIPHER) **skp, - 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, -@@ -2275,8 +2318,8 @@ void ssl3_free_digest_list(SSL *s); - __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); -+ STACK_OF(SSL_CIPHER) *clnt, -+ 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 d3358196d5..506d69487b 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1676,7 +1676,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, -@@ -1857,7 +1857,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->session->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, -@@ -1866,8 +1866,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2169,7 +2170,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, diff --git a/openssl-equal-pre7.patch b/openssl-equal-pre7.patch deleted file mode 100644 index 28d181e..0000000 --- a/openssl-equal-pre7.patch +++ /dev/null @@ -1,1165 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 3786e9a028..8dd0d2c028 100644 ---- a/doc/man1/ciphers.pod -+++ b/doc/man1/ciphers.pod -@@ -418,6 +418,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 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 db0a2d5d82..a26cd1cd82 100644 ---- a/include/openssl/ssl.h -+++ b/include/openssl/ssl.h -@@ -174,12 +174,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 8e395cdd2d..700d7b7b4e 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -591,6 +591,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_REPLACING_CERTIFICATE 289 - # define SSL_R_NOT_SERVER 284 -@@ -719,9 +721,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/include/openssl/tls1.h b/include/openssl/tls1.h -index 37bdc7da43..894801bb4a 100644 ---- a/include/openssl/tls1.h -+++ b/include/openssl/tls1.h -@@ -31,9 +31,11 @@ extern "C" { - # define TLS_MAX_VERSION TLS1_3_VERSION - - /* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */ -+# define TLS1_3_VERSION_DRAFT_23 0x7f17 - # define TLS1_3_VERSION_DRAFT_26 0x7f1a - # define TLS1_3_VERSION_DRAFT_27 0x7f1b - # define TLS1_3_VERSION_DRAFT 0x7f1c -+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)" - # define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)" - # define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)" - # define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)" -diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c -index 8822ca25c3..63ecafe373 100644 ---- a/ssl/record/ssl3_record_tls13.c -+++ b/ssl/record/ssl3_record_tls13.c -@@ -167,8 +167,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) - if (((alg_enc & SSL_AESCCM) != 0 - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) -- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -- sizeof(recheader)) <= 0 -+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23 -+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -+ sizeof(recheader)) <= 0) - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 354769b0c1..ef48c9b312 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, -@@ -4095,6 +4095,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 -@@ -4104,16 +4115,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 */ - -@@ -4140,54 +4159,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; - } - -@@ -4218,14 +4196,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 -@@ -4247,10 +4227,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); -@@ -4267,6 +4247,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) { -@@ -4274,14 +4262,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); - -@@ -4293,13 +4274,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 9011e42fa8..8aa922d426 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -190,6 +190,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; - -@@ -682,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++; - } - -@@ -775,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; -@@ -784,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) -@@ -863,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 */ -@@ -870,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 */ -@@ -881,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) -@@ -948,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; -@@ -963,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; - -@@ -974,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; - } -@@ -1027,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; - } -@@ -1206,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++; -@@ -1216,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; - } - -@@ -1380,7 +1438,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1393,7 +1451,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -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 bce203654a..31b55997a2 100644 ---- a/ssl/ssl_err.c -+++ b/ssl/ssl_err.c -@@ -956,6 +956,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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), -@@ -1186,11 +1189,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 22f729c284..c57c56e39a 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1108,6 +1108,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; -@@ -1148,7 +1213,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); - -@@ -2431,9 +2497,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; -@@ -2507,8 +2573,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; - } - -@@ -2932,7 +2998,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; - } -@@ -3095,7 +3161,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); -@@ -3747,13 +3813,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 4aec810179..d251ee178f 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -741,9 +741,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 */ -@@ -1120,7 +1157,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- 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; -@@ -2224,7 +2261,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, - __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str); - __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); -@@ -2234,6 +2271,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, -@@ -2316,7 +2360,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/extensions_clnt.c b/ssl/statem/extensions_clnt.c -index cc4563b357..4fb02935e9 100644 ---- a/ssl/statem/extensions_clnt.c -+++ b/ssl/statem/extensions_clnt.c -@@ -540,7 +540,8 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, - if (currv == TLS1_3_VERSION) { - if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) - || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27) -- || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26)) { -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, - ERR_R_INTERNAL_ERROR); -@@ -1793,8 +1794,11 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, - /* TODO(TLS1.3): Remove this before release */ - if (version == TLS1_3_VERSION_DRAFT - || version == TLS1_3_VERSION_DRAFT_27 -- || version == TLS1_3_VERSION_DRAFT_26) -+ || version == TLS1_3_VERSION_DRAFT_26 -+ || version == TLS1_3_VERSION_DRAFT_23) { -+ s->version_draft = version; - version = TLS1_3_VERSION; -+ } - - /* - * The only protocol version we support which is valid in this extension in -diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c -index 91d304e2b4..38a1684793 100644 ---- a/ssl/statem/statem_lib.c -+++ b/ssl/statem/statem_lib.c -@@ -1708,8 +1708,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - while (PACKET_get_net_2(&versionslist, &candidate_vers)) { - /* TODO(TLS1.3): Remove this before release */ - if (candidate_vers == TLS1_3_VERSION_DRAFT -- || candidate_vers == TLS1_3_VERSION_DRAFT_27 -- || candidate_vers == TLS1_3_VERSION_DRAFT_26) { -+ || candidate_vers == TLS1_3_VERSION_DRAFT_26 -+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) { - if (best_vers == TLS1_3_VERSION - && orig_candidate > candidate_vers) - continue; -diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c -index ce8cec185a..1a12a9c1a0 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1708,7 +1708,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, -@@ -1889,7 +1889,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->session->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, -@@ -1898,8 +1898,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2211,7 +2212,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, -diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c -index 4d052d0705..15f7f76e6e 100644 ---- a/ssl/t1_trce.c -+++ b/ssl/t1_trce.c -@@ -66,6 +66,7 @@ static const ssl_trace_tbl ssl_version_tbl[] = { - {TLS1_2_VERSION, "TLS 1.2"}, - {TLS1_3_VERSION, "TLS 1.3"}, - /* TODO(TLS1.3): Remove these lines before release */ -+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23}, - {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26}, - {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27}, - {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT}, -@@ -645,6 +646,7 @@ static int ssl_print_version(BIO *bio, int indent, const char *name, - if (version != NULL) { - /* TODO(TLS1.3): Remove the draft conditional here before release */ - switch(vers) { -+ case TLS1_3_VERSION_DRAFT_23: - case TLS1_3_VERSION_DRAFT_26: - case TLS1_3_VERSION_DRAFT_27: - case TLS1_3_VERSION_DRAFT: diff --git a/openssl-equal-pre7_ciphers.patch b/openssl-equal-pre7_ciphers.patch deleted file mode 100644 index cc59d3f..0000000 --- a/openssl-equal-pre7_ciphers.patch +++ /dev/null @@ -1,1200 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 3786e9a028..8dd0d2c028 100644 ---- a/doc/man1/ciphers.pod -+++ b/doc/man1/ciphers.pod -@@ -418,6 +418,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 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 8e395cdd2d..700d7b7b4e 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -591,6 +591,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_REPLACING_CERTIFICATE 289 - # define SSL_R_NOT_SERVER 284 -@@ -719,9 +721,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/include/openssl/tls1.h b/include/openssl/tls1.h -index 37bdc7da43..894801bb4a 100644 ---- a/include/openssl/tls1.h -+++ b/include/openssl/tls1.h -@@ -31,9 +31,11 @@ extern "C" { - # define TLS_MAX_VERSION TLS1_3_VERSION - - /* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */ -+# define TLS1_3_VERSION_DRAFT_23 0x7f17 - # define TLS1_3_VERSION_DRAFT_26 0x7f1a - # define TLS1_3_VERSION_DRAFT_27 0x7f1b - # define TLS1_3_VERSION_DRAFT 0x7f1c -+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)" - # define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)" - # define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)" - # define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)" -diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c -index 8822ca25c3..63ecafe373 100644 ---- a/ssl/record/ssl3_record_tls13.c -+++ b/ssl/record/ssl3_record_tls13.c -@@ -167,8 +167,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) - if (((alg_enc & SSL_AESCCM) != 0 - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) -- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -- sizeof(recheader)) <= 0 -+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23 -+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -+ sizeof(recheader)) <= 0) - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 354769b0c1..e22bf6212b 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, -@@ -4095,6 +4101,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 -@@ -4104,16 +4121,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 */ - -@@ -4140,54 +4165,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; - } - -@@ -4218,14 +4202,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 -@@ -4247,10 +4233,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); -@@ -4267,6 +4253,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) { -@@ -4274,14 +4268,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); - -@@ -4293,13 +4280,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 9011e42fa8..e89d1482b2 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -190,6 +190,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; - -@@ -294,6 +295,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}, -@@ -682,6 +684,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++; - } - -@@ -775,8 +778,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; -@@ -784,9 +787,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) -@@ -863,6 +866,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 */ -@@ -870,6 +874,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 */ -@@ -881,6 +886,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) -@@ -948,8 +954,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; -@@ -963,7 +969,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; - -@@ -974,18 +980,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; - } -@@ -1010,7 +1064,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 == '=')) -@@ -1027,7 +1081,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; - } -@@ -1206,8 +1260,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++; -@@ -1216,6 +1270,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; - } - -@@ -1380,7 +1439,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1393,7 +1452,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -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 bce203654a..31b55997a2 100644 ---- a/ssl/ssl_err.c -+++ b/ssl/ssl_err.c -@@ -956,6 +956,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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), -@@ -1186,11 +1189,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 22f729c284..c57c56e39a 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1108,6 +1108,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; -@@ -1148,7 +1213,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); - -@@ -2431,9 +2497,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; -@@ -2507,8 +2573,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; - } - -@@ -2932,7 +2998,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; - } -@@ -3095,7 +3161,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); -@@ -3747,13 +3813,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 4aec810179..d251ee178f 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -741,9 +741,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 */ -@@ -1120,7 +1157,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- 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; -@@ -2224,7 +2261,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, - __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str); - __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); -@@ -2234,6 +2271,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, -@@ -2316,7 +2360,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/extensions_clnt.c b/ssl/statem/extensions_clnt.c -index cc4563b357..4fb02935e9 100644 ---- a/ssl/statem/extensions_clnt.c -+++ b/ssl/statem/extensions_clnt.c -@@ -540,7 +540,8 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, - if (currv == TLS1_3_VERSION) { - if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) - || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27) -- || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26)) { -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, - ERR_R_INTERNAL_ERROR); -@@ -1793,8 +1794,11 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, - /* TODO(TLS1.3): Remove this before release */ - if (version == TLS1_3_VERSION_DRAFT - || version == TLS1_3_VERSION_DRAFT_27 -- || version == TLS1_3_VERSION_DRAFT_26) -+ || version == TLS1_3_VERSION_DRAFT_26 -+ || version == TLS1_3_VERSION_DRAFT_23) { -+ s->version_draft = version; - version = TLS1_3_VERSION; -+ } - - /* - * The only protocol version we support which is valid in this extension in -diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c -index 91d304e2b4..38a1684793 100644 ---- a/ssl/statem/statem_lib.c -+++ b/ssl/statem/statem_lib.c -@@ -1708,8 +1708,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - while (PACKET_get_net_2(&versionslist, &candidate_vers)) { - /* TODO(TLS1.3): Remove this before release */ - if (candidate_vers == TLS1_3_VERSION_DRAFT -- || candidate_vers == TLS1_3_VERSION_DRAFT_27 -- || candidate_vers == TLS1_3_VERSION_DRAFT_26) { -+ || candidate_vers == TLS1_3_VERSION_DRAFT_26 -+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) { - if (best_vers == TLS1_3_VERSION - && orig_candidate > candidate_vers) - continue; -diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c -index ce8cec185a..1a12a9c1a0 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1708,7 +1708,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, -@@ -1889,7 +1889,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->session->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, -@@ -1898,8 +1898,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2211,7 +2212,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, -diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c -index 4d052d0705..15f7f76e6e 100644 ---- a/ssl/t1_trce.c -+++ b/ssl/t1_trce.c -@@ -66,6 +66,7 @@ static const ssl_trace_tbl ssl_version_tbl[] = { - {TLS1_2_VERSION, "TLS 1.2"}, - {TLS1_3_VERSION, "TLS 1.3"}, - /* TODO(TLS1.3): Remove these lines before release */ -+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23}, - {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26}, - {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27}, - {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT}, -@@ -645,6 +646,7 @@ static int ssl_print_version(BIO *bio, int indent, const char *name, - if (version != NULL) { - /* TODO(TLS1.3): Remove the draft conditional here before release */ - switch(vers) { -+ case TLS1_3_VERSION_DRAFT_23: - case TLS1_3_VERSION_DRAFT_26: - case TLS1_3_VERSION_DRAFT_27: - case TLS1_3_VERSION_DRAFT: diff --git a/openssl-equal-pre8.patch b/openssl-equal-pre8.patch deleted file mode 100644 index 17719ea..0000000 --- a/openssl-equal-pre8.patch +++ /dev/null @@ -1,1165 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 3786e9a028..8dd0d2c028 100644 ---- a/doc/man1/ciphers.pod -+++ b/doc/man1/ciphers.pod -@@ -418,6 +418,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 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 280250ad83..9a61045186 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 8e395cdd2d..700d7b7b4e 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -591,6 +591,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_REPLACING_CERTIFICATE 289 - # define SSL_R_NOT_SERVER 284 -@@ -719,9 +721,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/include/openssl/tls1.h b/include/openssl/tls1.h -index 37bdc7da43..894801bb4a 100644 ---- a/include/openssl/tls1.h -+++ b/include/openssl/tls1.h -@@ -31,9 +31,11 @@ extern "C" { - # define TLS_MAX_VERSION TLS1_3_VERSION - - /* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */ -+# define TLS1_3_VERSION_DRAFT_23 0x7f17 - # define TLS1_3_VERSION_DRAFT_26 0x7f1a - # define TLS1_3_VERSION_DRAFT_27 0x7f1b - # define TLS1_3_VERSION_DRAFT 0x7f1c -+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)" - # define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)" - # define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)" - # define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)" -diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c -index 8822ca25c3..63ecafe373 100644 ---- a/ssl/record/ssl3_record_tls13.c -+++ b/ssl/record/ssl3_record_tls13.c -@@ -167,8 +167,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) - if (((alg_enc & SSL_AESCCM) != 0 - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) -- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -- sizeof(recheader)) <= 0 -+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23 -+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -+ sizeof(recheader)) <= 0) - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 354769b0c1..ef48c9b312 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, -@@ -4095,6 +4095,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 -@@ -4104,16 +4115,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 */ - -@@ -4140,54 +4159,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; - } - -@@ -4218,14 +4196,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 -@@ -4247,10 +4227,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); -@@ -4267,6 +4247,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) { -@@ -4274,14 +4262,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); - -@@ -4293,13 +4274,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 9011e42fa8..8aa922d426 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -190,6 +190,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; - -@@ -682,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++; - } - -@@ -775,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; -@@ -784,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) -@@ -863,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 */ -@@ -870,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 */ -@@ -881,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) -@@ -948,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; -@@ -963,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; - -@@ -974,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; - } -@@ -1027,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; - } -@@ -1206,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++; -@@ -1216,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; - } - -@@ -1380,7 +1438,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1393,7 +1451,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -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 bce203654a..31b55997a2 100644 ---- a/ssl/ssl_err.c -+++ b/ssl/ssl_err.c -@@ -956,6 +956,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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), -@@ -1186,11 +1189,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 22f729c284..c57c56e39a 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1108,6 +1108,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; -@@ -1148,7 +1213,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); - -@@ -2431,9 +2497,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; -@@ -2507,8 +2573,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; - } - -@@ -2932,7 +2998,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; - } -@@ -3095,7 +3161,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); -@@ -3747,13 +3813,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 86c250b695..757aa47f23 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -736,9 +736,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 */ -@@ -1115,7 +1152,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- 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; -@@ -2221,7 +2258,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, - __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str); - __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); -@@ -2231,6 +2268,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, -@@ -2313,7 +2357,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/extensions_clnt.c b/ssl/statem/extensions_clnt.c -index cc4563b357..4fb02935e9 100644 ---- a/ssl/statem/extensions_clnt.c -+++ b/ssl/statem/extensions_clnt.c -@@ -540,7 +540,8 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, - if (currv == TLS1_3_VERSION) { - if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) - || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27) -- || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26)) { -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, - ERR_R_INTERNAL_ERROR); -@@ -1793,8 +1794,11 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, - /* TODO(TLS1.3): Remove this before release */ - if (version == TLS1_3_VERSION_DRAFT - || version == TLS1_3_VERSION_DRAFT_27 -- || version == TLS1_3_VERSION_DRAFT_26) -+ || version == TLS1_3_VERSION_DRAFT_26 -+ || version == TLS1_3_VERSION_DRAFT_23) { -+ s->version_draft = version; - version = TLS1_3_VERSION; -+ } - - /* - * The only protocol version we support which is valid in this extension in -diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c -index 91d304e2b4..38a1684793 100644 ---- a/ssl/statem/statem_lib.c -+++ b/ssl/statem/statem_lib.c -@@ -1708,8 +1708,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - while (PACKET_get_net_2(&versionslist, &candidate_vers)) { - /* TODO(TLS1.3): Remove this before release */ - if (candidate_vers == TLS1_3_VERSION_DRAFT -- || candidate_vers == TLS1_3_VERSION_DRAFT_27 -- || candidate_vers == TLS1_3_VERSION_DRAFT_26) { -+ || candidate_vers == TLS1_3_VERSION_DRAFT_26 -+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) { - if (best_vers == TLS1_3_VERSION - && orig_candidate > candidate_vers) - continue; -diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c -index c2976b7a32..5a0afcf5d7 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1710,7 +1710,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, -@@ -1891,7 +1891,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->session->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, -@@ -1900,8 +1900,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2213,7 +2214,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, -diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c -index 4d052d0705..15f7f76e6e 100644 ---- a/ssl/t1_trce.c -+++ b/ssl/t1_trce.c -@@ -66,6 +66,7 @@ static const ssl_trace_tbl ssl_version_tbl[] = { - {TLS1_2_VERSION, "TLS 1.2"}, - {TLS1_3_VERSION, "TLS 1.3"}, - /* TODO(TLS1.3): Remove these lines before release */ -+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23}, - {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26}, - {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27}, - {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT}, -@@ -645,6 +646,7 @@ static int ssl_print_version(BIO *bio, int indent, const char *name, - if (version != NULL) { - /* TODO(TLS1.3): Remove the draft conditional here before release */ - switch(vers) { -+ case TLS1_3_VERSION_DRAFT_23: - case TLS1_3_VERSION_DRAFT_26: - case TLS1_3_VERSION_DRAFT_27: - case TLS1_3_VERSION_DRAFT: diff --git a/openssl-equal-pre8_ciphers.patch b/openssl-equal-pre8_ciphers.patch deleted file mode 100644 index 6f26cc5..0000000 --- a/openssl-equal-pre8_ciphers.patch +++ /dev/null @@ -1,1200 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 3786e9a028..8dd0d2c028 100644 ---- a/doc/man1/ciphers.pod -+++ b/doc/man1/ciphers.pod -@@ -418,6 +418,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 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 8e395cdd2d..700d7b7b4e 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -591,6 +591,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_REPLACING_CERTIFICATE 289 - # define SSL_R_NOT_SERVER 284 -@@ -719,9 +721,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/include/openssl/tls1.h b/include/openssl/tls1.h -index 37bdc7da43..894801bb4a 100644 ---- a/include/openssl/tls1.h -+++ b/include/openssl/tls1.h -@@ -31,9 +31,11 @@ extern "C" { - # define TLS_MAX_VERSION TLS1_3_VERSION - - /* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */ -+# define TLS1_3_VERSION_DRAFT_23 0x7f17 - # define TLS1_3_VERSION_DRAFT_26 0x7f1a - # define TLS1_3_VERSION_DRAFT_27 0x7f1b - # define TLS1_3_VERSION_DRAFT 0x7f1c -+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)" - # define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)" - # define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)" - # define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)" -diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c -index 8822ca25c3..63ecafe373 100644 ---- a/ssl/record/ssl3_record_tls13.c -+++ b/ssl/record/ssl3_record_tls13.c -@@ -167,8 +167,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) - if (((alg_enc & SSL_AESCCM) != 0 - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) -- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -- sizeof(recheader)) <= 0 -+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23 -+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -+ sizeof(recheader)) <= 0) - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 354769b0c1..e22bf6212b 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, -@@ -4095,6 +4101,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 -@@ -4104,16 +4121,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 */ - -@@ -4140,54 +4165,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; - } - -@@ -4218,14 +4202,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 -@@ -4247,10 +4233,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); -@@ -4267,6 +4253,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) { -@@ -4274,14 +4268,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); - -@@ -4293,13 +4280,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 9011e42fa8..e89d1482b2 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -190,6 +190,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; - -@@ -294,6 +295,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}, -@@ -682,6 +684,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++; - } - -@@ -775,8 +778,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; -@@ -784,9 +787,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) -@@ -863,6 +866,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 */ -@@ -870,6 +874,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 */ -@@ -881,6 +886,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) -@@ -948,8 +954,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; -@@ -963,7 +969,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; - -@@ -974,18 +980,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; - } -@@ -1010,7 +1064,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 == '=')) -@@ -1027,7 +1081,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; - } -@@ -1206,8 +1260,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++; -@@ -1216,6 +1270,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; - } - -@@ -1380,7 +1439,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1393,7 +1452,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -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 bce203654a..31b55997a2 100644 ---- a/ssl/ssl_err.c -+++ b/ssl/ssl_err.c -@@ -956,6 +956,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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), -@@ -1186,11 +1189,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 22f729c284..c57c56e39a 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1108,6 +1108,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; -@@ -1148,7 +1213,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); - -@@ -2431,9 +2497,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; -@@ -2507,8 +2573,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; - } - -@@ -2932,7 +2998,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; - } -@@ -3095,7 +3161,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); -@@ -3747,13 +3813,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 86c250b695..757aa47f23 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -736,9 +736,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 */ -@@ -1115,7 +1152,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- 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; -@@ -2221,7 +2258,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, - __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str); - __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); -@@ -2231,6 +2268,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, -@@ -2313,7 +2357,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/extensions_clnt.c b/ssl/statem/extensions_clnt.c -index cc4563b357..4fb02935e9 100644 ---- a/ssl/statem/extensions_clnt.c -+++ b/ssl/statem/extensions_clnt.c -@@ -540,7 +540,8 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, - if (currv == TLS1_3_VERSION) { - if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) - || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27) -- || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26)) { -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, - ERR_R_INTERNAL_ERROR); -@@ -1793,8 +1794,11 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, - /* TODO(TLS1.3): Remove this before release */ - if (version == TLS1_3_VERSION_DRAFT - || version == TLS1_3_VERSION_DRAFT_27 -- || version == TLS1_3_VERSION_DRAFT_26) -+ || version == TLS1_3_VERSION_DRAFT_26 -+ || version == TLS1_3_VERSION_DRAFT_23) { -+ s->version_draft = version; - version = TLS1_3_VERSION; -+ } - - /* - * The only protocol version we support which is valid in this extension in -diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c -index 91d304e2b4..38a1684793 100644 ---- a/ssl/statem/statem_lib.c -+++ b/ssl/statem/statem_lib.c -@@ -1708,8 +1708,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - while (PACKET_get_net_2(&versionslist, &candidate_vers)) { - /* TODO(TLS1.3): Remove this before release */ - if (candidate_vers == TLS1_3_VERSION_DRAFT -- || candidate_vers == TLS1_3_VERSION_DRAFT_27 -- || candidate_vers == TLS1_3_VERSION_DRAFT_26) { -+ || candidate_vers == TLS1_3_VERSION_DRAFT_26 -+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) { - if (best_vers == TLS1_3_VERSION - && orig_candidate > candidate_vers) - continue; -diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c -index c2976b7a32..5a0afcf5d7 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1710,7 +1710,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, -@@ -1891,7 +1891,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->session->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, -@@ -1900,8 +1900,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2213,7 +2214,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, -diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c -index 4d052d0705..15f7f76e6e 100644 ---- a/ssl/t1_trce.c -+++ b/ssl/t1_trce.c -@@ -66,6 +66,7 @@ static const ssl_trace_tbl ssl_version_tbl[] = { - {TLS1_2_VERSION, "TLS 1.2"}, - {TLS1_3_VERSION, "TLS 1.3"}, - /* TODO(TLS1.3): Remove these lines before release */ -+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23}, - {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26}, - {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27}, - {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT}, -@@ -645,6 +646,7 @@ static int ssl_print_version(BIO *bio, int indent, const char *name, - if (version != NULL) { - /* TODO(TLS1.3): Remove the draft conditional here before release */ - switch(vers) { -+ case TLS1_3_VERSION_DRAFT_23: - case TLS1_3_VERSION_DRAFT_26: - case TLS1_3_VERSION_DRAFT_27: - case TLS1_3_VERSION_DRAFT: diff --git a/openssl-equal-pre9.patch b/openssl-equal-pre9.patch deleted file mode 100644 index c58807d..0000000 --- a/openssl-equal-pre9.patch +++ /dev/null @@ -1,1273 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 3aea982384..3c93eba0bf 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 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 eb689c1c36..3191b68efe 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 87b295c9f9..d118d8e864 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -596,6 +596,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_REPLACING_CERTIFICATE 289 - # define SSL_R_NOT_SERVER 284 -@@ -726,9 +728,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/include/openssl/tls1.h b/include/openssl/tls1.h -index 2e46cf80d3..0accc837a3 100644 ---- a/include/openssl/tls1.h -+++ b/include/openssl/tls1.h -@@ -30,6 +30,16 @@ extern "C" { - # define TLS1_3_VERSION 0x0304 - # define TLS_MAX_VERSION TLS1_3_VERSION - -+/* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */ -+# define TLS1_3_VERSION_DRAFT_23 0x7f17 -+# define TLS1_3_VERSION_DRAFT_26 0x7f1a -+# define TLS1_3_VERSION_DRAFT_27 0x7f1b -+# define TLS1_3_VERSION_DRAFT 0x7f1c -+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)" -+# define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)" -+# define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)" -+# define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)" -+ - /* Special value for method supporting multiple versions */ - # define TLS_ANY_VERSION 0x10000 - -diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c -index a11ed483e6..4fd583dd03 100644 ---- a/ssl/record/ssl3_record_tls13.c -+++ b/ssl/record/ssl3_record_tls13.c -@@ -173,8 +173,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) - if (((alg_enc & SSL_AESCCM) != 0 - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) -- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -- sizeof(recheader)) <= 0 -+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23 -+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -+ sizeof(recheader)) <= 0) - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 5ecbc3c554..55c9a7510a 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, -@@ -4104,6 +4104,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 -@@ -4113,16 +4124,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 */ - -@@ -4149,54 +4168,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; - } - -@@ -4227,14 +4205,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 -@@ -4256,10 +4236,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); -@@ -4276,6 +4256,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) { -@@ -4283,14 +4271,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); - -@@ -4302,13 +4283,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 b60cc79a2f..e028151423 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -190,6 +190,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; - -@@ -679,6 +680,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++; - } - -@@ -772,8 +774,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; -@@ -781,9 +783,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) -@@ -860,6 +862,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 */ -@@ -867,6 +870,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 */ -@@ -878,6 +882,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) -@@ -945,8 +950,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; -@@ -960,7 +965,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; - -@@ -971,18 +976,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; - } -@@ -1024,7 +1077,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; - } -@@ -1203,8 +1256,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++; -@@ -1213,6 +1266,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; - } - -@@ -1377,7 +1435,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1390,7 +1448,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1399,17 +1457,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. -@@ -1458,16 +1519,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); - - /* -@@ -1476,13 +1537,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); - - /* -@@ -1490,16 +1551,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); - - /* -@@ -1515,7 +1576,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); - - /* -@@ -1531,15 +1592,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. -@@ -1553,9 +1614,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, -@@ -1580,27 +1640,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; - } - - /* -@@ -1609,26 +1677,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 11331ce41f..cfc770b8d6 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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), -@@ -1199,11 +1202,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 7e8093bcfd..8f50d6d343 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1113,6 +1113,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; -@@ -1153,7 +1218,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); - -@@ -2422,9 +2488,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; -@@ -2498,8 +2564,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; - } - -@@ -2934,7 +3000,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; - } -@@ -3107,7 +3173,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); -@@ -3762,13 +3828,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 362ae1cbe5..bc70199224 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -737,9 +737,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 */ -@@ -1074,6 +1111,8 @@ struct ssl_st { - * DTLS1_VERSION) - */ - int version; -+ /* TODO(TLS1.3): Remove this before release */ -+ int version_draft; - /* SSLv3 */ - const SSL_METHOD *method; - /* -@@ -1132,7 +1171,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- 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; -@@ -2254,7 +2293,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, - __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str); - __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); -@@ -2264,6 +2303,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, -@@ -2347,7 +2393,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/extensions_clnt.c b/ssl/statem/extensions_clnt.c -index 2d5b60a737..39a60a2167 100644 ---- a/ssl/statem/extensions_clnt.c -+++ b/ssl/statem/extensions_clnt.c -@@ -530,8 +530,25 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, - return EXT_RETURN_FAIL; - } - -+ /* -+ * TODO(TLS1.3): There is some discussion on the TLS list as to whether -+ * we should include versions = min_version; currv--) { -- if (!WPACKET_put_bytes_u16(pkt, currv)) { -+ /* TODO(TLS1.3): Remove this first if clause prior to release!! */ -+ if (currv == TLS1_3_VERSION) { -+ if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) { -+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, -+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, -+ ERR_R_INTERNAL_ERROR); -+ return EXT_RETURN_FAIL; -+ } -+ } else if (!WPACKET_put_bytes_u16(pkt, currv)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, - ERR_R_INTERNAL_ERROR); -@@ -1760,6 +1777,15 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, - return 0; - } - -+ /* TODO(TLS1.3): Remove this before release */ -+ if (version == TLS1_3_VERSION_DRAFT -+ || version == TLS1_3_VERSION_DRAFT_27 -+ || version == TLS1_3_VERSION_DRAFT_26 -+ || version == TLS1_3_VERSION_DRAFT_23) { -+ s->version_draft = version; -+ version = TLS1_3_VERSION; -+ } -+ - /* - * The only protocol version we support which is valid in this extension in - * a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else. -diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c -index 295d3e7ee5..00c0ec9c09 100644 ---- a/ssl/statem/extensions_srvr.c -+++ b/ssl/statem/extensions_srvr.c -@@ -897,7 +897,8 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - } - if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions) - || !WPACKET_start_sub_packet_u16(&hrrpkt) -- || !WPACKET_put_bytes_u16(&hrrpkt, s->version) -+ /* TODO(TLS1.3): Fix this before release */ -+ || !WPACKET_put_bytes_u16(&hrrpkt, s->version_draft) - || !WPACKET_close(&hrrpkt)) { - WPACKET_cleanup(&hrrpkt); - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, -@@ -1650,7 +1651,8 @@ EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt, - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) - || !WPACKET_start_sub_packet_u16(pkt) -- || !WPACKET_put_bytes_u16(pkt, s->version) -+ /* TODO(TLS1.3): Update to remove the TLSv1.3 draft indicator */ -+ || !WPACKET_put_bytes_u16(pkt, s->version_draft) - || !WPACKET_close(pkt)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, -diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c -index 38121b7fd2..df0a398340 100644 ---- a/ssl/statem/statem_lib.c -+++ b/ssl/statem/statem_lib.c -@@ -1742,6 +1742,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - unsigned int best_vers = 0; - const SSL_METHOD *best_method = NULL; - PACKET versionslist; -+ /* TODO(TLS1.3): Remove this before release */ -+ unsigned int orig_candidate = 0; - - suppversions->parsed = 1; - -@@ -1763,6 +1765,23 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - return SSL_R_BAD_LEGACY_VERSION; - - while (PACKET_get_net_2(&versionslist, &candidate_vers)) { -+ /* TODO(TLS1.3): Remove this before release */ -+ if (candidate_vers == TLS1_3_VERSION -+ || candidate_vers == TLS1_3_VERSION_DRAFT -+ || candidate_vers == TLS1_3_VERSION_DRAFT_26 -+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) { -+ if (best_vers == TLS1_3_VERSION -+ && (orig_candidate > candidate_vers -+ || orig_candidate == TLS1_3_VERSION)) -+ continue; -+ orig_candidate = candidate_vers; -+ candidate_vers = TLS1_3_VERSION; -+ } -+ /* -+ * TODO(TLS1.3): There is some discussion on the TLS list about -+ * whether to ignore versions version = best_vers; -+ /* TODO(TLS1.3): Remove this before release */ -+ if (best_vers == TLS1_3_VERSION) -+ s->version_draft = orig_candidate; - s->method = best_method; - return 0; - } -diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c -index db5aafe3be..d2912756fe 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1711,7 +1711,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, -@@ -1892,7 +1892,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->session->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, -@@ -1901,8 +1901,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2214,7 +2215,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, -diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c -index b79c776f2d..15f7f76e6e 100644 ---- a/ssl/t1_trce.c -+++ b/ssl/t1_trce.c -@@ -65,6 +65,11 @@ static const ssl_trace_tbl ssl_version_tbl[] = { - {TLS1_1_VERSION, "TLS 1.1"}, - {TLS1_2_VERSION, "TLS 1.2"}, - {TLS1_3_VERSION, "TLS 1.3"}, -+ /* TODO(TLS1.3): Remove these lines before release */ -+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23}, -+ {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26}, -+ {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27}, -+ {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT}, - {DTLS1_VERSION, "DTLS 1.0"}, - {DTLS1_2_VERSION, "DTLS 1.2"}, - {DTLS1_BAD_VER, "DTLS 1.0 (bad)"} -@@ -638,8 +643,19 @@ static int ssl_print_version(BIO *bio, int indent, const char *name, - if (*pmsglen < 2) - return 0; - vers = ((*pmsg)[0] << 8) | (*pmsg)[1]; -- if (version != NULL) -- *version = vers; -+ if (version != NULL) { -+ /* TODO(TLS1.3): Remove the draft conditional here before release */ -+ switch(vers) { -+ case TLS1_3_VERSION_DRAFT_23: -+ case TLS1_3_VERSION_DRAFT_26: -+ case TLS1_3_VERSION_DRAFT_27: -+ case TLS1_3_VERSION_DRAFT: -+ *version = TLS1_3_VERSION; -+ break; -+ default: -+ *version = vers; -+ } -+ } - BIO_indent(bio, indent, 80); - BIO_printf(bio, "%s=0x%x (%s)\n", - name, vers, ssl_trace_str(vers, ssl_version_tbl)); diff --git a/openssl-equal-pre9_ciphers.patch b/openssl-equal-pre9_ciphers.patch deleted file mode 100644 index f05753c..0000000 --- a/openssl-equal-pre9_ciphers.patch +++ /dev/null @@ -1,1308 +0,0 @@ -diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod -index 3aea982384..3c93eba0bf 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 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 87b295c9f9..d118d8e864 100644 ---- a/include/openssl/sslerr.h -+++ b/include/openssl/sslerr.h -@@ -596,6 +596,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_NOT_ON_RECORD_BOUNDARY 182 - # define SSL_R_NOT_REPLACING_CERTIFICATE 289 - # define SSL_R_NOT_SERVER 284 -@@ -726,9 +728,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/include/openssl/tls1.h b/include/openssl/tls1.h -index 2e46cf80d3..0accc837a3 100644 ---- a/include/openssl/tls1.h -+++ b/include/openssl/tls1.h -@@ -30,6 +30,16 @@ extern "C" { - # define TLS1_3_VERSION 0x0304 - # define TLS_MAX_VERSION TLS1_3_VERSION - -+/* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */ -+# define TLS1_3_VERSION_DRAFT_23 0x7f17 -+# define TLS1_3_VERSION_DRAFT_26 0x7f1a -+# define TLS1_3_VERSION_DRAFT_27 0x7f1b -+# define TLS1_3_VERSION_DRAFT 0x7f1c -+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)" -+# define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)" -+# define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)" -+# define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)" -+ - /* Special value for method supporting multiple versions */ - # define TLS_ANY_VERSION 0x10000 - -diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c -index a11ed483e6..4fd583dd03 100644 ---- a/ssl/record/ssl3_record_tls13.c -+++ b/ssl/record/ssl3_record_tls13.c -@@ -173,8 +173,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending) - if (((alg_enc & SSL_AESCCM) != 0 - && EVP_CipherUpdate(ctx, NULL, &lenu, NULL, - (unsigned int)rec->length) <= 0) -- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -- sizeof(recheader)) <= 0 -+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23 -+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader, -+ sizeof(recheader)) <= 0) - || EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input, - (unsigned int)rec->length) <= 0 - || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 -diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c -index 5ecbc3c554..63a6cc6190 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, -@@ -4104,6 +4110,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 -@@ -4113,16 +4130,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 */ - -@@ -4149,54 +4174,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; - } - -@@ -4227,14 +4211,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 -@@ -4256,10 +4242,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); -@@ -4276,6 +4262,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) { -@@ -4283,14 +4277,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); - -@@ -4302,13 +4289,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 b60cc79a2f..205f868a05 100644 ---- a/ssl/ssl_ciph.c -+++ b/ssl/ssl_ciph.c -@@ -190,6 +190,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; - -@@ -294,6 +295,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}, -@@ -679,6 +681,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++; - } - -@@ -772,8 +775,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; -@@ -781,9 +784,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) -@@ -860,6 +863,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 */ -@@ -867,6 +871,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 */ -@@ -878,6 +883,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) -@@ -945,8 +951,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; -@@ -960,7 +966,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; - -@@ -971,18 +977,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; - } -@@ -1007,7 +1061,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 == '=')) -@@ -1024,7 +1078,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; - } -@@ -1203,8 +1257,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++; -@@ -1213,6 +1267,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; - } - -@@ -1377,7 +1436,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) - - if (ret && ctx->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1390,7 +1449,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) - - if (ret && s->cipher_list != NULL) { - /* We already have a cipher_list, so we need to update it */ -- 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); - } - -@@ -1399,17 +1458,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. -@@ -1458,16 +1520,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); - - /* -@@ -1476,13 +1538,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); - - /* -@@ -1490,16 +1552,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); - - /* -@@ -1515,7 +1577,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); - - /* -@@ -1531,15 +1593,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. -@@ -1553,9 +1618,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, -@@ -1580,28 +1644,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 -@@ -1609,26 +1664,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 11331ce41f..cfc770b8d6 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_NOT_ON_RECORD_BOUNDARY), - "not on record boundary"}, - {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE), -@@ -1199,11 +1202,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 7e8093bcfd..8f50d6d343 100644 ---- a/ssl/ssl_lib.c -+++ b/ssl/ssl_lib.c -@@ -1113,6 +1113,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; -@@ -1153,7 +1218,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); - -@@ -2422,9 +2488,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; -@@ -2498,8 +2564,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; - } - -@@ -2934,7 +3000,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; - } -@@ -3107,7 +3173,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); -@@ -3762,13 +3828,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 (s->ca_names != NULL) { -diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h -index 362ae1cbe5..bc70199224 100644 ---- a/ssl/ssl_locl.h -+++ b/ssl/ssl_locl.h -@@ -737,9 +737,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 */ -@@ -1074,6 +1111,8 @@ struct ssl_st { - * DTLS1_VERSION) - */ - int version; -+ /* TODO(TLS1.3): Remove this before release */ -+ int version_draft; - /* SSLv3 */ - const SSL_METHOD *method; - /* -@@ -1132,7 +1171,7 @@ struct ssl_st { - /* Per connection DANE state */ - SSL_DANE dane; - /* crypto */ -- 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; -@@ -2254,7 +2293,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, - __owur int set_ciphersuites(STACK_OF(SSL_CIPHER) **currciphers, const char *str); - __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); -@@ -2264,6 +2303,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, -@@ -2347,7 +2393,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/extensions_clnt.c b/ssl/statem/extensions_clnt.c -index 2d5b60a737..39a60a2167 100644 ---- a/ssl/statem/extensions_clnt.c -+++ b/ssl/statem/extensions_clnt.c -@@ -530,8 +530,25 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt, - return EXT_RETURN_FAIL; - } - -+ /* -+ * TODO(TLS1.3): There is some discussion on the TLS list as to whether -+ * we should include versions = min_version; currv--) { -- if (!WPACKET_put_bytes_u16(pkt, currv)) { -+ /* TODO(TLS1.3): Remove this first if clause prior to release!! */ -+ if (currv == TLS1_3_VERSION) { -+ if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26) -+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) { -+ SSLfatal(s, SSL_AD_INTERNAL_ERROR, -+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, -+ ERR_R_INTERNAL_ERROR); -+ return EXT_RETURN_FAIL; -+ } -+ } else if (!WPACKET_put_bytes_u16(pkt, currv)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS, - ERR_R_INTERNAL_ERROR); -@@ -1760,6 +1777,15 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context, - return 0; - } - -+ /* TODO(TLS1.3): Remove this before release */ -+ if (version == TLS1_3_VERSION_DRAFT -+ || version == TLS1_3_VERSION_DRAFT_27 -+ || version == TLS1_3_VERSION_DRAFT_26 -+ || version == TLS1_3_VERSION_DRAFT_23) { -+ s->version_draft = version; -+ version = TLS1_3_VERSION; -+ } -+ - /* - * The only protocol version we support which is valid in this extension in - * a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else. -diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c -index 295d3e7ee5..00c0ec9c09 100644 ---- a/ssl/statem/extensions_srvr.c -+++ b/ssl/statem/extensions_srvr.c -@@ -897,7 +897,8 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x, - } - if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions) - || !WPACKET_start_sub_packet_u16(&hrrpkt) -- || !WPACKET_put_bytes_u16(&hrrpkt, s->version) -+ /* TODO(TLS1.3): Fix this before release */ -+ || !WPACKET_put_bytes_u16(&hrrpkt, s->version_draft) - || !WPACKET_close(&hrrpkt)) { - WPACKET_cleanup(&hrrpkt); - SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE, -@@ -1650,7 +1651,8 @@ EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt, - - if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions) - || !WPACKET_start_sub_packet_u16(pkt) -- || !WPACKET_put_bytes_u16(pkt, s->version) -+ /* TODO(TLS1.3): Update to remove the TLSv1.3 draft indicator */ -+ || !WPACKET_put_bytes_u16(pkt, s->version_draft) - || !WPACKET_close(pkt)) { - SSLfatal(s, SSL_AD_INTERNAL_ERROR, - SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS, -diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c -index 38121b7fd2..df0a398340 100644 ---- a/ssl/statem/statem_lib.c -+++ b/ssl/statem/statem_lib.c -@@ -1742,6 +1742,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - unsigned int best_vers = 0; - const SSL_METHOD *best_method = NULL; - PACKET versionslist; -+ /* TODO(TLS1.3): Remove this before release */ -+ unsigned int orig_candidate = 0; - - suppversions->parsed = 1; - -@@ -1763,6 +1765,23 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd) - return SSL_R_BAD_LEGACY_VERSION; - - while (PACKET_get_net_2(&versionslist, &candidate_vers)) { -+ /* TODO(TLS1.3): Remove this before release */ -+ if (candidate_vers == TLS1_3_VERSION -+ || candidate_vers == TLS1_3_VERSION_DRAFT -+ || candidate_vers == TLS1_3_VERSION_DRAFT_26 -+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) { -+ if (best_vers == TLS1_3_VERSION -+ && (orig_candidate > candidate_vers -+ || orig_candidate == TLS1_3_VERSION)) -+ continue; -+ orig_candidate = candidate_vers; -+ candidate_vers = TLS1_3_VERSION; -+ } -+ /* -+ * TODO(TLS1.3): There is some discussion on the TLS list about -+ * whether to ignore versions version = best_vers; -+ /* TODO(TLS1.3): Remove this before release */ -+ if (best_vers == TLS1_3_VERSION) -+ s->version_draft = orig_candidate; - s->method = best_method; - return 0; - } -diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c -index db5aafe3be..d2912756fe 100644 ---- a/ssl/statem/statem_srvr.c -+++ b/ssl/statem/statem_srvr.c -@@ -1711,7 +1711,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, -@@ -1892,7 +1892,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->session->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, -@@ -1901,8 +1901,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->session->ciphers); -+ ssl_cipher_preference_list_free(s->cipher_list); -+ s->cipher_list = ssl_cipher_preference_list_from_ciphers( -+ s->session->ciphers); - sk_SSL_CIPHER_free(s->cipher_list_by_id); - s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); - } -@@ -2214,7 +2215,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->session->ciphers, SSL_get_ciphers(s)); -+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s)); - - if (cipher == NULL) { - SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, -diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c -index b79c776f2d..15f7f76e6e 100644 ---- a/ssl/t1_trce.c -+++ b/ssl/t1_trce.c -@@ -65,6 +65,11 @@ static const ssl_trace_tbl ssl_version_tbl[] = { - {TLS1_1_VERSION, "TLS 1.1"}, - {TLS1_2_VERSION, "TLS 1.2"}, - {TLS1_3_VERSION, "TLS 1.3"}, -+ /* TODO(TLS1.3): Remove these lines before release */ -+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23}, -+ {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26}, -+ {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27}, -+ {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT}, - {DTLS1_VERSION, "DTLS 1.0"}, - {DTLS1_2_VERSION, "DTLS 1.2"}, - {DTLS1_BAD_VER, "DTLS 1.0 (bad)"} -@@ -638,8 +643,19 @@ static int ssl_print_version(BIO *bio, int indent, const char *name, - if (*pmsglen < 2) - return 0; - vers = ((*pmsg)[0] << 8) | (*pmsg)[1]; -- if (version != NULL) -- *version = vers; -+ if (version != NULL) { -+ /* TODO(TLS1.3): Remove the draft conditional here before release */ -+ switch(vers) { -+ case TLS1_3_VERSION_DRAFT_23: -+ case TLS1_3_VERSION_DRAFT_26: -+ case TLS1_3_VERSION_DRAFT_27: -+ case TLS1_3_VERSION_DRAFT: -+ *version = TLS1_3_VERSION; -+ break; -+ default: -+ *version = vers; -+ } -+ } - BIO_indent(bio, indent, 80); - BIO_printf(bio, "%s=0x%x (%s)\n", - name, vers, ssl_trace_str(vers, ssl_version_tbl));