summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsing <jsing@openbsd.org>2020-09-13 16:49:05 +0000
committerjsing <jsing@openbsd.org>2020-09-13 16:49:05 +0000
commit61a9dc017c155caa6fe6323f54bc4d850457f395 (patch)
tree0b94bc45eae82ee9e316fc6ad41b4665a10b1a40
parentAdapt regress to IFS splitting correction (eval.c -r1.66) (diff)
downloadwireguard-openbsd-61a9dc017c155caa6fe6323f54bc4d850457f395.tar.xz
wireguard-openbsd-61a9dc017c155caa6fe6323f54bc4d850457f395.zip
Implement SSL_{CTX_,}set_ciphersuites().
OpenSSL added a separate API for configuring TLSv1.3 ciphersuites. Provide this API, while retaining the current behaviour of being able to configure TLSv1.3 via the existing interface. Note that this is not currently exposed in the headers/exported symbols. ok beck@ inoguchi@ tb@
-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);