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));