summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/libssl/ssl.h8
-rw-r--r--lib/libssl/ssl_ciph.c17
-rw-r--r--lib/libssl/ssl_ciphers.c129
-rw-r--r--lib/libssl/ssl_lib.c57
-rw-r--r--lib/libssl/ssl_locl.h13
5 files changed, 211 insertions, 13 deletions
diff --git a/lib/libssl/ssl.h b/lib/libssl/ssl.h
index 4370c84cd76..eb288699b1c 100644
--- a/lib/libssl/ssl.h
+++ b/lib/libssl/ssl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl.h,v 1.171 2020/03/16 15:25:13 tb Exp $ */
+/* $OpenBSD: ssl.h,v 1.172 2020/09/13 16:49:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -1275,6 +1275,9 @@ void BIO_ssl_shutdown(BIO *ssl_bio);
STACK_OF(SSL_CIPHER) *SSL_CTX_get_ciphers(const SSL_CTX *ctx);
int SSL_CTX_set_cipher_list(SSL_CTX *, const char *str);
+#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL)
+int SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str);
+#endif
SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth);
void SSL_CTX_free(SSL_CTX *);
int SSL_CTX_up_ref(SSL_CTX *ctx);
@@ -1316,6 +1319,9 @@ void SSL_set_bio(SSL *s, BIO *rbio, BIO *wbio);
BIO * SSL_get_rbio(const SSL *s);
BIO * SSL_get_wbio(const SSL *s);
int SSL_set_cipher_list(SSL *s, const char *str);
+#if defined(LIBRESSL_HAS_TLS1_3) || defined(LIBRESSL_INTERNAL)
+int SSL_set_ciphersuites(SSL *s, const char *str);
+#endif
void SSL_set_read_ahead(SSL *s, int yes);
int SSL_get_verify_mode(const SSL *s);
int SSL_get_verify_depth(const SSL *s);
diff --git a/lib/libssl/ssl_ciph.c b/lib/libssl/ssl_ciph.c
index 4afbcf98963..fd576cee7b1 100644
--- a/lib/libssl/ssl_ciph.c
+++ b/lib/libssl/ssl_ciph.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_ciph.c,v 1.118 2020/09/11 17:36:27 jsing Exp $ */
+/* $OpenBSD: ssl_ciph.c,v 1.119 2020/09/13 16:49:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -1184,6 +1184,7 @@ ssl_aes_is_accelerated(void)
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_tls13,
const char *rule_str)
{
int ok, num_of_ciphers, num_of_alias_max, num_of_group_aliases;
@@ -1192,8 +1193,10 @@ ssl_create_cipher_list(const SSL_METHOD *ssl_method,
const char *rule_p;
CIPHER_ORDER *co_list = NULL, *head = NULL, *tail = NULL, *curr;
const SSL_CIPHER **ca_list = NULL;
+ const SSL_CIPHER *cipher;
int tls13_seen = 0;
int any_active;
+ int i;
/*
* Return with error if nothing to do.
@@ -1335,11 +1338,21 @@ ssl_create_cipher_list(const SSL_METHOD *ssl_method,
return (NULL);
}
+ /* Prefer TLSv1.3 cipher suites. */
+ if (cipher_list_tls13 != NULL) {
+ for (i = 0; i < sk_SSL_CIPHER_num(cipher_list_tls13); i++) {
+ cipher = sk_SSL_CIPHER_value(cipher_list_tls13, i);
+ sk_SSL_CIPHER_push(cipherstack, cipher);
+ }
+ tls13_seen = 1;
+ }
+
/*
* The cipher selection for the list is done. The ciphers are added
* to the resulting precedence to the STACK_OF(SSL_CIPHER).
*
- * If the rule string did not contain any references to TLSv1.3,
+ * If the rule string did not contain any references to TLSv1.3 and
+ * TLSv1.3 cipher suites have not been configured separately,
* include inactive TLSv1.3 cipher suites. This avoids attempts to
* use TLSv1.3 with an older rule string that does not include
* TLSv1.3 cipher suites. If the rule string resulted in no active
diff --git a/lib/libssl/ssl_ciphers.c b/lib/libssl/ssl_ciphers.c
index 478238bd103..d84e4c6154c 100644
--- a/lib/libssl/ssl_ciphers.c
+++ b/lib/libssl/ssl_ciphers.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: ssl_ciphers.c,v 1.6 2020/09/11 17:36:27 jsing Exp $ */
+/* $OpenBSD: ssl_ciphers.c,v 1.7 2020/09/13 16:49:05 jsing Exp $ */
/*
* Copyright (c) 2015-2017 Doug Hogan <doug@openbsd.org>
- * Copyright (c) 2015-2018 Joel Sing <jsing@openbsd.org>
+ * Copyright (c) 2015-2018, 2020 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2019 Theo Buehler <tb@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
@@ -171,3 +171,128 @@ ssl_bytes_to_cipher_list(SSL *s, CBS *cbs)
return (NULL);
}
+
+struct ssl_tls13_ciphersuite {
+ const char *name;
+ const char *alias;
+ unsigned long cid;
+};
+
+static const struct ssl_tls13_ciphersuite ssl_tls13_ciphersuites[] = {
+ {
+ .name = TLS1_3_TXT_AES_128_GCM_SHA256,
+ .alias = "TLS_AES_128_GCM_SHA256",
+ .cid = TLS1_3_CK_AES_128_GCM_SHA256,
+ },
+ {
+ .name = TLS1_3_TXT_AES_256_GCM_SHA384,
+ .alias = "TLS_AES_256_GCM_SHA384",
+ .cid = TLS1_3_CK_AES_256_GCM_SHA384,
+ },
+ {
+ .name = TLS1_3_TXT_CHACHA20_POLY1305_SHA256,
+ .alias = "TLS_CHACHA20_POLY1305_SHA256",
+ .cid = TLS1_3_CK_CHACHA20_POLY1305_SHA256,
+ },
+ {
+ .name = TLS1_3_TXT_AES_128_CCM_SHA256,
+ .alias = "TLS_AES_128_CCM_SHA256",
+ .cid = TLS1_3_CK_AES_128_CCM_SHA256,
+ },
+ {
+ .name = TLS1_3_TXT_AES_128_CCM_8_SHA256,
+ .alias = "TLS_AES_128_CCM_8_SHA256",
+ .cid = TLS1_3_CK_AES_128_CCM_8_SHA256,
+ },
+ {
+ .name = NULL,
+ },
+};
+
+int
+ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str)
+{
+ const struct ssl_tls13_ciphersuite *ciphersuite;
+ STACK_OF(SSL_CIPHER) *ciphers;
+ const SSL_CIPHER *cipher;
+ char *s = NULL;
+ char *p, *q;
+ int i;
+ int ret = 0;
+
+ sk_SSL_CIPHER_free(*out_ciphers);
+ *out_ciphers = NULL;
+
+ if ((ciphers = sk_SSL_CIPHER_new_null()) == NULL)
+ goto err;
+
+ /* An empty string is valid and means no ciphers. */
+ if (strcmp(str, "") == 0)
+ goto done;
+
+ if ((s = strdup(str)) == NULL)
+ goto err;
+
+ q = s;
+ while ((p = strsep(&q, ":")) != NULL) {
+ ciphersuite = &ssl_tls13_ciphersuites[0];
+ for (i = 0; ciphersuite->name != NULL; i++) {
+ ciphersuite = &ssl_tls13_ciphersuites[i];
+ if (strcmp(p, ciphersuite->name) == 0)
+ break;
+ if (strcmp(p, ciphersuite->alias) == 0)
+ break;
+ }
+ if (ciphersuite->name == NULL)
+ goto err;
+
+ /* We know about the cipher suite, but it is not supported. */
+ if ((cipher = ssl3_get_cipher_by_id(ciphersuite->cid)) == NULL)
+ continue;
+
+ if (!sk_SSL_CIPHER_push(ciphers, cipher))
+ goto err;
+ }
+
+ done:
+ *out_ciphers = ciphers;
+ ciphers = NULL;
+ ret = 1;
+
+ err:
+ sk_SSL_CIPHER_free(ciphers);
+ free(s);
+
+ return ret;
+}
+
+int
+ssl_merge_cipherlists(STACK_OF(SSL_CIPHER) *cipherlist,
+ STACK_OF(SSL_CIPHER) *cipherlist_tls13,
+ STACK_OF(SSL_CIPHER) **out_cipherlist)
+{
+ STACK_OF(SSL_CIPHER) *ciphers = NULL;
+ const SSL_CIPHER *cipher;
+ int i, ret = 0;
+
+ if ((ciphers = sk_SSL_CIPHER_dup(cipherlist_tls13)) == NULL)
+ goto err;
+ for (i = 0; i < sk_SSL_CIPHER_num(cipherlist); i++) {
+ cipher = sk_SSL_CIPHER_value(cipherlist, i);
+ if (cipher->algorithm_ssl == SSL_TLSV1_3)
+ continue;
+ if (!sk_SSL_CIPHER_push(ciphers, cipher))
+ goto err;
+ }
+
+ sk_SSL_CIPHER_free(*out_cipherlist);
+ *out_cipherlist = ciphers;
+ ciphers = NULL;
+
+ ret = 1;
+
+ err:
+ sk_SSL_CIPHER_free(ciphers);
+
+ return ret;
+}
diff --git a/lib/libssl/ssl_lib.c b/lib/libssl/ssl_lib.c
index 5bc759d483c..a194e5639a7 100644
--- a/lib/libssl/ssl_lib.c
+++ b/lib/libssl/ssl_lib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_lib.c,v 1.225 2020/09/11 17:36:27 jsing Exp $ */
+/* $OpenBSD: ssl_lib.c,v 1.226 2020/09/13 16:49:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -230,7 +230,7 @@ SSL_CTX_set_ssl_version(SSL_CTX *ctx, const SSL_METHOD *meth)
ctx->method = meth;
ciphers = ssl_create_cipher_list(ctx->method, &ctx->cipher_list,
- SSL_DEFAULT_CIPHER_LIST);
+ ctx->internal->cipher_list_tls13, SSL_DEFAULT_CIPHER_LIST);
if (ciphers == NULL || sk_SSL_CIPHER_num(ciphers) <= 0) {
SSLerrorx(SSL_R_SSL_LIBRARY_HAS_NO_CIPHERS);
return (0);
@@ -530,6 +530,7 @@ SSL_free(SSL *s)
BUF_MEM_free(s->internal->init_buf);
sk_SSL_CIPHER_free(s->cipher_list);
+ sk_SSL_CIPHER_free(s->internal->cipher_list_tls13);
/* Make the next call work :-) */
if (s->session != NULL) {
@@ -1353,7 +1354,8 @@ SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
* an error as far as ssl_create_cipher_list is concerned, and hence
* ctx->cipher_list has been updated.
*/
- ciphers = ssl_create_cipher_list(ctx->method, &ctx->cipher_list, str);
+ ciphers = ssl_create_cipher_list(ctx->method, &ctx->cipher_list,
+ ctx->internal->cipher_list_tls13, str);
if (ciphers == NULL) {
return (0);
} else if (sk_SSL_CIPHER_num(ciphers) == 0) {
@@ -1363,14 +1365,32 @@ SSL_CTX_set_cipher_list(SSL_CTX *ctx, const char *str)
return (1);
}
+int
+SSL_CTX_set_ciphersuites(SSL_CTX *ctx, const char *str)
+{
+ if (!ssl_parse_ciphersuites(&ctx->internal->cipher_list_tls13, str)) {
+ SSLerrorx(SSL_R_NO_CIPHER_MATCH);
+ return 0;
+ }
+ if (!ssl_merge_cipherlists(ctx->cipher_list,
+ ctx->internal->cipher_list_tls13, &ctx->cipher_list))
+ return 0;
+
+ return 1;
+}
+
/* Specify the ciphers to be used by the SSL. */
int
SSL_set_cipher_list(SSL *s, const char *str)
{
- STACK_OF(SSL_CIPHER) *ciphers;
+ STACK_OF(SSL_CIPHER) *ciphers, *ciphers_tls13;
+
+ if ((ciphers_tls13 = s->internal->cipher_list_tls13) == NULL)
+ ciphers_tls13 = s->ctx->internal->cipher_list_tls13;
/* See comment in SSL_CTX_set_cipher_list. */
- ciphers = ssl_create_cipher_list(s->ctx->method, &s->cipher_list, str);
+ ciphers = ssl_create_cipher_list(s->ctx->method, &s->cipher_list,
+ ciphers_tls13, str);
if (ciphers == NULL) {
return (0);
} else if (sk_SSL_CIPHER_num(ciphers) == 0) {
@@ -1380,6 +1400,25 @@ SSL_set_cipher_list(SSL *s, const char *str)
return (1);
}
+int
+SSL_set_ciphersuites(SSL *s, const char *str)
+{
+ STACK_OF(SSL_CIPHER) *ciphers;
+
+ if ((ciphers = s->cipher_list) == NULL)
+ ciphers = s->ctx->cipher_list;
+
+ if (!ssl_parse_ciphersuites(&s->internal->cipher_list_tls13, str)) {
+ SSLerrorx(SSL_R_NO_CIPHER_MATCH);
+ return (0);
+ }
+ if (!ssl_merge_cipherlists(ciphers, s->internal->cipher_list_tls13,
+ &s->cipher_list))
+ return 0;
+
+ return 1;
+}
+
char *
SSL_get_shared_ciphers(const SSL *s, char *buf, int len)
{
@@ -1758,7 +1797,7 @@ SSL_CTX_new(const SSL_METHOD *meth)
goto err;
ssl_create_cipher_list(ret->method, &ret->cipher_list,
- SSL_DEFAULT_CIPHER_LIST);
+ NULL, SSL_DEFAULT_CIPHER_LIST);
if (ret->cipher_list == NULL ||
sk_SSL_CIPHER_num(ret->cipher_list) <= 0) {
SSLerrorx(SSL_R_LIBRARY_HAS_NO_CIPHERS);
@@ -1855,6 +1894,7 @@ SSL_CTX_free(SSL_CTX *ctx)
X509_STORE_free(ctx->cert_store);
sk_SSL_CIPHER_free(ctx->cipher_list);
+ sk_SSL_CIPHER_free(ctx->internal->cipher_list_tls13);
ssl_cert_free(ctx->internal->cert);
sk_X509_NAME_pop_free(ctx->internal->client_CA, X509_NAME_free);
sk_X509_pop_free(ctx->extra_certs, X509_free);
@@ -2451,6 +2491,11 @@ SSL_dup(SSL *s)
sk_SSL_CIPHER_dup(s->cipher_list)) == NULL)
goto err;
}
+ if (s->internal->cipher_list_tls13 != NULL) {
+ if ((ret->internal->cipher_list_tls13 =
+ sk_SSL_CIPHER_dup(s->internal->cipher_list_tls13)) == NULL)
+ goto err;
+ }
/* Dup the client_CA list */
if (s->internal->client_CA != NULL) {
diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h
index df07ca68a67..540afee004f 100644
--- a/lib/libssl/ssl_locl.h
+++ b/lib/libssl/ssl_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_locl.h,v 1.290 2020/09/11 17:36:27 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.291 2020/09/13 16:49:05 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -599,6 +599,8 @@ typedef struct ssl_ctx_internal_st {
CRYPTO_EX_DATA ex_data;
+ STACK_OF(SSL_CIPHER) *cipher_list_tls13;
+
struct cert_st /* CERT */ *cert;
/* Default values used when no per-SSL value is defined follow */
@@ -743,6 +745,8 @@ typedef struct ssl_internal_st {
int hit; /* reusing a previous session */
+ STACK_OF(SSL_CIPHER) *cipher_list_tls13;
+
/* These are the ones being used, the ones in SSL_SESSION are
* the ones to be 'copied' into these ones */
int mac_flags;
@@ -1164,7 +1168,12 @@ SSL_CIPHER *OBJ_bsearch_ssl_cipher_id(SSL_CIPHER *key, SSL_CIPHER const *base,
int ssl_cipher_list_to_bytes(SSL *s, STACK_OF(SSL_CIPHER) *ciphers, CBB *cbb);
STACK_OF(SSL_CIPHER) *ssl_bytes_to_cipher_list(SSL *s, CBS *cbs);
STACK_OF(SSL_CIPHER) *ssl_create_cipher_list(const SSL_METHOD *meth,
- STACK_OF(SSL_CIPHER) **pref, const char *rule_str);
+ STACK_OF(SSL_CIPHER) **pref, STACK_OF(SSL_CIPHER) *tls13,
+ const char *rule_str);
+int ssl_parse_ciphersuites(STACK_OF(SSL_CIPHER) **out_ciphers, const char *str);
+int ssl_merge_cipherlists(STACK_OF(SSL_CIPHER) *cipherlist,
+ STACK_OF(SSL_CIPHER) *cipherlist_tls13,
+ STACK_OF(SSL_CIPHER) **out_cipherlist);
void ssl_update_cache(SSL *s, int mode);
int ssl_cipher_get_evp(const SSL_SESSION *s, const EVP_CIPHER **enc,
const EVP_MD **md, int *mac_pkey_type, int *mac_secret_size);