diff options
author | Joel Sing <jsing@cvs.openbsd.org> | 2020-11-16 18:55:16 +0000 |
---|---|---|
committer | Joel Sing <jsing@cvs.openbsd.org> | 2020-11-16 18:55:16 +0000 |
commit | 62766ac86f234d498b68df5d7ea8affe6773dd2d (patch) | |
tree | f96fc8c1ecc856f3607ff37d541ef527443763d0 /lib | |
parent | 2ae9b8cb5f4c03f7565afea3d2909c3572b4746f (diff) |
Implement exporter for TLSv1.3.
This implements the key material exporter for TLSv1.3, as defined in
RFC8446 section 7.5.
Issue reported by nmathewson on github.
ok inoguchi@ tb@
Diffstat (limited to 'lib')
-rw-r--r-- | lib/libssl/ssl_lib.c | 15 | ||||
-rw-r--r-- | lib/libssl/tls13_internal.h | 16 | ||||
-rw-r--r-- | lib/libssl/tls13_key_schedule.c | 24 | ||||
-rw-r--r-- | lib/libssl/tls13_lib.c | 74 |
4 files changed, 121 insertions, 8 deletions
diff --git a/lib/libssl/ssl_lib.c b/lib/libssl/ssl_lib.c index d92ccd80291..58b9dae9102 100644 --- a/lib/libssl/ssl_lib.c +++ b/lib/libssl/ssl_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ssl_lib.c,v 1.237 2020/10/14 16:57:33 jsing Exp $ */ +/* $OpenBSD: ssl_lib.c,v 1.238 2020/11/16 18:55:15 jsing Exp $ */ /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) * All rights reserved. * @@ -1716,8 +1716,17 @@ SSL_export_keying_material(SSL *s, unsigned char *out, size_t olen, const char *label, size_t llen, const unsigned char *p, size_t plen, int use_context) { - return (tls1_export_keying_material(s, out, olen, - label, llen, p, plen, use_context)); + if (s->internal->tls13 != NULL && s->version == TLS1_3_VERSION) { + if (!use_context) { + p = NULL; + plen = 0; + } + return tls13_exporter(s->internal->tls13, label, llen, p, plen, + out, olen); + } + + return (tls1_export_keying_material(s, out, olen, label, llen, p, plen, + use_context)); } static unsigned long diff --git a/lib/libssl/tls13_internal.h b/lib/libssl/tls13_internal.h index 03a1a6b4b15..ea5f9a14739 100644 --- a/lib/libssl/tls13_internal.h +++ b/lib/libssl/tls13_internal.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_internal.h,v 1.86 2020/07/30 16:23:17 tb Exp $ */ +/* $OpenBSD: tls13_internal.h,v 1.87 2020/11/16 18:55:15 jsing Exp $ */ /* * Copyright (c) 2018 Bob Beck <beck@openbsd.org> * Copyright (c) 2018 Theo Buehler <tb@openbsd.org> @@ -148,6 +148,16 @@ void tls13_secrets_destroy(struct tls13_secrets *secrets); int tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, const struct tls13_secret *secret, const char *label, const struct tls13_secret *context); +int tls13_hkdf_expand_label_with_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, + const uint8_t *label, size_t label_len, const struct tls13_secret *context); + +int tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, + const struct tls13_secret *secret, const char *label, + const struct tls13_secret *context); +int tls13_derive_secret_with_label_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, + const uint8_t *label, size_t label_len, const struct tls13_secret *context); int tls13_derive_early_secrets(struct tls13_secrets *secrets, uint8_t *psk, size_t psk_len, const struct tls13_secret *context); @@ -412,6 +422,10 @@ int tls13_error_setx(struct tls13_error *error, int code, int subcode, tls13_error_setx(&(ctx)->error, (code), (subcode), __FILE__, __LINE__, \ (fmt), __VA_ARGS__) +int tls13_exporter(struct tls13_ctx *ctx, const uint8_t *label, size_t label_len, + const uint8_t *context_value, size_t context_value_len, uint8_t *out, + size_t out_len); + extern const uint8_t tls13_downgrade_12[8]; extern const uint8_t tls13_downgrade_11[8]; extern const uint8_t tls13_hello_retry_request_hash[32]; diff --git a/lib/libssl/tls13_key_schedule.c b/lib/libssl/tls13_key_schedule.c index 91f59e46f92..35180cfe5c4 100644 --- a/lib/libssl/tls13_key_schedule.c +++ b/lib/libssl/tls13_key_schedule.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_key_schedule.c,v 1.8 2019/11/17 21:01:08 beck Exp $ */ +/* $OpenBSD: tls13_key_schedule.c,v 1.9 2020/11/16 18:55:15 jsing Exp $ */ /* Copyright (c) 2018, Bob Beck <beck@openbsd.org> * * Permission to use, copy, modify, and/or distribute this software for any @@ -174,6 +174,15 @@ tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, const struct tls13_secret *secret, const char *label, const struct tls13_secret *context) { + return tls13_hkdf_expand_label_with_length(out, digest, secret, label, + strlen(label), context); +} + +int +tls13_hkdf_expand_label_with_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, + const uint8_t *label, size_t label_len, const struct tls13_secret *context) +{ const char tls13_plabel[] = "tls13 "; uint8_t *hkdf_label; size_t hkdf_label_len; @@ -188,7 +197,7 @@ tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, goto err; if (!CBB_add_bytes(&child, tls13_plabel, strlen(tls13_plabel))) goto err; - if (!CBB_add_bytes(&child, label, strlen(label))) + if (!CBB_add_bytes(&child, label, label_len)) goto err; if (!CBB_add_u8_length_prefixed(&cbb, &child)) goto err; @@ -207,7 +216,7 @@ tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, return(0); } -static int +int tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, const struct tls13_secret *secret, const char *label, const struct tls13_secret *context) @@ -216,6 +225,15 @@ tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, } int +tls13_derive_secret_with_label_length(struct tls13_secret *out, + const EVP_MD *digest, const struct tls13_secret *secret, const uint8_t *label, + size_t label_len, const struct tls13_secret *context) +{ + return tls13_hkdf_expand_label_with_length(out, digest, secret, label, + label_len, context); +} + +int tls13_derive_early_secrets(struct tls13_secrets *secrets, uint8_t *psk, size_t psk_len, const struct tls13_secret *context) { diff --git a/lib/libssl/tls13_lib.c b/lib/libssl/tls13_lib.c index 590426ad8ac..6b6ddce4d65 100644 --- a/lib/libssl/tls13_lib.c +++ b/lib/libssl/tls13_lib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tls13_lib.c,v 1.54 2020/09/11 15:03:36 jsing Exp $ */ +/* $OpenBSD: tls13_lib.c,v 1.55 2020/11/16 18:55:15 jsing Exp $ */ /* * Copyright (c) 2018, 2019 Joel Sing <jsing@openbsd.org> * Copyright (c) 2019 Bob Beck <beck@openbsd.org> @@ -579,3 +579,75 @@ tls13_clienthello_hash_validate(struct tls13_ctx *ctx) return 1; } +int +tls13_exporter(struct tls13_ctx *ctx, const uint8_t *label, size_t label_len, + const uint8_t *context_value, size_t context_value_len, uint8_t *out, + size_t out_len) +{ + struct tls13_secret context, export_out, export_secret; + struct tls13_secrets *secrets = ctx->hs->secrets; + EVP_MD_CTX *md_ctx = NULL; + unsigned int md_out_len; + int md_len; + int ret = 0; + + /* + * RFC 8446 Section 7.5. + */ + + memset(&context, 0, sizeof(context)); + memset(&export_secret, 0, sizeof(export_secret)); + + export_out.data = out; + export_out.len = out_len; + + if (!ctx->handshake_completed) + return 0; + + md_len = EVP_MD_size(secrets->digest); + if (md_len <= 0 || md_len > EVP_MAX_MD_SIZE) + goto err; + + if ((export_secret.data = calloc(1, md_len)) == NULL) + goto err; + export_secret.len = md_len; + + if ((context.data = calloc(1, md_len)) == NULL) + goto err; + context.len = md_len; + + /* In TLSv1.3 no context is equivalent to an empty context. */ + if (context_value == NULL) { + context_value = ""; + context_value_len = 0; + } + + if ((md_ctx = EVP_MD_CTX_new()) == NULL) + goto err; + if (!EVP_DigestInit_ex(md_ctx, secrets->digest, NULL)) + goto err; + if (!EVP_DigestUpdate(md_ctx, context_value, context_value_len)) + goto err; + if (!EVP_DigestFinal_ex(md_ctx, context.data, &md_out_len)) + goto err; + if (md_len != md_out_len) + goto err; + + if (!tls13_derive_secret_with_label_length(&export_secret, + secrets->digest, &secrets->exporter_master, label, label_len, + &secrets->empty_hash)) + goto err; + + if (!tls13_hkdf_expand_label(&export_out, secrets->digest, + &export_secret, "exporter", &context)) + goto err; + + ret = 1; + + err: + EVP_MD_CTX_free(md_ctx); + freezero(context.data, context.len); + freezero(export_secret.data, export_secret.len); + + return ret; +} |