Update files - Remove pre2, pre6 and Update pre7.

This commit is contained in:
2018-06-05 07:48:56 +09:00
parent 76e2025727
commit cf31a6265e
6 changed files with 331 additions and 3314 deletions
+7 -25
View File
@@ -18,27 +18,19 @@
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) 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)
## pre6, pre7 Patch files ## Patch files
**Patches for BoringSSL's Equal Preference Patch are included by default.**
| Patch file name | Patch list |
| :--- | :--- |
| openssl-equal-pre6.patch | _Support_ **draft 26**, _Not support_ **draft 28** |
| openssl-equal-pre7.patch | [Patch files prior to this patch](https://github.com/openssl/openssl/commit/73cc84a132a08a02253ae168600fc4d16cd400d8), _Support_ **draft 26** |
| openssl-equal-pre7-draft28.patch | [Patch files after this patch](https://github.com/openssl/openssl/commit/73cc84a132a08a02253ae168600fc4d16cd400d8), _Support_ **draft 26~28** |
| openssl-equal-pre7-draft23_28.patch | Final (pre7 release), _Support_ **draft 23, 28** |
## pre8 Patch files
Here is the basic patch content. Here is the basic patch content.
- Support TLS 1.3 draft 23 + 28 - Support TLS 1.3 draft 23 + 28
- Server: draft 23 + 28 - Server: draft 23 + 28
- Client: draft 23 + 26 + 27 + 28 - Client: draft 23 + 26 + 27 + 28
- BoringSSL's Equal Preference Patch - 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 | | Patch file name | Patch list |
| :--- | :--- | | :--- | :--- |
| openssl-equal-pre7.patch | TLS 1.3 cipher settings **_can not_** be changed on _nginx_. |
| openssl-equal-pre7_ciphers.patch | TLS 1.3 cipher settings **_can_** be changed on _nginx_. |
| openssl-equal-pre8.patch | TLS 1.3 cipher settings **_can not_** be changed on _nginx_. | | openssl-equal-pre8.patch | TLS 1.3 cipher settings **_can not_** be changed on _nginx_. |
| openssl-equal-pre8_ciphers.patch | TLS 1.3 cipher settings **_can_** be changed on _nginx_. | | openssl-equal-pre8_ciphers.patch | TLS 1.3 cipher settings **_can_** be changed on _nginx_. |
@@ -59,22 +51,12 @@ ssl_ecdh_curve X25519:P-256:P-384;
ssl_prefer_server_ciphers on; ssl_prefer_server_ciphers on;
``` ```
### OpenSSL-1.1.1-pre2 ciphers (draft 23) ### OpenSSL-1.1.1-pre7, pre8 ciphers (draft 23, 28)
```
[TLS13-AES-128-GCM-SHA256|TLS13-CHACHA20-POLY1305-SHA256]:TLS13-AES-256-GCM-SHA384:[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-pre6~pre7 ciphers (draft 26 ~ 28)
``` ```
[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 [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-draft23_28, pre8 ciphers (draft 23, 28) ### OpenSSL-1.1.1-pre7_ciphers, pre8_ciphers ciphers (draft 23, 28)
``` ```
[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 [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
```
### OpenSSL-1.1.1-pre8_ciphers ciphers (Latest, draft 23, 28)
```
[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
``` ```
-1014
View File
@@ -1,1014 +0,0 @@
diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod
index 129f766..1fe2187 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<SSL_OP_CIPHER_SERVER_PREFERENCE> is enabled. Ciphers in an equal-preference
+group have equal priority and use the client order. This may be used to
+enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305
+based on client preferences. An equal-preference is specified with square
+brackets, combining multiple selectors separated by |. For example:
+
+ [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]
+
+ Once an equal-preference group is used, future directives must be
+ opcode-less.
+
=head1 CIPHER SUITE NAMES
The following lists give the SSL or TLS cipher suites names from the
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 1a02268..a3b5819 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 8f0d3e1..b11285c 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -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)) {
- prio = srvr;
- allow = clnt;
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
prio = srvr;
+ in_group_flags = server_pref->in_group_flags;
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
@@ -4214,13 +4194,25 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
+ /* Skip 3DES over TLS v1.0 */
+ if (c->algorithm_enc == SSL_3DES &&
+ (s->version != TLS1_VERSION &&
+ s->version != DTLS1_VERSION))
+ ok = 0;
+
+ /* not use ECDSA under TLS v1.2 */
+ // if ((alg_a & SSL_aECDSA) && s->version != TLS1_2_VERSION) ok = 0;
+ if ((alg_a & SSL_aRSA) &&
+ (alg_k & SSL_kRSA) &&
+ (s->version != TLS1_VERSION)) ok = 0;
+
#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 +4229,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 +4244,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 d31aeb7..8db2ffe 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 f0bde60..35e804e 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 59b507e..3bd2af9 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 0dd2a7b..c05ac8b 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 d335819..506d694 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,
-1063
View File
@@ -1,1063 +0,0 @@
diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod
index 3786e9a..8dd0d2c 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<SSL_OP_CIPHER_SERVER_PREFERENCE> is enabled. Ciphers in an equal-preference
+group have equal priority and use the client order. This may be used to
+enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305
+based on client preferences. An equal-preference is specified with square
+brackets, combining multiple selectors separated by |. For example:
+
+ [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]
+
+ Once an equal-preference group is used, future directives must be
+ opcode-less.
+
=head1 CIPHER SUITE NAMES
The following lists give the SSL or TLS cipher suites names from the
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 4b45ae7..7567b18 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 8e395cd..700d7b7 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/ssl/s3_lib.c b/ssl/s3_lib.c
index f797497..0206266 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -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,15 +4115,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 = 0;
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 */
@@ -4139,54 +4158,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;
}
@@ -4198,14 +4176,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
@@ -4224,13 +4204,25 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
+ /* Skip 3DES over TLS v1.0 */
+ if (c->algorithm_enc == SSL_3DES &&
+ (s->version != TLS1_VERSION &&
+ s->version != DTLS1_VERSION))
+ ok = 0;
+
+ /* Not use weak cipher after TLSv1.0 */
+ if ((alg_a & SSL_aRSA) &&
+ (alg_k & SSL_kRSA) &&
+ (s->version != TLS1_VERSION))
+ ok = 0;
+
#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);
@@ -4247,6 +4239,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) {
@@ -4254,21 +4254,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 9011e42..7da2f1b 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;
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
- STACK_OF(SSL_CIPHER) *cipherstack;
+ 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;
+ 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,36 @@ 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++) {
+ 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;
+ if (tmp->algorithm_enc == SSL_AES128GCM &&
+ i + 1 < sk_SSL_CIPHER_num(tls13_ciphersuites)) {
+ tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i + 1);
+ if (tmp->algorithm_enc == SSL_CHACHA20POLY1305)
+ in_group_flags[num_in_group_flags++] = 1;
+ else
+ in_group_flags[num_in_group_flags++] = 0;
}
+ else
+ in_group_flags[num_in_group_flags++] = 0;
}
/*
@@ -1612,26 +1681,67 @@ 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 */
+ tmp = NULL;
+ co_list = NULL;
- if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
- sk_SSL_CIPHER_free(cipherstack);
- return NULL;
+ tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack);
+ 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;
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 bce2036..31b5599 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 1e24f84..5423413 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1106,6 +1106,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;
@@ -1146,7 +1211,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);
@@ -2426,9 +2492,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;
@@ -2502,8 +2568,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;
}
@@ -2917,7 +2983,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;
}
@@ -3077,7 +3143,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);
@@ -3708,13 +3774,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 d881458..f1dcc37 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 */
@@ -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;
@@ -2213,7 +2250,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);
@@ -2223,6 +2260,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,
@@ -2304,8 +2348,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 aa38fad..4a32fb1 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);
}
@@ -2179,7 +2180,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,
-1046
View File
@@ -1,1046 +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<SSL_OP_CIPHER_SERVER_PREFERENCE> is enabled. Ciphers in an equal-preference
+group have equal priority and use the client order. This may be used to
+enforce that AEADs are preferred but select AES-GCM vs. ChaCha20-Poly1305
+based on client preferences. An equal-preference is specified with square
+brackets, combining multiple selectors separated by |. For example:
+
+ [ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256]
+
+ Once an equal-preference group is used, future directives must be
+ opcode-less.
+
=head1 CIPHER SUITE NAMES
The following lists give the SSL or TLS cipher suites names from the
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 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/ssl/s3_lib.c b/ssl/s3_lib.c
index 354769b0c1..f883175359 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -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)) {
- prio = srvr;
- allow = clnt;
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
prio = srvr;
+ in_group_flags = server_pref->in_group_flags;
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..ff5ba41d45 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,
@@ -2315,8 +2359,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 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,
+182 -84
View File
@@ -25,7 +25,7 @@ index 3786e9a028..8dd0d2c028 100644
The following lists give the SSL or TLS cipher suites names from the 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 diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 4bd53fc24c..a480863755 100644 index db0a2d5d82..a26cd1cd82 100644
--- a/include/openssl/ssl.h --- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h +++ b/include/openssl/ssl.h
@@ -174,12 +174,12 @@ extern "C" { @@ -174,12 +174,12 @@ extern "C" {
@@ -70,10 +70,69 @@ index 8e395cdd2d..700d7b7b4e 100644
# define SSL_R_UNEXPECTED_RECORD 245 # define SSL_R_UNEXPECTED_RECORD 245
# define SSL_R_UNINITIALIZED 276 # define SSL_R_UNINITIALIZED 276
# define SSL_R_UNKNOWN_ALERT_TYPE 246 # 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 diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index f79749724f..020626606f 100644 index 354769b0c1..ef48c9b312 100644
--- a/ssl/s3_lib.c --- a/ssl/s3_lib.c
+++ b/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) @@ -4095,6 +4095,17 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
return 1; return 1;
} }
@@ -92,7 +151,7 @@ index f79749724f..020626606f 100644
/* /*
* ssl3_choose_cipher - choose a cipher from those offered by the client * ssl3_choose_cipher - choose a cipher from those offered by the client
* @s: SSL connection * @s: SSL connection
@@ -4104,15 +4115,23 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len) @@ -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. * Returns the selected cipher or NULL when no common ciphers.
*/ */
const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
@@ -102,10 +161,11 @@ index f79749724f..020626606f 100644
{ {
const SSL_CIPHER *c, *ret = NULL; const SSL_CIPHER *c, *ret = NULL;
- STACK_OF(SSL_CIPHER) *prio, *allow; - STACK_OF(SSL_CIPHER) *prio, *allow;
- int i, ii, ok; - int i, ii, ok, prefer_sha256 = 0;
+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow; + STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
+ int i, ii, ok, safari_ec = 0; + int i, ii, ok, prefer_sha256 = 0, safari_ec = 0;
unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 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 -#ifndef OPENSSL_NO_CHACHA
- STACK_OF(SSL_CIPHER) *prio_chacha = NULL; - STACK_OF(SSL_CIPHER) *prio_chacha = NULL;
-#endif -#endif
@@ -122,7 +182,7 @@ index f79749724f..020626606f 100644
/* Let's see which ciphers we can support */ /* Let's see which ciphers we can support */
@@ -4139,54 +4158,13 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -4140,54 +4159,13 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
#endif #endif
/* SUITE-B takes precedence over server preference and ChaCha priortiy */ /* SUITE-B takes precedence over server preference and ChaCha priortiy */
@@ -180,7 +240,7 @@ index f79749724f..020626606f 100644
allow = srvr; allow = srvr;
} }
@@ -4198,14 +4176,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -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++) { for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
c = sk_SSL_CIPHER_value(prio, i); c = sk_SSL_CIPHER_value(prio, i);
@@ -199,22 +259,7 @@ index f79749724f..020626606f 100644
/* /*
* Since TLS 1.3 ciphersuites can be used with any auth or * Since TLS 1.3 ciphersuites can be used with any auth or
@@ -4224,13 +4204,25 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -4247,10 +4227,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
alg_k = c->algorithm_mkey;
alg_a = c->algorithm_auth;
+ /* Skip 3DES over TLS v1.0 */
+ if (c->algorithm_enc == SSL_3DES &&
+ (s->version != TLS1_VERSION &&
+ s->version != DTLS1_VERSION))
+ ok = 0;
+
+ /* Not use weak cipher after TLSv1.0 */
+ if ((alg_a & SSL_aRSA) &&
+ (alg_k & SSL_kRSA) &&
+ (s->version != TLS1_VERSION))
+ ok = 0;
+
#ifndef OPENSSL_NO_PSK #ifndef OPENSSL_NO_PSK
/* with PSK there must be server callback set */ /* with PSK there must be server callback set */
if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL) if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
@@ -227,7 +272,7 @@ index f79749724f..020626606f 100644
#ifdef CIPHER_DEBUG #ifdef CIPHER_DEBUG
fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k, fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
alg_a, mask_k, mask_a, (void *)c, c->name); alg_a, mask_k, mask_a, (void *)c, c->name);
@@ -4247,6 +4239,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -4267,6 +4247,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
if (!ok) if (!ok)
continue; continue;
@@ -242,13 +287,27 @@ index f79749724f..020626606f 100644
} }
ii = sk_SSL_CIPHER_find(allow, c); ii = sk_SSL_CIPHER_find(allow, c);
if (ii >= 0) { if (ii >= 0) {
@@ -4254,21 +4254,38 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -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, if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
c->strength_bits, 0, (void *)c)) c->strength_bits, 0, (void *)c))
continue; continue;
-#if !defined(OPENSSL_NO_EC) -#if !defined(OPENSSL_NO_EC)
- if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA) - if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
- && s->s3->is_probably_safari) { - && 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) { + if (in_group_flags != NULL && in_group_flags[i] == 1) {
+ /* This element of |prio| is in a group. Update + /* This element of |prio| is in a group. Update
@@ -273,13 +332,10 @@ index f79749724f..020626606f 100644
+ /* We are about to leave a group, but we found a match + /* We are about to leave a group, but we found a match
+ * in it, so that's our answer. */ + * in it, so that's our answer. */
+ if (safari_ec) { + if (safari_ec) {
if (!ret) + if (!ret)
- ret = sk_SSL_CIPHER_value(allow, ii);
+ ret = sk_SSL_CIPHER_value(allow, group_min); + ret = sk_SSL_CIPHER_value(allow, group_min);
continue; + continue;
} + }
-#endif
- ret = sk_SSL_CIPHER_value(allow, ii);
+ ret = sk_SSL_CIPHER_value(allow, group_min); + ret = sk_SSL_CIPHER_value(allow, group_min);
break; break;
} }
@@ -291,7 +347,7 @@ index f79749724f..020626606f 100644
} }
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 9011e42fa8..4ad79b3ebe 100644 index 9011e42fa8..8aa922d426 100644
--- a/ssl/ssl_ciph.c --- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c
@@ -190,6 +190,7 @@ typedef struct cipher_order_st { @@ -190,6 +190,7 @@ typedef struct cipher_order_st {
@@ -509,7 +565,7 @@ index 9011e42fa8..4ad79b3ebe 100644
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i, tls13_len; + 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; uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
- STACK_OF(SSL_CIPHER) *cipherstack; - STACK_OF(SSL_CIPHER) *cipherstack;
+ STACK_OF(SSL_CIPHER) *cipherstack = NULL, *tmp_cipher_list = NULL; + STACK_OF(SSL_CIPHER) *cipherstack = NULL;
const char *rule_p; const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
- const SSL_CIPHER **ca_list = NULL; - const SSL_CIPHER **ca_list = NULL;
@@ -622,7 +678,7 @@ index 9011e42fa8..4ad79b3ebe 100644
} }
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
disabled_mkey, disabled_auth, disabled_enc, disabled_mkey, disabled_auth, disabled_enc,
@@ -1583,27 +1643,37 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -1583,27 +1643,35 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
OPENSSL_free(ca_list); /* Not needed anymore */ OPENSSL_free(ca_list); /* Not needed anymore */
@@ -659,20 +715,18 @@ index 9011e42fa8..4ad79b3ebe 100644
- return NULL; - return NULL;
+ tmp)) + tmp))
+ goto err; + goto err;
+ /* Temporary - AES128, CHACHA20 priority adjustment of TLS 1.3. */
+ if (tmp->algorithm_enc == SSL_AES128GCM && + if (tmp->algorithm_enc == SSL_AES128GCM &&
+ tls13_len > (i + 1)) { + tls13_len > (i + 1)) {
+ tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i + 1); + tmp = sk_SSL_CIPHER_value(tls13_ciphersuites, i + 1);
+ if (tmp->algorithm_enc == SSL_CHACHA20POLY1305) + in_group_flags[num_in_group_flags++] = (tmp->algorithm_enc == SSL_CHACHA20POLY1305) ? 1 : 0;
+ in_group_flags[num_in_group_flags++] = 1;
+ else
+ in_group_flags[num_in_group_flags++] = 0;
} }
+ else + else
+ in_group_flags[num_in_group_flags++] = 0; + in_group_flags[num_in_group_flags++] = 0;
} }
/* /*
@@ -1612,26 +1682,67 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -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) { for (curr = head; curr != NULL; curr = curr->next) {
if (curr->active) { if (curr->active) {
@@ -689,16 +743,18 @@ index 9011e42fa8..4ad79b3ebe 100644
#endif #endif
} }
} }
+ - OPENSSL_free(co_list); /* Not needed any longer */
OPENSSL_free(co_list); /* Not needed any longer */
+ tmp = NULL;
+ co_list = NULL;
- if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) { - if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
- sk_SSL_CIPHER_free(cipherstack); - sk_SSL_CIPHER_free(cipherstack);
- return NULL; - return NULL;
+ tmp_cipher_list = sk_SSL_CIPHER_dup(cipherstack); - }
+ if (tmp_cipher_list == 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; + goto err;
+ +
+ pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st)); + pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
@@ -715,21 +771,6 @@ index 9011e42fa8..4ad79b3ebe 100644
+ ssl_cipher_preference_list_free(*cipher_list); + ssl_cipher_preference_list_free(*cipher_list);
+ *cipher_list = pref_list; + *cipher_list = pref_list;
+ pref_list = NULL; + 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;
return cipherstack; return cipherstack;
+ +
@@ -740,8 +781,6 @@ index 9011e42fa8..4ad79b3ebe 100644
+ OPENSSL_free(in_group_flags); + OPENSSL_free(in_group_flags);
+ if (cipherstack) + if (cipherstack)
+ sk_SSL_CIPHER_free(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) + if (pref_list && pref_list->in_group_flags)
+ OPENSSL_free(pref_list->in_group_flags); + OPENSSL_free(pref_list->in_group_flags);
+ if (pref_list) + if (pref_list)
@@ -780,10 +819,10 @@ index bce203654a..31b55997a2 100644
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"}, {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_ALERT_TYPE), "unknown alert type"}, {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 diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 3aefa34ab2..64f553ce35 100644 index 22f729c284..c57c56e39a 100644
--- a/ssl/ssl_lib.c --- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c +++ b/ssl/ssl_lib.c
@@ -1106,6 +1106,71 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm) @@ -1108,6 +1108,71 @@ int SSL_set1_param(SSL *ssl, X509_VERIFY_PARAM *vpm)
return X509_VERIFY_PARAM_set1(ssl->param, vpm); return X509_VERIFY_PARAM_set1(ssl->param, vpm);
} }
@@ -855,7 +894,7 @@ index 3aefa34ab2..64f553ce35 100644
X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx) X509_VERIFY_PARAM *SSL_CTX_get0_param(SSL_CTX *ctx)
{ {
return ctx->param; return ctx->param;
@@ -1146,7 +1211,8 @@ void SSL_free(SSL *s) @@ -1148,7 +1213,8 @@ void SSL_free(SSL *s)
BUF_MEM_free(s->init_buf); BUF_MEM_free(s->init_buf);
/* add extra stuff */ /* add extra stuff */
@@ -865,7 +904,7 @@ index 3aefa34ab2..64f553ce35 100644
sk_SSL_CIPHER_free(s->cipher_list_by_id); sk_SSL_CIPHER_free(s->cipher_list_by_id);
sk_SSL_CIPHER_free(s->tls13_ciphersuites); sk_SSL_CIPHER_free(s->tls13_ciphersuites);
@@ -2426,9 +2492,9 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s) @@ -2431,9 +2497,9 @@ STACK_OF(SSL_CIPHER) *SSL_get_ciphers(const SSL *s)
{ {
if (s != NULL) { if (s != NULL) {
if (s->cipher_list != NULL) { if (s->cipher_list != NULL) {
@@ -877,7 +916,7 @@ index 3aefa34ab2..64f553ce35 100644
} }
} }
return NULL; return NULL;
@@ -2502,8 +2568,8 @@ const char *SSL_get_cipher_list(const SSL *s, int n) @@ -2507,8 +2573,8 @@ const char *SSL_get_cipher_list(const SSL *s, int n)
* preference */ * preference */
STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx) STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx)
{ {
@@ -888,7 +927,7 @@ index 3aefa34ab2..64f553ce35 100644
return NULL; return NULL;
} }
@@ -2926,7 +2992,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth) @@ -2932,7 +2998,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->tls13_ciphersuites, ret->tls13_ciphersuites,
&ret->cipher_list, &ret->cipher_list_by_id, &ret->cipher_list, &ret->cipher_list_by_id,
SSL_DEFAULT_CIPHER_LIST, ret->cert) SSL_DEFAULT_CIPHER_LIST, ret->cert)
@@ -897,7 +936,7 @@ index 3aefa34ab2..64f553ce35 100644
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS); SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
goto err2; goto err2;
} }
@@ -3086,7 +3152,7 @@ void SSL_CTX_free(SSL_CTX *a) @@ -3095,7 +3161,7 @@ void SSL_CTX_free(SSL_CTX *a)
#ifndef OPENSSL_NO_CT #ifndef OPENSSL_NO_CT
CTLOG_STORE_free(a->ctlog_store); CTLOG_STORE_free(a->ctlog_store);
#endif #endif
@@ -906,7 +945,7 @@ index 3aefa34ab2..64f553ce35 100644
sk_SSL_CIPHER_free(a->cipher_list_by_id); sk_SSL_CIPHER_free(a->cipher_list_by_id);
sk_SSL_CIPHER_free(a->tls13_ciphersuites); sk_SSL_CIPHER_free(a->tls13_ciphersuites);
ssl_cert_free(a->cert); ssl_cert_free(a->cert);
@@ -3718,13 +3784,15 @@ SSL *SSL_dup(SSL *s) @@ -3747,13 +3813,15 @@ SSL *SSL_dup(SSL *s)
/* dup the cipher_list and cipher_list_by_id stacks */ /* dup the cipher_list and cipher_list_by_id stacks */
if (s->cipher_list != NULL) { if (s->cipher_list != NULL) {
@@ -927,7 +966,7 @@ index 3aefa34ab2..64f553ce35 100644
/* Dup the client_CA list */ /* Dup the client_CA list */
if (s->ca_names != NULL) { if (s->ca_names != NULL) {
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index b32b23bedf..b0ea64b523 100644 index 4aec810179..d251ee178f 100644
--- a/ssl/ssl_locl.h --- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h +++ b/ssl/ssl_locl.h
@@ -741,9 +741,46 @@ typedef struct ssl_ctx_ext_secure_st { @@ -741,9 +741,46 @@ typedef struct ssl_ctx_ext_secure_st {
@@ -978,7 +1017,7 @@ index b32b23bedf..b0ea64b523 100644
/* same as above but sorted for lookup */ /* same as above but sorted for lookup */
STACK_OF(SSL_CIPHER) *cipher_list_by_id; STACK_OF(SSL_CIPHER) *cipher_list_by_id;
/* TLSv1.3 specific ciphersuites */ /* TLSv1.3 specific ciphersuites */
@@ -1115,7 +1152,7 @@ struct ssl_st { @@ -1120,7 +1157,7 @@ struct ssl_st {
/* Per connection DANE state */ /* Per connection DANE state */
SSL_DANE dane; SSL_DANE dane;
/* crypto */ /* crypto */
@@ -987,7 +1026,7 @@ index b32b23bedf..b0ea64b523 100644
STACK_OF(SSL_CIPHER) *cipher_list_by_id; STACK_OF(SSL_CIPHER) *cipher_list_by_id;
/* TLSv1.3 specific ciphersuites */ /* TLSv1.3 specific ciphersuites */
STACK_OF(SSL_CIPHER) *tls13_ciphersuites; STACK_OF(SSL_CIPHER) *tls13_ciphersuites;
@@ -2213,7 +2250,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap, @@ -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 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, __owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites, STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
@@ -996,7 +1035,7 @@ index b32b23bedf..b0ea64b523 100644
STACK_OF(SSL_CIPHER) **cipher_list_by_id, STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str, const char *rule_str,
CERT *c); CERT *c);
@@ -2223,6 +2260,13 @@ __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites, @@ -2234,6 +2271,13 @@ __owur int bytes_to_cipher_list(SSL *s, PACKET *cipher_suites,
STACK_OF(SSL_CIPHER) **scsvs, int sslv2format, STACK_OF(SSL_CIPHER) **scsvs, int sslv2format,
int fatal); int fatal);
void ssl_update_cache(SSL *s, int mode); void ssl_update_cache(SSL *s, int mode);
@@ -1010,22 +1049,61 @@ index b32b23bedf..b0ea64b523 100644
__owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc, __owur int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
const EVP_MD **md, int *mac_pkey_type, const EVP_MD **md, int *mac_pkey_type,
size_t *mac_secret_size, SSL_COMP **comp, size_t *mac_secret_size, SSL_COMP **comp,
@@ -2304,8 +2348,8 @@ void ssl3_free_digest_list(SSL *s); @@ -2316,7 +2360,7 @@ __owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
__owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
CERT_PKEY *cpk); CERT_PKEY *cpk);
__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl, __owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
- STACK_OF(SSL_CIPHER) *clnt, STACK_OF(SSL_CIPHER) *clnt,
- STACK_OF(SSL_CIPHER) *srvr); - STACK_OF(SSL_CIPHER) *srvr);
+ STACK_OF(SSL_CIPHER) *clnt, + struct ssl_cipher_preference_list_st *srvr);
+ struct ssl_cipher_preference_list_st *srvr);
__owur int ssl3_digest_cached_records(SSL *s, int keep); __owur int ssl3_digest_cached_records(SSL *s, int keep);
__owur int ssl3_new(SSL *s); __owur int ssl3_new(SSL *s);
void ssl3_free(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..1f2eecad0b 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -1708,8 +1708,7 @@ 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_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 diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 018daaa0da..cd222e4641 100644 index ce8cec185a..1a12a9c1a0 100644
--- a/ssl/statem/statem_srvr.c --- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c +++ b/ssl/statem/statem_srvr.c
@@ -1690,7 +1690,7 @@ static int tls_early_post_process_client_hello(SSL *s) @@ -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 */ /* For TLSv1.3 we must select the ciphersuite *before* session resumption */
if (SSL_IS_TLS13(s)) { if (SSL_IS_TLS13(s)) {
const SSL_CIPHER *cipher = const SSL_CIPHER *cipher =
@@ -1034,7 +1112,7 @@ index 018daaa0da..cd222e4641 100644
if (cipher == NULL) { if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
@@ -1871,7 +1871,7 @@ static int tls_early_post_process_client_hello(SSL *s) @@ -1889,7 +1889,7 @@ static int tls_early_post_process_client_hello(SSL *s)
/* check if some cipher was preferred by call back */ /* check if some cipher was preferred by call back */
if (pref_cipher == NULL) if (pref_cipher == NULL)
pref_cipher = ssl3_choose_cipher(s, s->session->ciphers, pref_cipher = ssl3_choose_cipher(s, s->session->ciphers,
@@ -1043,7 +1121,7 @@ index 018daaa0da..cd222e4641 100644
if (pref_cipher == NULL) { if (pref_cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO, SSL_F_TLS_EARLY_POST_PROCESS_CLIENT_HELLO,
@@ -1880,8 +1880,9 @@ static int tls_early_post_process_client_hello(SSL *s) @@ -1898,8 +1898,9 @@ static int tls_early_post_process_client_hello(SSL *s)
} }
s->session->cipher = pref_cipher; s->session->cipher = pref_cipher;
@@ -1055,7 +1133,7 @@ index 018daaa0da..cd222e4641 100644
sk_SSL_CIPHER_free(s->cipher_list_by_id); sk_SSL_CIPHER_free(s->cipher_list_by_id);
s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers); s->cipher_list_by_id = sk_SSL_CIPHER_dup(s->session->ciphers);
} }
@@ -2193,7 +2194,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst) @@ -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 */ /* In TLSv1.3 we selected the ciphersuite before resumption */
if (!SSL_IS_TLS13(s)) { if (!SSL_IS_TLS13(s)) {
cipher = cipher =
@@ -1064,3 +1142,23 @@ index 018daaa0da..cd222e4641 100644
if (cipher == NULL) { if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, 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:
@@ -24,27 +24,6 @@ index 3786e9a028..8dd0d2c028 100644
=head1 CIPHER SUITE NAMES =head1 CIPHER SUITE NAMES
The following lists give the SSL or TLS cipher suites names from the 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 diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 8e395cdd2d..700d7b7b4e 100644 index 8e395cdd2d..700d7b7b4e 100644
--- a/include/openssl/sslerr.h --- a/include/openssl/sslerr.h
@@ -103,10 +82,84 @@ index 8822ca25c3..63ecafe373 100644
(unsigned int)rec->length) <= 0 (unsigned int)rec->length) <= 0
|| EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0 || EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 354769b0c1..f883175359 100644 index 354769b0c1..f90634d600 100644
--- a/ssl/s3_lib.c --- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c +++ b/ssl/s3_lib.c
@@ -4095,6 +4095,17 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len) @@ -31,7 +31,23 @@ 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[] = {
+
+};
+
+/*
+ * 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 +127,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 +171,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 +236,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 +300,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 +4099,17 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
return 1; return 1;
} }
@@ -124,7 +177,7 @@ index 354769b0c1..f883175359 100644
/* /*
* ssl3_choose_cipher - choose a cipher from those offered by the client * ssl3_choose_cipher - choose a cipher from those offered by the client
* @s: SSL connection * @s: SSL connection
@@ -4104,16 +4115,24 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len) @@ -4104,16 +4119,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. * Returns the selected cipher or NULL when no common ciphers.
*/ */
const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
@@ -155,18 +208,18 @@ index 354769b0c1..f883175359 100644
/* Let's see which ciphers we can support */ /* 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, @@ -4140,54 +4163,13 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
#endif #endif
/* SUITE-B takes precedence over server preference and ChaCha priortiy */ /* SUITE-B takes precedence over server preference and ChaCha priortiy */
- if (tls1_suiteb(s)) { - if (tls1_suiteb(s)) {
- prio = srvr;
- allow = clnt;
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) { + if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
prio = srvr; prio = srvr;
+ in_group_flags = server_pref->in_group_flags; + in_group_flags = server_pref->in_group_flags;
allow = clnt; allow = clnt;
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
- prio = srvr;
- allow = clnt;
-#ifndef OPENSSL_NO_CHACHA -#ifndef OPENSSL_NO_CHACHA
- /* If ChaCha20 is at the top of the client preference list, - /* If ChaCha20 is at the top of the client preference list,
- and there are ChaCha20 ciphers in the server list, then - and there are ChaCha20 ciphers in the server list, then
@@ -213,7 +266,7 @@ index 354769b0c1..f883175359 100644
allow = srvr; allow = srvr;
} }
@@ -4218,14 +4196,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -4218,14 +4200,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) { for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
c = sk_SSL_CIPHER_value(prio, i); c = sk_SSL_CIPHER_value(prio, i);
@@ -232,7 +285,7 @@ index 354769b0c1..f883175359 100644
/* /*
* Since TLS 1.3 ciphersuites can be used with any auth or * 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, @@ -4247,10 +4231,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
#ifndef OPENSSL_NO_PSK #ifndef OPENSSL_NO_PSK
/* with PSK there must be server callback set */ /* with PSK there must be server callback set */
if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL) if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
@@ -245,7 +298,7 @@ index 354769b0c1..f883175359 100644
#ifdef CIPHER_DEBUG #ifdef CIPHER_DEBUG
fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k, fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
alg_a, mask_k, mask_a, (void *)c, c->name); 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, @@ -4267,6 +4251,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
if (!ok) if (!ok)
continue; continue;
@@ -260,7 +313,7 @@ index 354769b0c1..f883175359 100644
} }
ii = sk_SSL_CIPHER_find(allow, c); ii = sk_SSL_CIPHER_find(allow, c);
if (ii >= 0) { if (ii >= 0) {
@@ -4274,14 +4262,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt, @@ -4274,14 +4266,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED, if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
c->strength_bits, 0, (void *)c)) c->strength_bits, 0, (void *)c))
continue; continue;
@@ -276,7 +329,7 @@ index 354769b0c1..f883175359 100644
if (prefer_sha256) { if (prefer_sha256) {
const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii); 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, @@ -4293,13 +4278,38 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
ret = tmp; ret = tmp;
continue; continue;
} }
@@ -320,7 +373,7 @@ index 354769b0c1..f883175359 100644
} }
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 9011e42fa8..8aa922d426 100644 index 9011e42fa8..e89d1482b2 100644
--- a/ssl/ssl_ciph.c --- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c +++ b/ssl/ssl_ciph.c
@@ -190,6 +190,7 @@ typedef struct cipher_order_st { @@ -190,6 +190,7 @@ typedef struct cipher_order_st {
@@ -331,7 +384,15 @@ index 9011e42fa8..8aa922d426 100644
struct cipher_order_st *next, *prev; struct cipher_order_st *next, *prev;
} CIPHER_ORDER; } CIPHER_ORDER;
@@ -682,6 +683,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method, @@ -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].next = NULL;
co_list[co_list_num].prev = NULL; co_list[co_list_num].prev = NULL;
co_list[co_list_num].active = 0; co_list[co_list_num].active = 0;
@@ -339,7 +400,7 @@ index 9011e42fa8..8aa922d426 100644
co_list_num++; co_list_num++;
} }
@@ -775,8 +777,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey, @@ -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_auth, uint32_t alg_enc,
uint32_t alg_mac, int min_tls, uint32_t alg_mac, int min_tls,
uint32_t algo_strength, int rule, uint32_t algo_strength, int rule,
@@ -350,7 +411,7 @@ index 9011e42fa8..8aa922d426 100644
{ {
CIPHER_ORDER *head, *tail, *curr, *next, *last; CIPHER_ORDER *head, *tail, *curr, *next, *last;
const SSL_CIPHER *cp; const SSL_CIPHER *cp;
@@ -784,9 +786,9 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey, @@ -784,9 +787,9 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
#ifdef CIPHER_DEBUG #ifdef CIPHER_DEBUG
fprintf(stderr, fprintf(stderr,
@@ -362,7 +423,7 @@ index 9011e42fa8..8aa922d426 100644
#endif #endif
if (rule == CIPHER_DEL || rule == CIPHER_BUMP) 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, @@ -863,6 +866,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
if (!curr->active) { if (!curr->active) {
ll_append_tail(&head, curr, &tail); ll_append_tail(&head, curr, &tail);
curr->active = 1; curr->active = 1;
@@ -370,7 +431,7 @@ index 9011e42fa8..8aa922d426 100644
} }
} }
/* Move the added cipher to this location */ /* 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, @@ -870,6 +874,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
/* reverse == 0 */ /* reverse == 0 */
if (curr->active) { if (curr->active) {
ll_append_tail(&head, curr, &tail); ll_append_tail(&head, curr, &tail);
@@ -378,7 +439,7 @@ index 9011e42fa8..8aa922d426 100644
} }
} else if (rule == CIPHER_DEL) { } else if (rule == CIPHER_DEL) {
/* reverse == 1 */ /* reverse == 1 */
@@ -881,6 +885,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey, @@ -881,6 +886,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
*/ */
ll_append_head(&head, curr, &tail); ll_append_head(&head, curr, &tail);
curr->active = 0; curr->active = 0;
@@ -386,7 +447,7 @@ index 9011e42fa8..8aa922d426 100644
} }
} else if (rule == CIPHER_BUMP) { } else if (rule == CIPHER_BUMP) {
if (curr->active) if (curr->active)
@@ -948,8 +953,8 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p, @@ -948,8 +954,8 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
*/ */
for (i = max_strength_bits; i >= 0; i--) for (i = max_strength_bits; i >= 0; i--)
if (number_uses[i] > 0) if (number_uses[i] > 0)
@@ -397,7 +458,7 @@ index 9011e42fa8..8aa922d426 100644
OPENSSL_free(number_uses); OPENSSL_free(number_uses);
return 1; return 1;
@@ -963,7 +968,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str, @@ -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; uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
int min_tls; int min_tls;
const char *l, *buf; const char *l, *buf;
@@ -406,7 +467,7 @@ index 9011e42fa8..8aa922d426 100644
uint32_t cipher_id = 0; uint32_t cipher_id = 0;
char ch; char ch;
@@ -974,18 +979,66 @@ static int ssl_cipher_process_rulestr(const char *rule_str, @@ -974,18 +980,66 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
if (ch == '\0') if (ch == '\0')
break; /* done */ break; /* done */
@@ -474,7 +535,16 @@ index 9011e42fa8..8aa922d426 100644
} else { } else {
rule = CIPHER_ADD; rule = CIPHER_ADD;
} }
@@ -1027,7 +1080,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str, @@ -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. * alphanumeric, so we call this an error.
*/ */
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND); SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
@@ -483,7 +553,7 @@ index 9011e42fa8..8aa922d426 100644
l++; l++;
break; break;
} }
@@ -1206,8 +1259,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str, @@ -1206,8 +1260,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
} else if (found) { } else if (found) {
ssl_cipher_apply_rule(cipher_id, ssl_cipher_apply_rule(cipher_id,
alg_mkey, alg_auth, alg_enc, alg_mac, alg_mkey, alg_auth, alg_enc, alg_mac,
@@ -494,7 +564,7 @@ index 9011e42fa8..8aa922d426 100644
} else { } else {
while ((*l != '\0') && !ITEM_SEP(*l)) while ((*l != '\0') && !ITEM_SEP(*l))
l++; l++;
@@ -1216,6 +1269,11 @@ static int ssl_cipher_process_rulestr(const char *rule_str, @@ -1216,6 +1270,11 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
break; /* done */ break; /* done */
} }
@@ -506,7 +576,7 @@ index 9011e42fa8..8aa922d426 100644
return retval; return retval;
} }
@@ -1380,7 +1438,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str) @@ -1380,7 +1439,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
if (ret && ctx->cipher_list != NULL) { if (ret && ctx->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */ /* We already have a cipher_list, so we need to update it */
@@ -515,7 +585,7 @@ index 9011e42fa8..8aa922d426 100644
ctx->tls13_ciphersuites); ctx->tls13_ciphersuites);
} }
@@ -1393,7 +1451,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str) @@ -1393,7 +1452,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
if (ret && s->cipher_list != NULL) { if (ret && s->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */ /* We already have a cipher_list, so we need to update it */
@@ -524,7 +594,7 @@ index 9011e42fa8..8aa922d426 100644
s->tls13_ciphersuites); s->tls13_ciphersuites);
} }
@@ -1402,17 +1460,20 @@ int SSL_set_ciphersuites(SSL *s, const char *str) @@ -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) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites, STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
@@ -535,21 +605,20 @@ index 9011e42fa8..8aa922d426 100644
CERT *c) 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;
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i, tls13_len; + int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac; uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
- STACK_OF(SSL_CIPHER) *cipherstack; - STACK_OF(SSL_CIPHER) *cipherstack;
+ STACK_OF(SSL_CIPHER) *cipherstack = NULL; + STACK_OF(SSL_CIPHER) *cipherstack = NULL;
const char *rule_p; const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr; CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
- const SSL_CIPHER **ca_list = NULL; const SSL_CIPHER **ca_list = NULL;
+ const SSL_CIPHER **ca_list = NULL, *tmp = NULL;
+ uint8_t *in_group_flags = NULL; + uint8_t *in_group_flags = NULL;
+ unsigned int num_in_group_flags = 0; + unsigned int num_in_group_flags = 0;
+ struct ssl_cipher_preference_list_st *pref_list = NULL; + struct ssl_cipher_preference_list_st *pref_list = NULL;
/* /*
* Return with error if nothing to do. * Return with error if nothing to do.
@@ -1461,16 +1522,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -1461,16 +1523,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* preference). * preference).
*/ */
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD, ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
@@ -573,7 +642,7 @@ index 9011e42fa8..8aa922d426 100644
&head, &tail); &head, &tail);
/* /*
@@ -1479,13 +1540,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -1479,13 +1541,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* strength. * strength.
*/ */
ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD, ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
@@ -590,7 +659,7 @@ index 9011e42fa8..8aa922d426 100644
&tail); &tail);
/* /*
@@ -1493,16 +1554,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -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 * disabled. (For applications that allow them, they aren't too bad, but
* we prefer authenticated ciphers.) * we prefer authenticated ciphers.)
*/ */
@@ -611,7 +680,7 @@ index 9011e42fa8..8aa922d426 100644
&tail); &tail);
/* /*
@@ -1518,7 +1579,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -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. * Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
* TODO(openssl-team): is there an easier way to accomplish all this? * TODO(openssl-team): is there an easier way to accomplish all this?
*/ */
@@ -620,7 +689,7 @@ index 9011e42fa8..8aa922d426 100644
&head, &tail); &head, &tail);
/* /*
@@ -1534,15 +1595,15 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -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 * Because we now bump ciphers to the top of the list, we proceed in
* reverse order of preference. * reverse order of preference.
*/ */
@@ -633,6 +702,9 @@ index 9011e42fa8..8aa922d426 100644
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0, ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
- CIPHER_BUMP, -1, &head, &tail); - CIPHER_BUMP, -1, &head, &tail);
+ CIPHER_BUMP, -1, 0, &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!) */ /* 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, &head, &tail);
@@ -640,7 +712,7 @@ index 9011e42fa8..8aa922d426 100644
/* /*
* We also need cipher aliases for selecting based on the rule_str. * 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, @@ -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; num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max); ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
if (ca_list == NULL) { if (ca_list == NULL) {
@@ -651,7 +723,7 @@ index 9011e42fa8..8aa922d426 100644
} }
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases, ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
disabled_mkey, disabled_auth, disabled_enc, disabled_mkey, disabled_auth, disabled_enc,
@@ -1583,27 +1643,35 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method, @@ -1583,28 +1647,19 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
OPENSSL_free(ca_list); /* Not needed anymore */ OPENSSL_free(ca_list); /* Not needed anymore */
@@ -672,34 +744,22 @@ index 9011e42fa8..8aa922d426 100644
- } - }
+ if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) + if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
+ goto err; + 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); + in_group_flags = OPENSSL_malloc(num_of_ciphers);
+ if (!in_group_flags) + if (!in_group_flags)
+ goto err; + 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, * 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) { for (curr = head; curr != NULL; curr = curr->next) {
if (curr->active) { if (curr->active) {