Skip to content

Instantly share code, notes, and snippets.

@hakasenyang
Last active July 22, 2021 09:45
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hakasenyang/8dea6875b09757b411c2053a1cd34460 to your computer and use it in GitHub Desktop.
Save hakasenyang/8dea6875b09757b411c2053a1cd34460 to your computer and use it in GitHub Desktop.
ssl.hakase.io source
<?php
// Tor Check : https://gist.github.com/TheRealBastiaan/889b4ec5fafd928e0de2
function IsTorExitPoint($ip=null){
$ip = ($ip) ? $ip : $_SERVER['REMOTE_ADDR'];
if (gethostbyname(ReverseIPOctets($ip).".".$_SERVER['SERVER_PORT'].".".ReverseIPOctets($_SERVER['SERVER_ADDR']).".ip-port.exitlist.torproject.org")=="127.0.0.2") {
return true;
} else {
return false;
}
}
function ReverseIPOctets($inputip){
$ipoc = explode(".",$inputip);
return $ipoc[3].".".$ipoc[2].".".$ipoc[1].".".$ipoc[0];
}
?>
<!doctype html>
<html lang="en">
<head>
<title>SSL Test</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta property="og:locale" content="en_US">
<meta property="og:site_name" content="Hakase's SSL Test Page">
<meta property="og:title" content="Hakase's SSL Test Page">
<meta property="og:url" content="//hakase.io/">
<meta property="og:type" content="website">
<meta property="og:image" content="//ssl.hakase.io/favicon.ico">
<meta property="og:description" content="SSL Test Page (TLS1.3, etc.)">
<style>
body img {
width: auto;
height: auto;
max-width: 100%;
}
.visible_hidden {
visibility: hidden;
}
</style>
</head>
<body>
<h1>SSL Page!</h1>
<p>
<?php
if ($_SERVER['SSL_PROTOCOL'] === 'TLSv1.3') {
$early_data = (!empty($_SERVER['SSL_EARLY_DATA'])) ? 'Enabled' : 'Not used';
echo ' <strong>' . $early_data . ' TLS 1.3 0-RTT (Experimental)</strong><br>' . PHP_EOL;
}
?>
<?php $curves = $_SERVER['SSL_CURVES'];
$curves = preg_replace('/0x[0-9a-fA-F]{4}(\:*)/', '', $curves); $curves = explode(':', $curves)[0]; $curves = ($curves) ? '('.$curves.')' : NULL; ?>
Connection method : <?php echo $_SERVER['SERVER_PROTOCOL']; ?> / <?php echo $_SERVER['SSL_PROTOCOL']; ?><?php if(!empty($_SERVER['SSL_TLS13'])) echo ' (draft '.$_SERVER['SSL_TLS13'].')'; echo ' / '.$_SERVER['SSL_CIPHER'];?> <?php echo $curves; ?><br>
Your browser support ciphers : <?php
$a = str_replace(':', ' / ', preg_replace('/0x[0-9a-fA-F]{4}(\:*)/', '', $_SERVER['SSL_CIPHERS']));
echo (substr($a, -3) === ' / ') ? substr($a, 0, -3) : $a;
?><br>
Your browser support curves : <?php
$a = str_replace(':', ' / ', preg_replace('/0x[0-9a-fA-F]{4}(\:*)/', '', $_SERVER['SSL_CURVES']));
echo (substr($a, -3) === ' / ') ? substr($a, 0, -3) : $a;
?> <br><a href="//dev.ssllabs.com/ssltest/viewMyClient.html" target="_blank">(ciphers detail view)</a>
<br><a href="//dev.ssllabs.com/ssltest/analyze.html?d=hakase.io" target="_blank">SSLLabs A+</a>
<br><a href="ssltest/hakase.io.html" target="_blank">testssl.sh</a>
</p>
<p>
OpenSSL Version : OpenSSL 1.1.2-dev
<br>- Patch : <a href="//hks.pw/ossl" target="_blank">My Git</a> / <a href="//github.com/hakasenyang/openssl-patch" target="_blank">Github</a> (Equal preference + Support draft 23, 26, 28 patch)
<br>PHP Version : <?php echo phpversion().PHP_EOL; ?>
<br>IP Address : <?php echo $_SERVER['REMOTE_ADDR']; if (isset($_SERVER['HTTP_X_REAL_IP'])) echo ' ('.$_SERVER['HTTP_X_REAL_IP'].')'.PHP_EOL; ?>
<br>Tor Check : <strong><?php echo (IsTorExitPoint()) ? 'Using Tor' : 'Not using Tor'; ?></strong>
<br>User-Agent : <?php echo $_SERVER['HTTP_USER_AGENT'].PHP_EOL; ?>
<br>GeoIP : <?php echo $_SERVER['GEOIP_CITY']; if ($_SERVER['GEOIP_CITY'] !== $_SERVER['GEOIP_SUBDIVISIONS']) echo ' / ' . $_SERVER['GEOIP_SUBDIVISIONS']; echo ' / ' . $_SERVER['GEOIP_COUNTRY_NAME']; echo PHP_EOL; ?>
<br>Server Info : <a href="//info.hakase.io/" target="_blank">phpSysInfo</a>
</p>
</body>
</html>
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c
index 4f9da0b..809fad7 100644
--- a/src/event/ngx_event_openssl.c
+++ b/src/event/ngx_event_openssl.c
@@ -3919,6 +3919,14 @@ ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
}
+ngx_int_t
+ngx_ssl_get_tls13(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
+{
+ s->data = (u_char *) SSL_get_version_tls13(c->ssl->connection);
+ return NGX_OK;
+}
+
+
ngx_int_t
ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool, ngx_str_t *s)
{
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h
index f3526a0..3c504dd 100644
--- a/src/event/ngx_event_openssl.h
+++ b/src/event/ngx_event_openssl.h
@@ -227,6 +227,8 @@ ngx_int_t ngx_ssl_check_host(ngx_connection_t *c, ngx_str_t *name);
ngx_int_t ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
+ngx_int_t ngx_ssl_get_tls13(ngx_connection_t *c, ngx_pool_t *pool,
+ ngx_str_t *s);
ngx_int_t ngx_ssl_get_cipher_name(ngx_connection_t *c, ngx_pool_t *pool,
ngx_str_t *s);
ngx_int_t ngx_ssl_get_ciphers(ngx_connection_t *c, ngx_pool_t *pool,
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c
index d7b0fe7..6c8e239 100644
--- a/src/http/modules/ngx_http_ssl_module.c
+++ b/src/http/modules/ngx_http_ssl_module.c
@@ -321,6 +321,9 @@ static ngx_http_variable_t ngx_http_ssl_vars[] = {
{ ngx_string("ssl_protocol"), NULL, ngx_http_ssl_static_variable,
(uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGEABLE, 0 },
+ { ngx_string("ssl_tls13"), NULL, ngx_http_ssl_static_variable,
+ (uintptr_t) ngx_ssl_get_tls13, NGX_HTTP_VAR_CHANGEABLE, 0 },
+
{ ngx_string("ssl_cipher"), NULL, ngx_http_ssl_static_variable,
(uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGEABLE, 0 },
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param SCRIPT_NAME $fastcgi_script_name;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param DOCUMENT_URI $document_uri;
fastcgi_param DOCUMENT_ROOT $document_root;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REQUEST_SCHEME $scheme;
fastcgi_param HTTP2 $http2;
fastcgi_param SSL_CIPHERS $ssl_ciphers;
fastcgi_param SSL_CURVES $ssl_curves;
fastcgi_param SSL_CIPHER $ssl_cipher;
fastcgi_param SSL_PROTOCOL $ssl_protocol;
fastcgi_param SSL_TLS13 $ssl_tls13 if_not_empty;
fastcgi_param SSL_EARLY_DATA $ssl_early_data if_not_empty;
fastcgi_param HTTPS $https if_not_empty;
fastcgi_param GATEWAY_INTERFACE CGI/1.1;
fastcgi_param SERVER_SOFTWARE nginx/$nginx_version;
# GeoIP
#fastcgi_param GEOIP_COUNTRY_CODE $geoip_country_code;
#fastcgi_param GEOIP_COUNTRY_NAME $geoip_country_name;
#fastcgi_param GEOIP_REGION_NAME $geoip_city_country_code;
#fastcgi_param GEOIP_REGION $geoip_city_continent_code;
#fastcgi_param GEOIP_CITY $geoip_city;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
# PHP only, required if PHP was built with --enable-force-cgi-redirect
fastcgi_param REDIRECT_STATUS 200;
fastcgi_param HTTP_STATUS $status;
diff --git a/doc/man1/ciphers.pod b/doc/man1/ciphers.pod
index 3aea982384..3c93eba0bf 100644
--- a/doc/man1/ciphers.pod
+++ b/doc/man1/ciphers.pod
@@ -400,6 +400,21 @@ permissible.
=back
+=head1 EQUAL PREFERENCE GROUPS
+
+If configuring a server, one may also configure equal-preference groups to
+partially respect the client's preferences when
+B<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 0a18a43544..195e543cac 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -1829,6 +1829,7 @@ __owur int SSL_get_early_data_status(const SSL *s);
__owur int SSL_get_error(const SSL *s, int ret_code);
__owur const char *SSL_get_version(const SSL *s);
+__owur const char *SSL_get_version_tls13(const SSL *s);
/* This sets the 'default' SSL version that SSL_new() will create */
__owur int SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth);
diff --git a/include/openssl/sslerr.h b/include/openssl/sslerr.h
index 87b295c9f9..d118d8e864 100644
--- a/include/openssl/sslerr.h
+++ b/include/openssl/sslerr.h
@@ -596,6 +596,8 @@ int ERR_load_SSL_strings(void);
# define SSL_R_MISSING_SUPPORTED_GROUPS_EXTENSION 209
# define SSL_R_MISSING_TMP_DH_KEY 171
# define SSL_R_MISSING_TMP_ECDH_KEY 311
+# define SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS 101
+# define SSL_R_NESTED_GROUP 108
# define SSL_R_NOT_ON_RECORD_BOUNDARY 182
# define SSL_R_NOT_REPLACING_CERTIFICATE 289
# define SSL_R_NOT_SERVER 284
@@ -726,9 +728,11 @@ int ERR_load_SSL_strings(void);
# define SSL_R_UNABLE_TO_FIND_PUBLIC_KEY_PARAMETERS 239
# define SSL_R_UNABLE_TO_LOAD_SSL3_MD5_ROUTINES 242
# define SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES 243
+# define SSL_R_UNEXPECTED_GROUP_CLOSE 109
# define SSL_R_UNEXPECTED_CCS_MESSAGE 262
# define SSL_R_UNEXPECTED_END_OF_EARLY_DATA 178
# define SSL_R_UNEXPECTED_MESSAGE 244
+# define SSL_R_UNEXPECTED_OPERATOR_IN_GROUP 110
# define SSL_R_UNEXPECTED_RECORD 245
# define SSL_R_UNINITIALIZED 276
# define SSL_R_UNKNOWN_ALERT_TYPE 246
diff --git a/include/openssl/tls1.h b/include/openssl/tls1.h
index 2e46cf80d3..0accc837a3 100644
--- a/include/openssl/tls1.h
+++ b/include/openssl/tls1.h
@@ -30,6 +30,16 @@ extern "C" {
# define TLS1_3_VERSION 0x0304
# define TLS_MAX_VERSION TLS1_3_VERSION
+/* TODO(TLS1.3) REMOVE ME: Version indicators for draft version */
+# define TLS1_3_VERSION_DRAFT_23 0x7f17
+# define TLS1_3_VERSION_DRAFT_26 0x7f1a
+# define TLS1_3_VERSION_DRAFT_27 0x7f1b
+# define TLS1_3_VERSION_DRAFT 0x7f1c
+# define TLS1_3_VERSION_DRAFT_TXT_23 "TLS 1.3 (draft 23)"
+# define TLS1_3_VERSION_DRAFT_TXT_26 "TLS 1.3 (draft 26)"
+# define TLS1_3_VERSION_DRAFT_TXT_27 "TLS 1.3 (draft 27)"
+# define TLS1_3_VERSION_DRAFT_TXT "TLS 1.3 (draft 28)"
+
/* Special value for method supporting multiple versions */
# define TLS_ANY_VERSION 0x10000
diff --git a/ssl/record/ssl3_record_tls13.c b/ssl/record/ssl3_record_tls13.c
index a11ed483e6..4fd583dd03 100644
--- a/ssl/record/ssl3_record_tls13.c
+++ b/ssl/record/ssl3_record_tls13.c
@@ -173,8 +173,9 @@ int tls13_enc(SSL *s, SSL3_RECORD *recs, size_t n_recs, int sending)
if (((alg_enc & SSL_AESCCM) != 0
&& EVP_CipherUpdate(ctx, NULL, &lenu, NULL,
(unsigned int)rec->length) <= 0)
- || EVP_CipherUpdate(ctx, NULL, &lenu, recheader,
- sizeof(recheader)) <= 0
+ || (s->version_draft != TLS1_3_VERSION_DRAFT_23
+ && EVP_CipherUpdate(ctx, NULL, &lenu, recheader,
+ sizeof(recheader)) <= 0)
|| EVP_CipherUpdate(ctx, rec->data, &lenu, rec->input,
(unsigned int)rec->length) <= 0
|| EVP_CipherFinal_ex(ctx, rec->data + lenu, &lenf) <= 0
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index 7713f767b2..a0af8ac001 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -31,7 +31,25 @@ const unsigned char tls12downgrade[] = {
};
/* The list of available TLSv1.3 ciphers */
+/* Since nginx can not set the TLS 1.3 cipher, remove it temporarily. */
static SSL_CIPHER tls13_ciphers[] = {
+ {
+ 0,
+ }
+};
+
+/*
+ * The list of available ciphers, mostly organized into the following
+ * groups:
+ * Always there
+ * EC
+ * PSK
+ * SRP (within that: RSA EC PSK)
+ * Cipher families: Chacha/poly, Camellia, Gost, IDEA, SEED
+ * Weak ciphers
+ */
+static SSL_CIPHER ssl3_ciphers[] = {
+ /* TLSv1.3 ciphers */
{
1,
TLS1_3_RFC_AES_128_GCM_SHA256,
@@ -111,20 +129,8 @@ static SSL_CIPHER tls13_ciphers[] = {
SSL_HANDSHAKE_MAC_SHA256,
128,
128,
- }
-};
-
-/*
- * The list of available ciphers, mostly organized into the following
- * groups:
- * Always there
- * EC
- * PSK
- * SRP (within that: RSA EC PSK)
- * Cipher families: Chacha/poly, Camellia, Gost, IDEA, SEED
- * Weak ciphers
- */
-static SSL_CIPHER ssl3_ciphers[] = {
+ },
+ /* List of cipher below TLSv1.3 */
{
1,
SSL3_TXT_RSA_NULL_MD5,
@@ -167,7 +173,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
SSL_aRSA,
SSL_3DES,
SSL_SHA1,
- SSL3_VERSION, TLS1_2_VERSION,
+ SSL3_VERSION, TLS1_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_NOT_DEFAULT | SSL_MEDIUM | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
@@ -232,7 +238,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
SSL_aRSA,
SSL_AES128,
SSL_SHA1,
- SSL3_VERSION, TLS1_2_VERSION,
+ SSL3_VERSION, TLS1_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
@@ -296,7 +302,7 @@ static SSL_CIPHER ssl3_ciphers[] = {
SSL_aRSA,
SSL_AES256,
SSL_SHA1,
- SSL3_VERSION, TLS1_2_VERSION,
+ SSL3_VERSION, TLS1_VERSION,
DTLS1_BAD_VER, DTLS1_2_VERSION,
SSL_HIGH | SSL_FIPS,
SSL_HANDSHAKE_MAC_DEFAULT | TLS1_PRF,
@@ -4104,6 +4110,17 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
return 1;
}
+struct ssl_cipher_preference_list_st* ssl_get_cipher_preferences(SSL *s)
+{
+ if (s->cipher_list != NULL)
+ return (s->cipher_list);
+
+ if ((s->ctx != NULL) && (s->ctx->cipher_list != NULL))
+ return (s->ctx->cipher_list);
+
+ return NULL;
+}
+
/*
* ssl3_choose_cipher - choose a cipher from those offered by the client
* @s: SSL connection
@@ -4113,16 +4130,24 @@ int ssl3_put_cipher_by_char(const SSL_CIPHER *c, WPACKET *pkt, size_t *len)
* Returns the selected cipher or NULL when no common ciphers.
*/
const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
- STACK_OF(SSL_CIPHER) *srvr)
+ struct ssl_cipher_preference_list_st
+ *server_pref)
{
const SSL_CIPHER *c, *ret = NULL;
- STACK_OF(SSL_CIPHER) *prio, *allow;
- int i, ii, ok, prefer_sha256 = 0;
+ STACK_OF(SSL_CIPHER) *srvr = server_pref->ciphers, *prio, *allow;
+ int i, ii, ok, prefer_sha256 = 0, safari_ec = 0;
unsigned long alg_k = 0, alg_a = 0, mask_k = 0, mask_a = 0;
const EVP_MD *mdsha256 = EVP_sha256();
-#ifndef OPENSSL_NO_CHACHA
- STACK_OF(SSL_CIPHER) *prio_chacha = NULL;
-#endif
+
+ /* in_group_flags will either be NULL, or will point to an array of
+ * bytes which indicate equal-preference groups in the |prio| stack.
+ * See the comment about |in_group_flags| in the
+ * |ssl_cipher_preference_list_st| struct. */
+ const uint8_t *in_group_flags;
+
+ /* group_min contains the minimal index so far found in a group, or -1
+ * if no such value exists yet. */
+ int group_min = -1;
/* Let's see which ciphers we can support */
@@ -4149,54 +4174,13 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
#endif
/* SUITE-B takes precedence over server preference and ChaCha priortiy */
- if (tls1_suiteb(s)) {
+ if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE || tls1_suiteb(s)) {
prio = srvr;
+ in_group_flags = server_pref->in_group_flags;
allow = clnt;
- } else if (s->options & SSL_OP_CIPHER_SERVER_PREFERENCE) {
- prio = srvr;
- allow = clnt;
-#ifndef OPENSSL_NO_CHACHA
- /* If ChaCha20 is at the top of the client preference list,
- and there are ChaCha20 ciphers in the server list, then
- temporarily prioritize all ChaCha20 ciphers in the servers list. */
- if (s->options & SSL_OP_PRIORITIZE_CHACHA && sk_SSL_CIPHER_num(clnt) > 0) {
- c = sk_SSL_CIPHER_value(clnt, 0);
- if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
- /* ChaCha20 is client preferred, check server... */
- int num = sk_SSL_CIPHER_num(srvr);
- int found = 0;
- for (i = 0; i < num; i++) {
- c = sk_SSL_CIPHER_value(srvr, i);
- if (c->algorithm_enc == SSL_CHACHA20POLY1305) {
- found = 1;
- break;
- }
- }
- if (found) {
- prio_chacha = sk_SSL_CIPHER_new_reserve(NULL, num);
- /* if reserve fails, then there's likely a memory issue */
- if (prio_chacha != NULL) {
- /* Put all ChaCha20 at the top, starting with the one we just found */
- sk_SSL_CIPHER_push(prio_chacha, c);
- for (i++; i < num; i++) {
- c = sk_SSL_CIPHER_value(srvr, i);
- if (c->algorithm_enc == SSL_CHACHA20POLY1305)
- sk_SSL_CIPHER_push(prio_chacha, c);
- }
- /* Pull in the rest */
- for (i = 0; i < num; i++) {
- c = sk_SSL_CIPHER_value(srvr, i);
- if (c->algorithm_enc != SSL_CHACHA20POLY1305)
- sk_SSL_CIPHER_push(prio_chacha, c);
- }
- prio = prio_chacha;
- }
- }
- }
- }
-# endif
} else {
prio = clnt;
+ in_group_flags = NULL;
allow = srvr;
}
@@ -4227,14 +4211,16 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
for (i = 0; i < sk_SSL_CIPHER_num(prio); i++) {
c = sk_SSL_CIPHER_value(prio, i);
+ ok = 1;
+
/* Skip ciphers not supported by the protocol version */
if (!SSL_IS_DTLS(s) &&
((s->version < c->min_tls) || (s->version > c->max_tls)))
- continue;
+ ok = 0;
if (SSL_IS_DTLS(s) &&
(DTLS_VERSION_LT(s->version, c->min_dtls) ||
DTLS_VERSION_GT(s->version, c->max_dtls)))
- continue;
+ ok = 0;
/*
* Since TLS 1.3 ciphersuites can be used with any auth or
@@ -4256,10 +4242,10 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
#ifndef OPENSSL_NO_PSK
/* with PSK there must be server callback set */
if ((alg_k & SSL_PSK) && s->psk_server_callback == NULL)
- continue;
+ ok = 0;
#endif /* OPENSSL_NO_PSK */
- ok = (alg_k & mask_k) && (alg_a & mask_a);
+ ok = ok && (alg_k & mask_k) && (alg_a & mask_a);
#ifdef CIPHER_DEBUG
fprintf(stderr, "%d:[%08lX:%08lX:%08lX:%08lX]%p:%s\n", ok, alg_k,
alg_a, mask_k, mask_a, (void *)c, c->name);
@@ -4276,6 +4262,14 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
if (!ok)
continue;
+
+ safari_ec = 0;
+#if !defined(OPENSSL_NO_EC)
+ if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)) {
+ if (s->s3->is_probably_safari)
+ safari_ec = 1;
+ }
+#endif
}
ii = sk_SSL_CIPHER_find(allow, c);
if (ii >= 0) {
@@ -4283,14 +4277,7 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
if (!ssl_security(s, SSL_SECOP_CIPHER_SHARED,
c->strength_bits, 0, (void *)c))
continue;
-#if !defined(OPENSSL_NO_EC)
- if ((alg_k & SSL_kECDHE) && (alg_a & SSL_aECDSA)
- && s->s3->is_probably_safari) {
- if (!ret)
- ret = sk_SSL_CIPHER_value(allow, ii);
- continue;
- }
-#endif
+
if (prefer_sha256) {
const SSL_CIPHER *tmp = sk_SSL_CIPHER_value(allow, ii);
@@ -4302,13 +4289,38 @@ const SSL_CIPHER *ssl3_choose_cipher(SSL *s, STACK_OF(SSL_CIPHER) *clnt,
ret = tmp;
continue;
}
- ret = sk_SSL_CIPHER_value(allow, ii);
+
+ if (in_group_flags != NULL && in_group_flags[i] == 1) {
+ /* This element of |prio| is in a group. Update
+ * the minimum index found so far and continue
+ * looking. */
+ if (group_min == -1 || group_min > ii)
+ group_min = ii;
+ } else {
+ if (group_min != -1 && group_min < ii)
+ ii = group_min;
+ if (safari_ec) {
+ if (!ret)
+ ret = sk_SSL_CIPHER_value(allow, ii);
+ continue;
+ }
+ ret = sk_SSL_CIPHER_value(allow, ii);
+ break;
+ }
+ }
+
+ if (in_group_flags != NULL && !in_group_flags[i] && group_min != -1) {
+ /* We are about to leave a group, but we found a match
+ * in it, so that's our answer. */
+ if (safari_ec) {
+ if (!ret)
+ ret = sk_SSL_CIPHER_value(allow, group_min);
+ continue;
+ }
+ ret = sk_SSL_CIPHER_value(allow, group_min);
break;
}
}
-#ifndef OPENSSL_NO_CHACHA
- sk_SSL_CIPHER_free(prio_chacha);
-#endif
return ret;
}
diff --git a/ssl/ssl_ciph.c b/ssl/ssl_ciph.c
index 14066d0ea4..dc190fa334 100644
--- a/ssl/ssl_ciph.c
+++ b/ssl/ssl_ciph.c
@@ -190,6 +190,7 @@ typedef struct cipher_order_st {
const SSL_CIPHER *cipher;
int active;
int dead;
+ int in_group;
struct cipher_order_st *next, *prev;
} CIPHER_ORDER;
@@ -294,6 +295,7 @@ static const SSL_CIPHER cipher_aliases[] = {
{0, SSL_TXT_TLSV1, NULL, 0, 0, 0, 0, 0, TLS1_VERSION},
{0, "TLSv1.0", NULL, 0, 0, 0, 0, 0, TLS1_VERSION},
{0, SSL_TXT_TLSV1_2, NULL, 0, 0, 0, 0, 0, TLS1_2_VERSION},
+ {0, "TLS13", NULL, 0, 0, 0, 0, 0, TLS1_3_VERSION},
/* strength classes */
{0, SSL_TXT_LOW, NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, SSL_LOW},
@@ -679,6 +681,7 @@ static void ssl_cipher_collect_ciphers(const SSL_METHOD *ssl_method,
co_list[co_list_num].next = NULL;
co_list[co_list_num].prev = NULL;
co_list[co_list_num].active = 0;
+ co_list[co_list_num].in_group = 0;
co_list_num++;
}
@@ -772,8 +775,8 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
uint32_t alg_auth, uint32_t alg_enc,
uint32_t alg_mac, int min_tls,
uint32_t algo_strength, int rule,
- int32_t strength_bits, CIPHER_ORDER **head_p,
- CIPHER_ORDER **tail_p)
+ int32_t strength_bits, int in_group,
+ CIPHER_ORDER **head_p, CIPHER_ORDER **tail_p)
{
CIPHER_ORDER *head, *tail, *curr, *next, *last;
const SSL_CIPHER *cp;
@@ -781,9 +784,9 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
#ifdef CIPHER_DEBUG
fprintf(stderr,
- "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d)\n",
+ "Applying rule %d with %08x/%08x/%08x/%08x/%08x %08x (%d) g:%d\n",
rule, alg_mkey, alg_auth, alg_enc, alg_mac, min_tls,
- algo_strength, strength_bits);
+ algo_strength, strength_bits, in_group);
#endif
if (rule == CIPHER_DEL || rule == CIPHER_BUMP)
@@ -860,6 +863,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
if (!curr->active) {
ll_append_tail(&head, curr, &tail);
curr->active = 1;
+ curr->in_group = in_group;
}
}
/* Move the added cipher to this location */
@@ -867,6 +871,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
/* reverse == 0 */
if (curr->active) {
ll_append_tail(&head, curr, &tail);
+ curr->in_group = 0;
}
} else if (rule == CIPHER_DEL) {
/* reverse == 1 */
@@ -878,6 +883,7 @@ static void ssl_cipher_apply_rule(uint32_t cipher_id, uint32_t alg_mkey,
*/
ll_append_head(&head, curr, &tail);
curr->active = 0;
+ curr->in_group = 0;
}
} else if (rule == CIPHER_BUMP) {
if (curr->active)
@@ -945,8 +951,8 @@ static int ssl_cipher_strength_sort(CIPHER_ORDER **head_p,
*/
for (i = max_strength_bits; i >= 0; i--)
if (number_uses[i] > 0)
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, head_p,
- tail_p);
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ORD, i, 0,
+ head_p, tail_p);
OPENSSL_free(number_uses);
return 1;
@@ -960,7 +966,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
uint32_t alg_mkey, alg_auth, alg_enc, alg_mac, algo_strength;
int min_tls;
const char *l, *buf;
- int j, multi, found, rule, retval, ok, buflen;
+ int j, multi, found, rule, retval, ok, buflen, in_group = 0, has_group = 0;
uint32_t cipher_id = 0;
char ch;
@@ -971,18 +977,66 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
if (ch == '\0')
break; /* done */
- if (ch == '-') {
+ if (in_group) {
+ if (ch == ']') {
+ if (!in_group) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+ SSL_R_UNEXPECTED_GROUP_CLOSE);
+ retval = found = in_group = 0;
+ break;
+ }
+ if (*tail_p)
+ (*tail_p)->in_group = 0;
+ in_group = 0;
+ l++;
+ continue;
+ }
+ if (ch == '|') {
+ rule = CIPHER_ADD;
+ l++;
+ continue;
+ } else if (!(ch >= 'a' && ch <= 'z')
+ && !(ch >= 'A' && ch <= 'Z')
+ && !(ch >= '0' && ch <= '9')) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+ SSL_R_UNEXPECTED_OPERATOR_IN_GROUP);
+ retval = found = in_group = 0;
+ break;
+ } else {
+ rule = CIPHER_ADD;
+ }
+ } else if (ch == '-') {
rule = CIPHER_DEL;
l++;
} else if (ch == '+') {
rule = CIPHER_ORD;
l++;
+ } else if (ch == '!' && has_group) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+ retval = found = in_group = 0;
+ break;
} else if (ch == '!') {
rule = CIPHER_KILL;
l++;
+ } else if (ch == '@' && has_group) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR,
+ SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS);
+ retval = found = in_group = 0;
+ break;
} else if (ch == '@') {
rule = CIPHER_SPECIAL;
l++;
+ } else if (ch == '[') {
+ if (in_group) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_NESTED_GROUP);
+ retval = found = in_group = 0;
+ break;
+ }
+ in_group = 1;
+ has_group = 1;
+ l++;
+ continue;
} else {
rule = CIPHER_ADD;
}
@@ -1007,7 +1061,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
while (((ch >= 'A') && (ch <= 'Z')) ||
((ch >= '0') && (ch <= '9')) ||
((ch >= 'a') && (ch <= 'z')) ||
- (ch == '-') || (ch == '.') || (ch == '='))
+ (ch == '-') || (ch == '.') || (ch == '=') || (ch == '_'))
#else
while (isalnum((unsigned char)ch) || (ch == '-') || (ch == '.')
|| (ch == '='))
@@ -1024,7 +1078,7 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
* alphanumeric, so we call this an error.
*/
SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
- retval = found = 0;
+ retval = found = in_group = 0;
l++;
break;
}
@@ -1203,8 +1257,8 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
} else if (found) {
ssl_cipher_apply_rule(cipher_id,
alg_mkey, alg_auth, alg_enc, alg_mac,
- min_tls, algo_strength, rule, -1, head_p,
- tail_p);
+ min_tls, algo_strength, rule, -1, in_group,
+ head_p, tail_p);
} else {
while ((*l != '\0') && !ITEM_SEP(*l))
l++;
@@ -1213,6 +1267,11 @@ static int ssl_cipher_process_rulestr(const char *rule_str,
break; /* done */
}
+ if (in_group) {
+ SSLerr(SSL_F_SSL_CIPHER_PROCESS_RULESTR, SSL_R_INVALID_COMMAND);
+ retval = 0;
+ }
+
return retval;
}
@@ -1377,7 +1436,7 @@ int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
if (ret && ctx->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */
- return update_cipher_list(&ctx->cipher_list, &ctx->cipher_list_by_id,
+ return update_cipher_list(&ctx->cipher_list->ciphers, &ctx->cipher_list_by_id,
ctx->tls13_ciphersuites);
}
@@ -1390,7 +1449,7 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
if (ret && s->cipher_list != NULL) {
/* We already have a cipher_list, so we need to update it */
- return update_cipher_list(&s->cipher_list, &s->cipher_list_by_id,
+ return update_cipher_list(&s->cipher_list->ciphers, &s->cipher_list_by_id,
s->tls13_ciphersuites);
}
@@ -1399,17 +1458,20 @@ int SSL_set_ciphersuites(SSL *s, const char *str)
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
- STACK_OF(SSL_CIPHER) **cipher_list,
+ struct ssl_cipher_preference_list_st **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str,
CERT *c)
{
- int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases, i;
+ int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
uint32_t disabled_mkey, disabled_auth, disabled_enc, disabled_mac;
- STACK_OF(SSL_CIPHER) *cipherstack;
+ STACK_OF(SSL_CIPHER) *cipherstack = NULL;
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
const SSL_CIPHER **ca_list = NULL;
+ uint8_t *in_group_flags = NULL;
+ unsigned int num_in_group_flags = 0;
+ struct ssl_cipher_preference_list_st *pref_list = NULL;
/*
* Return with error if nothing to do.
@@ -1458,16 +1520,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* preference).
*/
ssl_cipher_apply_rule(0, SSL_kECDHE, SSL_aECDSA, 0, 0, 0, 0, CIPHER_ADD,
- -1, &head, &tail);
- ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head,
- &tail);
- ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head,
- &tail);
+ -1, 0, &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0,
+ &head, &tail);
+ ssl_cipher_apply_rule(0, SSL_kECDHE, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0,
+ &head, &tail);
/* Within each strength group, we prefer GCM over CHACHA... */
- ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1,
+ ssl_cipher_apply_rule(0, 0, 0, SSL_AESGCM, 0, 0, 0, CIPHER_ADD, -1, 0,
&head, &tail);
- ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1,
+ ssl_cipher_apply_rule(0, 0, 0, SSL_CHACHA20, 0, 0, 0, CIPHER_ADD, -1, 0,
&head, &tail);
/*
@@ -1476,13 +1538,13 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* strength.
*/
ssl_cipher_apply_rule(0, 0, 0, SSL_AES ^ SSL_AESGCM, 0, 0, 0, CIPHER_ADD,
- -1, &head, &tail);
+ -1, 0, &head, &tail);
/* Temporarily enable everything else for sorting */
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_ADD, -1, 0, &head, &tail);
/* Low priority for MD5 */
- ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, &head,
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_MD5, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
/*
@@ -1490,16 +1552,16 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* disabled. (For applications that allow them, they aren't too bad, but
* we prefer authenticated ciphers.)
*/
- ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
+ ssl_cipher_apply_rule(0, 0, SSL_aNULL, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
- ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
+ ssl_cipher_apply_rule(0, SSL_kRSA, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
- ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, &head,
+ ssl_cipher_apply_rule(0, SSL_kPSK, 0, 0, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
/* RC4 is sort-of broken -- move to the end */
- ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, &head,
+ ssl_cipher_apply_rule(0, 0, 0, SSL_RC4, 0, 0, 0, CIPHER_ORD, -1, 0, &head,
&tail);
/*
@@ -1515,7 +1577,7 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* Partially overrule strength sort to prefer TLS 1.2 ciphers/PRFs.
* TODO(openssl-team): is there an easier way to accomplish all this?
*/
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1,
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_2_VERSION, 0, CIPHER_BUMP, -1, 0,
&head, &tail);
/*
@@ -1531,15 +1593,18 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
* Because we now bump ciphers to the top of the list, we proceed in
* reverse order of preference.
*/
- ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1,
+ ssl_cipher_apply_rule(0, 0, 0, 0, SSL_AEAD, 0, 0, CIPHER_BUMP, -1, 0,
&head, &tail);
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, 0, 0, 0,
- CIPHER_BUMP, -1, &head, &tail);
+ CIPHER_BUMP, -1, 0, &head, &tail);
ssl_cipher_apply_rule(0, SSL_kDHE | SSL_kECDHE, 0, 0, SSL_AEAD, 0, 0,
- CIPHER_BUMP, -1, &head, &tail);
+ CIPHER_BUMP, -1, 0, &head, &tail);
+
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, TLS1_3_VERSION, 0, CIPHER_BUMP, -1, 0,
+ &head, &tail);
/* Now disable everything (maintaining the ordering!) */
- ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, &head, &tail);
+ ssl_cipher_apply_rule(0, 0, 0, 0, 0, 0, 0, CIPHER_DEL, -1, 0, &head, &tail);
/*
* We also need cipher aliases for selecting based on the rule_str.
@@ -1553,9 +1618,8 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
num_of_alias_max = num_of_ciphers + num_of_group_aliases + 1;
ca_list = OPENSSL_malloc(sizeof(*ca_list) * num_of_alias_max);
if (ca_list == NULL) {
- OPENSSL_free(co_list);
SSLerr(SSL_F_SSL_CREATE_CIPHER_LIST, ERR_R_MALLOC_FAILURE);
- return NULL; /* Failure */
+ goto err; /* Failure */
}
ssl_cipher_collect_aliases(ca_list, num_of_group_aliases,
disabled_mkey, disabled_auth, disabled_enc,
@@ -1580,28 +1644,19 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
OPENSSL_free(ca_list); /* Not needed anymore */
- if (!ok) { /* Rule processing failure */
- OPENSSL_free(co_list);
- return NULL;
- }
+ if (!ok)
+ goto err; /* Rule processing failure */
/*
* Allocate new "cipherstack" for the result, return with error
* if we cannot get one.
*/
- if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL) {
- OPENSSL_free(co_list);
- return NULL;
- }
+ if ((cipherstack = sk_SSL_CIPHER_new_null()) == NULL)
+ goto err;
- /* Add TLSv1.3 ciphers first - we always prefer those if possible */
- for (i = 0; i < sk_SSL_CIPHER_num(tls13_ciphersuites); i++) {
- if (!sk_SSL_CIPHER_push(cipherstack,
- sk_SSL_CIPHER_value(tls13_ciphersuites, i))) {
- sk_SSL_CIPHER_free(cipherstack);
- return NULL;
- }
- }
+ in_group_flags = OPENSSL_malloc(num_of_ciphers);
+ if (!in_group_flags)
+ goto err;
/*
* The cipher selection for the list is done. The ciphers are added
@@ -1609,26 +1664,50 @@ STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
*/
for (curr = head; curr != NULL; curr = curr->next) {
if (curr->active) {
- if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher)) {
- OPENSSL_free(co_list);
- sk_SSL_CIPHER_free(cipherstack);
- return NULL;
- }
+ if (!sk_SSL_CIPHER_push(cipherstack, curr->cipher))
+ goto err;
+ in_group_flags[num_in_group_flags++] = curr->in_group;
#ifdef CIPHER_DEBUG
fprintf(stderr, "<%s>\n", curr->cipher->name);
#endif
}
}
- OPENSSL_free(co_list); /* Not needed any longer */
- if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack)) {
- sk_SSL_CIPHER_free(cipherstack);
- return NULL;
- }
- sk_SSL_CIPHER_free(*cipher_list);
- *cipher_list = cipherstack;
+ OPENSSL_free(co_list); /* Not needed any longer */
+ co_list = NULL;
+
+ if (!update_cipher_list_by_id(cipher_list_by_id, cipherstack))
+ goto err;
+
+ pref_list = OPENSSL_malloc(sizeof(struct ssl_cipher_preference_list_st));
+ if (!pref_list)
+ goto err;
+ pref_list->ciphers = cipherstack;
+ pref_list->in_group_flags = OPENSSL_malloc(num_in_group_flags);
+ if (!pref_list->in_group_flags)
+ goto err;
+ memcpy(pref_list->in_group_flags, in_group_flags, num_in_group_flags);
+ OPENSSL_free(in_group_flags);
+ in_group_flags = NULL;
+ if (*cipher_list != NULL)
+ ssl_cipher_preference_list_free(*cipher_list);
+ *cipher_list = pref_list;
+ pref_list = NULL;
return cipherstack;
+
+err:
+ if (co_list)
+ OPENSSL_free(co_list);
+ if (in_group_flags)
+ OPENSSL_free(in_group_flags);
+ if (cipherstack)
+ sk_SSL_CIPHER_free(cipherstack);
+ if (pref_list && pref_list->in_group_flags)
+ OPENSSL_free(pref_list->in_group_flags);
+ if (pref_list)
+ OPENSSL_free(pref_list);
+ return NULL;
}
char *SSL_CIPHER_description(const SSL_CIPHER *cipher, char *buf, int len)
diff --git a/ssl/ssl_err.c b/ssl/ssl_err.c
index 11331ce41f..cfc770b8d6 100644
--- a/ssl/ssl_err.c
+++ b/ssl/ssl_err.c
@@ -965,6 +965,9 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_DH_KEY), "missing tmp dh key"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MISSING_TMP_ECDH_KEY),
"missing tmp ecdh key"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_MIXED_SPECIAL_OPERATOR_WITH_GROUPS),
+ "mixed special operator with groups"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NESTED_GROUP), "nested group"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_ON_RECORD_BOUNDARY),
"not on record boundary"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_NOT_REPLACING_CERTIFICATE),
@@ -1199,11 +1202,14 @@ static const ERR_STRING_DATA SSL_str_reasons[] = {
"unable to load ssl3 md5 routines"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNABLE_TO_LOAD_SSL3_SHA1_ROUTINES),
"unable to load ssl3 sha1 routines"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_GROUP_CLOSE), "unexpected group close"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_CCS_MESSAGE),
"unexpected ccs message"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_END_OF_EARLY_DATA),
"unexpected end of early data"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_MESSAGE), "unexpected message"},
+ {ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_OPERATOR_IN_GROUP),
+ "unexpected operator in group"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNEXPECTED_RECORD), "unexpected record"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNINITIALIZED), "uninitialized"},
{ERR_PACK(ERR_LIB_SSL, 0, SSL_R_UNKNOWN_ALERT_TYPE), "unknown alert type"},
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index ec5b1554f7..f81ae38839 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -1117,6 +1117,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;
@@ -1157,7 +1222,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;
}
@@ -2934,7 +3000,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->tls13_ciphersuites,
&ret->cipher_list, &ret->cipher_list_by_id,
SSL_DEFAULT_CIPHER_LIST, ret->cert)
- || sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
+ || sk_SSL_CIPHER_num(ret->cipher_list->ciphers) <= 0) {
SSLerr(SSL_F_SSL_CTX_NEW, SSL_R_LIBRARY_HAS_NO_CIPHERS);
goto err2;
}
@@ -3107,7 +3173,7 @@ void SSL_CTX_free(SSL_CTX *a)
#ifndef OPENSSL_NO_CT
CTLOG_STORE_free(a->ctlog_store);
#endif
- sk_SSL_CIPHER_free(a->cipher_list);
+ ssl_cipher_preference_list_free(a->cipher_list);
sk_SSL_CIPHER_free(a->cipher_list_by_id);
sk_SSL_CIPHER_free(a->tls13_ciphersuites);
ssl_cert_free(a->cert);
@@ -3657,6 +3723,35 @@ const char *SSL_get_version(const SSL *s)
return ssl_protocol_to_string(s->version);
}
+const char *ssl_version_tls13_to_string(int version)
+{
+ switch(version)
+ {
+ case TLS1_3_VERSION_DRAFT_23:
+ return "23";
+
+ case TLS1_3_VERSION_DRAFT_26:
+ return "26";
+
+ case TLS1_3_VERSION_DRAFT_27:
+ return "27";
+
+ case TLS1_3_VERSION_DRAFT:
+ return "28";
+
+ case TLS1_3_VERSION:
+ return "";
+
+ default:
+ return "";
+ }
+}
+
+const char *SSL_get_version_tls13(const SSL *s)
+{
+ return ssl_version_tls13_to_string(s->version_draft);
+}
+
SSL *SSL_dup(SSL *s)
{
STACK_OF(X509_NAME) *sk;
@@ -3756,13 +3851,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 8afb117372..00a36e7111 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -502,6 +502,7 @@ struct ssl_method_st {
struct ssl_session_st {
int ssl_version; /* what ssl version session info is being kept
* in here? */
+ int ssl_version_draft;
size_t master_key_length;
/* TLSv1.3 early_secret used for external PSKs */
@@ -737,9 +738,46 @@ typedef struct ssl_ctx_ext_secure_st {
unsigned char tick_aes_key[TLSEXT_TICK_KEY_LENGTH];
} SSL_CTX_EXT_SECURE;
+/* ssl_cipher_preference_list_st contains a list of SSL_CIPHERs with
+ * equal-preference groups. For TLS clients, the groups are moot because the
+ * server picks the cipher and groups cannot be expressed on the wire. However,
+ * for servers, the equal-preference groups allow the client's preferences to
+ * be partially respected. (This only has an effect with
+ * SSL_OP_CIPHER_SERVER_PREFERENCE).
+ *
+ * The equal-preference groups are expressed by grouping SSL_CIPHERs together.
+ * All elements of a group have the same priority: no ordering is expressed
+ * within a group.
+ *
+ * The values in |ciphers| are in one-to-one correspondence with
+ * |in_group_flags|. (That is, sk_SSL_CIPHER_num(ciphers) is the number of
+ * bytes in |in_group_flags|.) The bytes in |in_group_flags| are either 1, to
+ * indicate that the corresponding SSL_CIPHER is not the last element of a
+ * group, or 0 to indicate that it is.
+ *
+ * For example, if |in_group_flags| contains all zeros then that indicates a
+ * traditional, fully-ordered preference. Every SSL_CIPHER is the last element
+ * of the group (i.e. they are all in a one-element group).
+ *
+ * For a more complex example, consider:
+ * ciphers: A B C D E F
+ * in_group_flags: 1 1 0 0 1 0
+ *
+ * That would express the following, order:
+ *
+ * A E
+ * B -> D -> F
+ * C
+ */
+struct ssl_cipher_preference_list_st {
+ STACK_OF(SSL_CIPHER) *ciphers;
+ uint8_t *in_group_flags;
+};
+
+
struct ssl_ctx_st {
const SSL_METHOD *method;
- STACK_OF(SSL_CIPHER) *cipher_list;
+ struct ssl_cipher_preference_list_st *cipher_list;
/* same as above but sorted for lookup */
STACK_OF(SSL_CIPHER) *cipher_list_by_id;
/* TLSv1.3 specific ciphersuites */
@@ -1074,6 +1112,8 @@ struct ssl_st {
* DTLS1_VERSION)
*/
int version;
+ /* TODO(TLS1.3): Remove this before release */
+ int version_draft;
/* SSLv3 */
const SSL_METHOD *method;
/*
@@ -1132,7 +1172,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;
@@ -2214,6 +2254,7 @@ struct openssl_ssl_test_functions {
};
const char *ssl_protocol_to_string(int version);
+const char *ssl_version_tls13_to_string(int version);
/* Returns true if certificate and private key for 'idx' are present */
static ossl_inline int ssl_has_cert(const SSL *s, int idx)
@@ -2253,7 +2294,7 @@ __owur int ssl_cipher_ptr_id_cmp(const SSL_CIPHER *const *ap,
const SSL_CIPHER *const *bp);
__owur STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *ssl_method,
STACK_OF(SSL_CIPHER) *tls13_ciphersuites,
- STACK_OF(SSL_CIPHER) **cipher_list,
+ struct ssl_cipher_preference_list_st **cipher_list,
STACK_OF(SSL_CIPHER) **cipher_list_by_id,
const char *rule_str,
CERT *c);
@@ -2263,6 +2304,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,
@@ -2346,7 +2394,7 @@ __owur unsigned long ssl3_output_cert_chain(SSL *s, WPACKET *pkt,
CERT_PKEY *cpk);
__owur const SSL_CIPHER *ssl3_choose_cipher(SSL *ssl,
STACK_OF(SSL_CIPHER) *clnt,
- STACK_OF(SSL_CIPHER) *srvr);
+ struct ssl_cipher_preference_list_st *srvr);
__owur int ssl3_digest_cached_records(SSL *s, int keep);
__owur int ssl3_new(SSL *s);
void ssl3_free(SSL *s);
diff --git a/ssl/ssl_txt.c b/ssl/ssl_txt.c
index cf6e4c3c05..1cde358cbc 100644
--- a/ssl/ssl_txt.c
+++ b/ssl/ssl_txt.c
@@ -40,8 +40,17 @@ int SSL_SESSION_print(BIO *bp, const SSL_SESSION *x)
istls13 = (x->ssl_version == TLS1_3_VERSION);
if (BIO_puts(bp, "SSL-Session:\n") <= 0)
goto err;
+
s = ssl_protocol_to_string(x->ssl_version);
- if (BIO_printf(bp, " Protocol : %s\n", s) <= 0)
+ if (BIO_printf(bp, " Protocol : %s", s) <= 0)
+ goto err;
+
+ s = ssl_version_tls13_to_string(x->ssl_version_draft);
+ if (strlen(s) > 0)
+ if (BIO_printf(bp, " (draft %s)", s) <= 0)
+ goto err;
+
+ if (BIO_puts(bp, "\n") <= 0)
goto err;
if (x->cipher == NULL) {
diff --git a/ssl/statem/extensions.c b/ssl/statem/extensions.c
index 8422161dc1..6e59b01d42 100644
--- a/ssl/statem/extensions.c
+++ b/ssl/statem/extensions.c
@@ -998,7 +998,9 @@ static int final_server_name(SSL *s, unsigned int context, int sent)
switch (ret) {
case SSL_TLSEXT_ERR_ALERT_FATAL:
- SSLfatal(s, altmp, SSL_F_FINAL_SERVER_NAME, SSL_R_CALLBACK_FAILED);
+ s->statem.in_init = 1;
+ s->statem.state = MSG_FLOW_ERROR;
+ ssl3_send_alert(s, SSL3_AL_FATAL, SSL_F_FINAL_RENEGOTIATE);
return 0;
case SSL_TLSEXT_ERR_ALERT_WARNING:
diff --git a/ssl/statem/extensions_clnt.c b/ssl/statem/extensions_clnt.c
index 4b5e6fe2b8..99981c9e37 100644
--- a/ssl/statem/extensions_clnt.c
+++ b/ssl/statem/extensions_clnt.c
@@ -530,8 +530,25 @@ EXT_RETURN tls_construct_ctos_supported_versions(SSL *s, WPACKET *pkt,
return EXT_RETURN_FAIL;
}
+ /*
+ * TODO(TLS1.3): There is some discussion on the TLS list as to whether
+ * we should include versions <TLS1.2. For the moment we do. To be
+ * reviewed later.
+ */
for (currv = max_version; currv >= min_version; currv--) {
- if (!WPACKET_put_bytes_u16(pkt, currv)) {
+ /* TODO(TLS1.3): Remove this first if clause prior to release!! */
+ if (currv == TLS1_3_VERSION) {
+ if (!WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION)
+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT)
+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_27)
+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_26)
+ || !WPACKET_put_bytes_u16(pkt, TLS1_3_VERSION_DRAFT_23)) {
+ SSLfatal(s, SSL_AD_INTERNAL_ERROR,
+ SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
+ ERR_R_INTERNAL_ERROR);
+ return EXT_RETURN_FAIL;
+ }
+ } else if (!WPACKET_put_bytes_u16(pkt, currv)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_CTOS_SUPPORTED_VERSIONS,
ERR_R_INTERNAL_ERROR);
@@ -1760,6 +1777,15 @@ int tls_parse_stoc_supported_versions(SSL *s, PACKET *pkt, unsigned int context,
return 0;
}
+ /* TODO(TLS1.3): Remove this before release */
+ if (version == TLS1_3_VERSION_DRAFT
+ || version == TLS1_3_VERSION_DRAFT_27
+ || version == TLS1_3_VERSION_DRAFT_26
+ || version == TLS1_3_VERSION_DRAFT_23) {
+ s->version_draft = version;
+ version = TLS1_3_VERSION;
+ }
+
/*
* The only protocol version we support which is valid in this extension in
* a ServerHello is TLSv1.3 therefore we shouldn't be getting anything else.
diff --git a/ssl/statem/extensions_srvr.c b/ssl/statem/extensions_srvr.c
index 0f2b22392b..6c1ce9813f 100644
--- a/ssl/statem/extensions_srvr.c
+++ b/ssl/statem/extensions_srvr.c
@@ -897,7 +897,8 @@ int tls_parse_ctos_cookie(SSL *s, PACKET *pkt, unsigned int context, X509 *x,
}
if (!WPACKET_put_bytes_u16(&hrrpkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(&hrrpkt)
- || !WPACKET_put_bytes_u16(&hrrpkt, s->version)
+ /* TODO(TLS1.3): Fix this before release */
+ || !WPACKET_put_bytes_u16(&hrrpkt, s->version_draft)
|| !WPACKET_close(&hrrpkt)) {
WPACKET_cleanup(&hrrpkt);
SSLfatal(s, SSL_AD_INTERNAL_ERROR, SSL_F_TLS_PARSE_CTOS_COOKIE,
@@ -1652,7 +1653,8 @@ EXT_RETURN tls_construct_stoc_supported_versions(SSL *s, WPACKET *pkt,
if (!WPACKET_put_bytes_u16(pkt, TLSEXT_TYPE_supported_versions)
|| !WPACKET_start_sub_packet_u16(pkt)
- || !WPACKET_put_bytes_u16(pkt, s->version)
+ /* TODO(TLS1.3): Update to remove the TLSv1.3 draft indicator */
+ || !WPACKET_put_bytes_u16(pkt, s->version_draft)
|| !WPACKET_close(pkt)) {
SSLfatal(s, SSL_AD_INTERNAL_ERROR,
SSL_F_TLS_CONSTRUCT_STOC_SUPPORTED_VERSIONS,
diff --git a/ssl/statem/statem_clnt.c b/ssl/statem/statem_clnt.c
index 8c658da899..08b84dfe32 100644
--- a/ssl/statem/statem_clnt.c
+++ b/ssl/statem/statem_clnt.c
@@ -1631,6 +1631,7 @@ MSG_PROCESS_RETURN tls_process_server_hello(SSL *s, PACKET *pkt)
}
s->session->ssl_version = s->version;
+ s->session->ssl_version_draft = s->version_draft;
/*
* In TLSv1.2 and below we save the session id we were sent so we can
* resume it later. In TLSv1.3 the session id we were sent is just an
diff --git a/ssl/statem/statem_lib.c b/ssl/statem/statem_lib.c
index 508bb88767..ee927baf64 100644
--- a/ssl/statem/statem_lib.c
+++ b/ssl/statem/statem_lib.c
@@ -1753,6 +1753,8 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
unsigned int best_vers = 0;
const SSL_METHOD *best_method = NULL;
PACKET versionslist;
+ /* TODO(TLS1.3): Remove this before release */
+ unsigned int orig_candidate = 0;
suppversions->parsed = 1;
@@ -1774,6 +1776,23 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
return SSL_R_BAD_LEGACY_VERSION;
while (PACKET_get_net_2(&versionslist, &candidate_vers)) {
+ /* TODO(TLS1.3): Remove this before release */
+ if (candidate_vers == TLS1_3_VERSION
+ || candidate_vers == TLS1_3_VERSION_DRAFT
+ || candidate_vers == TLS1_3_VERSION_DRAFT_26
+ || candidate_vers == TLS1_3_VERSION_DRAFT_23) {
+ if (best_vers == TLS1_3_VERSION
+ && (orig_candidate > candidate_vers
+ || orig_candidate == TLS1_3_VERSION))
+ continue;
+ orig_candidate = candidate_vers;
+ candidate_vers = TLS1_3_VERSION;
+ }
+ /*
+ * TODO(TLS1.3): There is some discussion on the TLS list about
+ * whether to ignore versions <TLS1.2 in supported_versions. At the
+ * moment we honour them if present. To be reviewed later
+ */
if (version_cmp(s, candidate_vers, best_vers) <= 0)
continue;
if (ssl_version_supported(s, candidate_vers, &best_method))
@@ -1796,6 +1815,9 @@ int ssl_choose_server_version(SSL *s, CLIENTHELLO_MSG *hello, DOWNGRADE *dgrd)
}
check_for_downgrade(s, best_vers, dgrd);
s->version = best_vers;
+ /* TODO(TLS1.3): Remove this before release */
+ if (best_vers == TLS1_3_VERSION)
+ s->version_draft = orig_candidate;
s->method = best_method;
return 0;
}
diff --git a/ssl/statem/statem_srvr.c b/ssl/statem/statem_srvr.c
index 346b1e3989..0a747f39ce 100644
--- a/ssl/statem/statem_srvr.c
+++ b/ssl/statem/statem_srvr.c
@@ -1742,7 +1742,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,
@@ -1923,7 +1923,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,
@@ -1932,8 +1932,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);
}
@@ -2245,7 +2246,7 @@ WORK_STATE tls_post_process_client_hello(SSL *s, WORK_STATE wst)
/* In TLSv1.3 we selected the ciphersuite before resumption */
if (!SSL_IS_TLS13(s)) {
cipher =
- ssl3_choose_cipher(s, s->session->ciphers, SSL_get_ciphers(s));
+ ssl3_choose_cipher(s, s->session->ciphers, ssl_get_cipher_preferences(s));
if (cipher == NULL) {
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE,
diff --git a/ssl/t1_trce.c b/ssl/t1_trce.c
index be3039af38..99c4ddcb41 100644
--- a/ssl/t1_trce.c
+++ b/ssl/t1_trce.c
@@ -65,6 +65,11 @@ static const ssl_trace_tbl ssl_version_tbl[] = {
{TLS1_1_VERSION, "TLS 1.1"},
{TLS1_2_VERSION, "TLS 1.2"},
{TLS1_3_VERSION, "TLS 1.3"},
+ /* TODO(TLS1.3): Remove these lines before release */
+ {TLS1_3_VERSION_DRAFT_23, TLS1_3_VERSION_DRAFT_TXT_23},
+ {TLS1_3_VERSION_DRAFT_26, TLS1_3_VERSION_DRAFT_TXT_26},
+ {TLS1_3_VERSION_DRAFT_27, TLS1_3_VERSION_DRAFT_TXT_27},
+ {TLS1_3_VERSION_DRAFT, TLS1_3_VERSION_DRAFT_TXT},
{DTLS1_VERSION, "DTLS 1.0"},
{DTLS1_2_VERSION, "DTLS 1.2"},
{DTLS1_BAD_VER, "DTLS 1.0 (bad)"}
@@ -638,8 +643,19 @@ static int ssl_print_version(BIO *bio, int indent, const char *name,
if (*pmsglen < 2)
return 0;
vers = ((*pmsg)[0] << 8) | (*pmsg)[1];
- if (version != NULL)
- *version = vers;
+ if (version != NULL) {
+ /* TODO(TLS1.3): Remove the draft conditional here before release */
+ switch(vers) {
+ case TLS1_3_VERSION_DRAFT_23:
+ case TLS1_3_VERSION_DRAFT_26:
+ case TLS1_3_VERSION_DRAFT_27:
+ case TLS1_3_VERSION_DRAFT:
+ *version = TLS1_3_VERSION;
+ break;
+ default:
+ *version = vers;
+ }
+ }
BIO_indent(bio, indent, 80);
BIO_printf(bio, "%s=0x%x (%s)\n",
name, vers, ssl_trace_str(vers, ssl_version_tbl));
diff --git a/util/libssl.num b/util/libssl.num
index ccf73411a9..9c53af24a5 100644
--- a/util/libssl.num
+++ b/util/libssl.num
@@ -497,3 +497,5 @@ SSL_get_recv_max_early_data 497 1_1_1 EXIST::FUNCTION:
SSL_CTX_get_recv_max_early_data 498 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_recv_max_early_data 499 1_1_1 EXIST::FUNCTION:
SSL_CTX_set_post_handshake_auth 500 1_1_1 EXIST::FUNCTION:
+SSL_get_version_tls13 501 1_1_1 EXIST::FUNCTION:
+
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment