summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoel Sing <jsing@cvs.openbsd.org>2019-02-04 16:18:16 +0000
committerJoel Sing <jsing@cvs.openbsd.org>2019-02-04 16:18:16 +0000
commit66dd949ade2bf91e71a63b26f5d4651f4aa86178 (patch)
tree1aafaea8c709b007f6b12bdd0d9bcaf29da3a08b
parentc3c1288d3618ba568ef3e32ee7a56e449a1c9388 (diff)
Implement parsing and processing of TLSv1.3 ServerHello messages.
ok tb@
-rw-r--r--lib/libssl/tls13_client.c179
-rw-r--r--lib/libssl/tls13_handshake.c10
-rw-r--r--lib/libssl/tls13_internal.h9
3 files changed, 187 insertions, 11 deletions
diff --git a/lib/libssl/tls13_client.c b/lib/libssl/tls13_client.c
index 1a2529be6af..4d34cf99437 100644
--- a/lib/libssl/tls13_client.c
+++ b/lib/libssl/tls13_client.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls13_client.c,v 1.1 2019/01/21 13:45:57 jsing Exp $ */
+/* $OpenBSD: tls13_client.c,v 1.2 2019/02/04 16:18:15 jsing Exp $ */
/*
* Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org>
*
@@ -22,6 +22,7 @@
#include "bytestring.h"
#include "ssl_tlsext.h"
+#include "tls13_handshake.h"
#include "tls13_internal.h"
int
@@ -137,3 +138,179 @@ tls13_client_hello_send(struct tls13_ctx *ctx)
return 1;
}
+
+/*
+ * HelloRetryRequest hash - RFC 8446 section 4.1.3.
+ */
+static const uint8_t tls13_hello_retry_request_hash[] = {
+ 0xcf, 0x21, 0xad, 0x74, 0xe5, 0x9a, 0x61, 0x11,
+ 0xbe, 0x1d, 0x8c, 0x02, 0x1e, 0x65, 0xb8, 0x91,
+ 0xc2, 0xa2, 0x11, 0x16, 0x7a, 0xbb, 0x8c, 0x5e,
+ 0x07, 0x9e, 0x09, 0xe2, 0xc8, 0xa8, 0x33, 0x9c,
+};
+
+static int
+tls13_server_hello_process(struct tls13_ctx *ctx, CBS *cbs)
+{
+ CBS server_random, session_id;
+ uint16_t cipher_suite, legacy_version;
+ uint8_t compression_method;
+ const SSL_CIPHER *cipher;
+ SSL *s = ctx->ssl;
+ int alert;
+
+ if (!CBS_get_u16(cbs, &legacy_version))
+ goto err;
+ if (!CBS_get_bytes(cbs, &server_random, SSL3_RANDOM_SIZE))
+ goto err;
+ if (!CBS_get_u8_length_prefixed(cbs, &session_id))
+ goto err;
+ if (!CBS_get_u16(cbs, &cipher_suite))
+ goto err;
+ if (!CBS_get_u8(cbs, &compression_method))
+ goto err;
+
+ if (!tlsext_client_parse(s, cbs, &alert, SSL_TLSEXT_MSG_SH))
+ goto err;
+
+ if (CBS_len(cbs) != 0)
+ goto err;
+
+ /*
+ * See if a supported versions extension was returned. If it was then
+ * the legacy version must be set to 0x0303 (RFC 8446 section 4.1.3).
+ * Otherwise, fallback to the legacy version, ensuring that it is both
+ * within range and not TLS 1.3 or greater (which must use the
+ * supported version extension.
+ */
+ if (S3I(s)->hs_tls13.server_version != 0) {
+ if (legacy_version != TLS1_2_VERSION) {
+ /* XXX - alert. */
+ goto err;
+ }
+ } else {
+ if (legacy_version < S3I(s)->hs_tls13.min_version ||
+ legacy_version > S3I(s)->hs_tls13.max_version ||
+ legacy_version > TLS1_2_VERSION) {
+ /* XXX - alert. */
+ goto err;
+ }
+ S3I(s)->hs_tls13.server_version = legacy_version;
+ }
+
+ /* XXX - session_id must match. */
+
+ /*
+ * Ensure that the cipher suite is one that we offered in the client
+ * hello and that it matches the TLS version selected.
+ */
+ cipher = ssl3_get_cipher_by_value(cipher_suite);
+ if (cipher == NULL ||
+ sk_SSL_CIPHER_find(ssl_get_ciphers_by_id(s), cipher) < 0) {
+ /* XXX - alert. */
+ goto err;
+ }
+ if (S3I(s)->hs_tls13.server_version == TLS1_3_VERSION &&
+ cipher->algorithm_ssl != SSL_TLSV1_3) {
+ /* XXX - alert. */
+ goto err;
+ }
+ /* XXX - move this to hs_tls13? */
+ S3I(s)->hs.new_cipher = cipher;
+
+ if (compression_method != 0) {
+ /* XXX - alert. */
+ goto err;
+ }
+
+ if (CBS_mem_equal(&server_random, tls13_hello_retry_request_hash,
+ sizeof(tls13_hello_retry_request_hash)))
+ ctx->handshake_stage.hs_type |= WITH_HRR;
+
+ return 1;
+
+ err:
+ return 0;
+}
+
+int
+tls13_server_hello_recv(struct tls13_ctx *ctx)
+{
+ struct tls13_secrets *secrets;
+ struct tls13_secret context;
+ unsigned char buf[EVP_MAX_MD_SIZE];
+ uint8_t *shared_key = NULL;
+ size_t hash_len;
+ SSL *s = ctx->ssl;
+ int ret = 0;
+ CBS cbs;
+
+ if (!tls13_handshake_msg_content(ctx->hs_msg, &cbs))
+ goto err;
+
+ if (!tls13_server_hello_process(ctx, &cbs))
+ goto err;
+
+ if (S3I(s)->hs_tls13.server_version < TLS1_3_VERSION) {
+ /* XXX - switch back to legacy client. */
+ }
+
+ if (ctx->handshake_stage.hs_type & WITH_HRR)
+ return 1;
+
+ /* XXX - handle other key share types. */
+ if (S3I(s)->hs_tls13.x25519_peer_public == NULL) {
+ /* XXX - alert. */
+ goto err;
+ }
+ if ((shared_key = malloc(X25519_KEY_LENGTH)) == NULL)
+ goto err;
+ if (!X25519(shared_key, S3I(s)->hs_tls13.x25519_private,
+ S3I(s)->hs_tls13.x25519_peer_public))
+ goto err;
+
+ s->session->cipher = S3I(s)->hs.new_cipher;
+ s->session->ssl_version = S3I(s)->hs_tls13.server_version;
+
+ if ((ctx->aead = tls13_cipher_aead(S3I(s)->hs.new_cipher)) == NULL)
+ goto err;
+ if ((ctx->hash = tls13_cipher_hash(S3I(s)->hs.new_cipher)) == NULL)
+ goto err;
+
+ if ((secrets = tls13_secrets_create(ctx->hash, 0)) == NULL)
+ goto err;
+ S3I(ctx->ssl)->hs_tls13.secrets = secrets;
+
+ /* XXX - pass in hash. */
+ if (!tls1_handshake_hash_init(s))
+ goto err;
+ if (!tls1_handshake_hash_value(s, buf, sizeof(buf), &hash_len))
+ goto err;
+ context.data = buf;
+ context.len = hash_len;
+
+ /* Early secrets. */
+ if (!tls13_derive_early_secrets(secrets, secrets->zeros.data,
+ secrets->zeros.len, &context))
+ goto err;
+
+ /* Handshake secrets. */
+ if (!tls13_derive_handshake_secrets(S3I(s)->hs_tls13.secrets,
+ shared_key, X25519_KEY_LENGTH, &context))
+ goto err;
+
+ tls13_record_layer_set_aead(ctx->rl, ctx->aead);
+ tls13_record_layer_set_hash(ctx->rl, ctx->hash);
+
+ if (!tls13_record_layer_set_traffic_keys(ctx->rl,
+ &secrets->server_handshake_traffic,
+ &secrets->client_handshake_traffic))
+ goto err;
+
+ ctx->handshake_stage.hs_type |= NEGOTIATED;
+ ret = 1;
+
+ err:
+ freezero(shared_key, X25519_KEY_LENGTH);
+ return ret;
+}
diff --git a/lib/libssl/tls13_handshake.c b/lib/libssl/tls13_handshake.c
index f9cb3e5b476..b3c08ef39c1 100644
--- a/lib/libssl/tls13_handshake.c
+++ b/lib/libssl/tls13_handshake.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls13_handshake.c,v 1.22 2019/01/23 23:29:56 tb Exp $ */
+/* $OpenBSD: tls13_handshake.c,v 1.23 2019/02/04 16:18:15 jsing Exp $ */
/*
* Copyright (c) 2018-2019 Theo Buehler <tb@openbsd.org>
* Copyright (c) 2019 Joel Sing <jsing@openbsd.org>
@@ -467,14 +467,6 @@ tls13_client_key_update_recv(struct tls13_ctx *ctx)
}
int
-tls13_server_hello_recv(struct tls13_ctx *ctx)
-{
- ctx->handshake_stage.hs_type |= NEGOTIATED;
-
- return 0;
-}
-
-int
tls13_server_hello_send(struct tls13_ctx *ctx)
{
ctx->handshake_stage.hs_type |= NEGOTIATED;
diff --git a/lib/libssl/tls13_internal.h b/lib/libssl/tls13_internal.h
index 2738c40c4c1..4b23e74ae14 100644
--- a/lib/libssl/tls13_internal.h
+++ b/lib/libssl/tls13_internal.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tls13_internal.h,v 1.15 2019/01/21 13:45:57 jsing Exp $ */
+/* $OpenBSD: tls13_internal.h,v 1.16 2019/02/04 16:18:15 jsing Exp $ */
/*
* Copyright (c) 2018 Bob Beck <beck@openbsd.org>
* Copyright (c) 2018 Theo Buehler <tb@openbsd.org>
@@ -21,6 +21,7 @@
#define HEADER_TLS13_INTERNAL_H
#include <openssl/evp.h>
+#include <openssl/ssl.h>
#include "bytestring.h"
@@ -151,6 +152,9 @@ struct tls13_ctx {
uint8_t mode;
struct tls13_handshake_stage handshake_stage;
+ const EVP_AEAD *aead;
+ const EVP_MD *hash;
+
struct tls13_record_layer *rl;
struct tls13_handshake_msg *hs_msg;
};
@@ -158,6 +162,9 @@ struct tls13_ctx {
struct tls13_ctx *tls13_ctx_new(int mode);
void tls13_ctx_free(struct tls13_ctx *ctx);
+const EVP_AEAD *tls13_cipher_aead(const SSL_CIPHER *cipher);
+const EVP_MD *tls13_cipher_hash(const SSL_CIPHER *cipher);
+
/*
* Legacy interfaces.
*/