diff options
author | Bob Beck <beck@cvs.openbsd.org> | 2019-01-18 12:09:53 +0000 |
---|---|---|
committer | Bob Beck <beck@cvs.openbsd.org> | 2019-01-18 12:09:53 +0000 |
commit | cde2b9e99417bb7f1a50bef0e39ca75000de6eb5 (patch) | |
tree | 14dd3d7f12039cb92b6deb1243cac2ecb07cc56e /lib/libssl | |
parent | 3cb87eb23a23eed2a108f30cbba95953415fe808 (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.c | 7 | ||||
-rw-r--r-- | lib/libssl/ssl_locl.h | 20 | ||||
-rw-r--r-- | lib/libssl/ssl_tlsext.c | 223 | ||||
-rw-r--r-- | lib/libssl/ssl_tlsext.h | 16 |
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); |