summaryrefslogtreecommitdiff
path: root/lib/libssl
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2019-01-18 12:09:53 +0000
committerBob Beck <beck@cvs.openbsd.org>2019-01-18 12:09:53 +0000
commitcde2b9e99417bb7f1a50bef0e39ca75000de6eb5 (patch)
tree14dd3d7f12039cb92b6deb1243cac2ecb07cc56e /lib/libssl
parent3cb87eb23a23eed2a108f30cbba95953415fe808 (diff)
Add client side of supported versions and keyshare extensions with basic regress
ok jsing@
Diffstat (limited to 'lib/libssl')
-rw-r--r--lib/libssl/s3_lib.c7
-rw-r--r--lib/libssl/ssl_locl.h20
-rw-r--r--lib/libssl/ssl_tlsext.c223
-rw-r--r--lib/libssl/ssl_tlsext.h16
4 files changed, 262 insertions, 4 deletions
diff --git a/lib/libssl/s3_lib.c b/lib/libssl/s3_lib.c
index 091713d12a4..0761c5b5ce7 100644
--- a/lib/libssl/s3_lib.c
+++ b/lib/libssl/s3_lib.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: s3_lib.c,v 1.176 2018/11/08 22:28:52 jsing Exp $ */
+/* $OpenBSD: s3_lib.c,v 1.177 2019/01/18 12:09:52 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -1627,6 +1627,11 @@ ssl3_clear(SSL *s)
s->internal->packet_length = 0;
s->version = TLS1_VERSION;
+
+ tls13_secrets_destroy(S3I(s)->hs_tls13.secrets);
+ freezero(S3I(s)->hs_tls13.x25519_private, X25519_KEY_LENGTH);
+ freezero(S3I(s)->hs_tls13.x25519_public, X25519_KEY_LENGTH);
+ freezero(S3I(s)->hs_tls13.x25519_peer_public, X25519_KEY_LENGTH);
}
static long
diff --git a/lib/libssl/ssl_locl.h b/lib/libssl/ssl_locl.h
index 94bb76eca32..1653b2ab961 100644
--- a/lib/libssl/ssl_locl.h
+++ b/lib/libssl/ssl_locl.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_locl.h,v 1.225 2018/11/21 15:13:29 jsing Exp $ */
+/* $OpenBSD: ssl_locl.h,v 1.226 2019/01/18 12:09:52 beck Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
@@ -162,6 +162,7 @@
#include "bytestring.h"
#include "ssl_sigalgs.h"
+#include "tls13_internal.h"
__BEGIN_HIDDEN_DECLS
@@ -430,6 +431,22 @@ typedef struct ssl_handshake_st {
unsigned char *key_block;
} SSL_HANDSHAKE;
+typedef struct ssl_handshake_tls13_st {
+ uint16_t min_version;
+ uint16_t max_version;
+ uint16_t version;
+
+ /* Version proposed by peer server. */
+ uint16_t server_version;
+
+ /* X25519 key share. */
+ uint8_t *x25519_public;
+ uint8_t *x25519_private;
+ uint8_t *x25519_peer_public;
+
+ struct tls13_secrets *secrets;
+} SSL_HANDSHAKE_TLS13;
+
typedef struct ssl_ctx_internal_st {
uint16_t min_version;
uint16_t max_version;
@@ -803,6 +820,7 @@ typedef struct ssl3_state_internal_st {
int in_read_app_data;
SSL_HANDSHAKE hs;
+ SSL_HANDSHAKE_TLS13 hs_tls13;
struct {
int new_mac_secret_size;
diff --git a/lib/libssl/ssl_tlsext.c b/lib/libssl/ssl_tlsext.c
index da34a79f7d7..91b3b7d958e 100644
--- a/lib/libssl/ssl_tlsext.c
+++ b/lib/libssl/ssl_tlsext.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_tlsext.c,v 1.28 2019/01/18 03:39:27 beck Exp $ */
+/* $OpenBSD: ssl_tlsext.c,v 1.29 2019/01/18 12:09:52 beck Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -16,6 +16,7 @@
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <openssl/curve25519.h>
#include <openssl/ocsp.h>
#include "ssl_locl.h"
@@ -1193,6 +1194,196 @@ tlsext_srtp_client_parse(SSL *s, CBS *cbs, int *alert)
#endif /* OPENSSL_NO_SRTP */
+/*
+ * TLSv1.3 Key Share - RFC 8446 section 4.2.8.
+ */
+int
+tlsext_keyshare_client_needs(SSL *s)
+{
+ /* XXX once this gets initialized when we get tls13_client.c */
+ if (S3I(s)->hs_tls13.max_version == 0)
+ return 0;
+ return (!SSL_IS_DTLS(s) && S3I(s)->hs_tls13.max_version >=
+ TLS1_3_VERSION);
+}
+
+int
+tlsext_keyshare_client_build(SSL *s, CBB *cbb)
+{
+ uint8_t *public_key = NULL, *private_key = NULL;
+ CBB client_shares, key_exchange;
+
+ /* Generate and provide key shares. */
+ if (!CBB_add_u16_length_prefixed(cbb, &client_shares))
+ return 0;
+
+ /* XXX - other groups. */
+
+ /* Generate X25519 key pair. */
+ if ((public_key = malloc(X25519_KEY_LENGTH)) == NULL)
+ goto err;
+ if ((private_key = malloc(X25519_KEY_LENGTH)) == NULL)
+ goto err;
+ X25519_keypair(public_key, private_key);
+
+ /* Add the group and serialize the public key. */
+ if (!CBB_add_u16(&client_shares, tls1_ec_nid2curve_id(NID_X25519)))
+ goto err;
+ if (!CBB_add_u16_length_prefixed(&client_shares, &key_exchange))
+ goto err;
+ if (!CBB_add_bytes(&key_exchange, public_key, X25519_KEY_LENGTH))
+ goto err;
+
+ if (!CBB_flush(cbb))
+ goto err;
+
+ S3I(s)->hs_tls13.x25519_public = public_key;
+ S3I(s)->hs_tls13.x25519_private = private_key;
+
+ return 1;
+
+err:
+ freezero(public_key, X25519_KEY_LENGTH);
+ freezero(private_key, X25519_KEY_LENGTH);
+
+ return 0;
+}
+
+int
+tlsext_keyshare_server_parse(SSL *s, CBS *cbs, int *alert)
+{
+ /* XXX we accept this but currently ignore it */
+ if (!CBS_skip(cbs, CBS_len(cbs))) {
+ *alert = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+tlsext_keyshare_server_needs(SSL *s)
+{
+ return (!SSL_IS_DTLS(s) && s->version >= TLS1_3_VERSION);
+}
+
+int
+tlsext_keyshare_server_build(SSL *s, CBB *cbb)
+{
+ return 0;
+}
+
+int
+tlsext_keyshare_client_parse(SSL *s, CBS *cbs, int *alert)
+{
+ CBS key_exchange;
+ uint16_t group;
+ size_t out_len;
+
+ /* Unpack server share. */
+ if (!CBS_get_u16(cbs, &group))
+ goto err;
+
+ /* Handle other groups and verify that they're valid. */
+ if (group != tls1_ec_nid2curve_id(NID_X25519))
+ goto err;
+
+ if (!CBS_get_u16_length_prefixed(cbs, &key_exchange))
+ goto err;
+ if (CBS_len(&key_exchange) != X25519_KEY_LENGTH)
+ goto err;
+ if (!CBS_stow(&key_exchange, &S3I(s)->hs_tls13.x25519_peer_public,
+ &out_len))
+ goto err;
+
+ return 1;
+
+ err:
+ *alert = SSL_AD_DECODE_ERROR;
+ return 0;
+}
+
+/*
+ * Supported Versions - RFC 8446 section 4.2.1.
+ */
+int
+tlsext_versions_client_needs(SSL *s)
+{
+ /* XXX once this gets initialized when we get tls13_client.c */
+ if (S3I(s)->hs_tls13.max_version == 0)
+ return 0;
+ return (!SSL_IS_DTLS(s) && S3I(s)->hs_tls13.max_version >=
+ TLS1_3_VERSION);
+}
+
+int
+tlsext_versions_client_build(SSL *s, CBB *cbb)
+{
+ uint16_t version;
+ CBB versions;
+ uint16_t max, min;
+
+ max = S3I(s)->hs_tls13.max_version;
+ min = S3I(s)->hs_tls13.min_version;
+
+ if (min < TLS1_VERSION)
+ return 0;
+
+ if (!CBB_add_u8_length_prefixed(cbb, &versions))
+ return 0;
+
+ /* XXX - fix, but contiguous for now... */
+ for (version = max; version >= min; version--) {
+ if (!CBB_add_u16(&versions, version))
+ return 0;
+ }
+
+ if (!CBB_flush(cbb))
+ return 0;
+
+ return 1;
+}
+
+int
+tlsext_versions_server_parse(SSL *s, CBS *cbs, int *alert)
+{
+ /* XXX we accept this but currently ignore it */
+ if (!CBS_skip(cbs, CBS_len(cbs))) {
+ *alert = TLS1_AD_INTERNAL_ERROR;
+ return 0;
+ }
+
+ return 1;
+}
+
+int
+tlsext_versions_server_needs(SSL *s)
+{
+ return (!SSL_IS_DTLS(s) && s->version >= TLS1_3_VERSION);
+}
+
+int
+tlsext_versions_server_build(SSL *s, CBB *cbb)
+{
+ return 0;
+}
+
+int
+tlsext_versions_client_parse(SSL *s, CBS *cbs, int *alert)
+{
+ uint16_t selected_version;
+
+ if (!CBS_get_u16(cbs, &selected_version)) {
+ *alert = SSL_AD_DECODE_ERROR;
+ return 0;
+ }
+
+ /* XXX test between min and max once initialization code goes in */
+ S3I(s)->hs_tls13.server_version = selected_version;
+
+ return 1;
+}
+
struct tls_extension_funcs {
int (*needs)(SSL *s);
int (*build)(SSL *s, CBB *cbb);
@@ -1208,6 +1399,36 @@ struct tls_extension {
static struct tls_extension tls_extensions[] = {
{
+ .type = TLSEXT_TYPE_supported_versions,
+ .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH |
+ SSL_TLSEXT_MSG_HRR,
+ .client = {
+ .needs = tlsext_versions_client_needs,
+ .build = tlsext_versions_client_build,
+ .parse = tlsext_versions_server_parse,
+ },
+ .server = {
+ .needs = tlsext_versions_server_needs,
+ .build = tlsext_versions_server_build,
+ .parse = tlsext_versions_client_parse,
+ },
+ },
+ {
+ .type = TLSEXT_TYPE_key_share,
+ .messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_SH |
+ SSL_TLSEXT_MSG_HRR,
+ .client = {
+ .needs = tlsext_keyshare_client_needs,
+ .build = tlsext_keyshare_client_build,
+ .parse = tlsext_keyshare_server_parse,
+ },
+ .server = {
+ .needs = tlsext_keyshare_server_needs,
+ .build = tlsext_keyshare_server_build,
+ .parse = tlsext_keyshare_client_parse,
+ },
+ },
+ {
.type = TLSEXT_TYPE_server_name,
.messages = SSL_TLSEXT_MSG_CH | SSL_TLSEXT_MSG_EE,
.client = {
diff --git a/lib/libssl/ssl_tlsext.h b/lib/libssl/ssl_tlsext.h
index e5c1628c985..8f5aaa89dcf 100644
--- a/lib/libssl/ssl_tlsext.h
+++ b/lib/libssl/ssl_tlsext.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ssl_tlsext.h,v 1.15 2019/01/18 00:54:42 jsing Exp $ */
+/* $OpenBSD: ssl_tlsext.h,v 1.16 2019/01/18 12:09:52 beck Exp $ */
/*
* Copyright (c) 2016, 2017 Joel Sing <jsing@openbsd.org>
* Copyright (c) 2017 Doug Hogan <doug@openbsd.org>
@@ -86,6 +86,20 @@ int tlsext_sessionticket_server_needs(SSL *s);
int tlsext_sessionticket_server_build(SSL *s, CBB *cbb);
int tlsext_sessionticket_server_parse(SSL *s, CBS *cbs, int *alert);
+int tlsext_versions_client_needs(SSL *s);
+int tlsext_versions_client_build(SSL *s, CBB *cbb);
+int tlsext_versions_client_parse(SSL *s, CBS *cbs, int *alert);
+int tlsext_versions_server_needs(SSL *s);
+int tlsext_versions_server_build(SSL *s, CBB *cbb);
+int tlsext_versions_server_parse(SSL *s, CBS *cbs, int *alert);
+
+int tlsext_keyshare_client_needs(SSL *s);
+int tlsext_keyshare_client_build(SSL *s, CBB *cbb);
+int tlsext_keyshare_client_parse(SSL *s, CBS *cbs, int *alert);
+int tlsext_keyshare_server_needs(SSL *s);
+int tlsext_keyshare_server_build(SSL *s, CBB *cbb);
+int tlsext_keyshare_server_parse(SSL *s, CBS *cbs, int *alert);
+
#ifndef OPENSSL_NO_SRTP
int tlsext_srtp_client_needs(SSL *s);
int tlsext_srtp_client_build(SSL *s, CBB *cbb);