172c33676SMaxim Ag /* $OpenBSD: tls13_key_schedule.c,v 1.7 2018/11/13 01:25:13 beck Exp $ */ 272c33676SMaxim Ag /* Copyright (c) 2018, Bob Beck <beck@openbsd.org> 372c33676SMaxim Ag * 472c33676SMaxim Ag * Permission to use, copy, modify, and/or distribute this software for any 572c33676SMaxim Ag * purpose with or without fee is hereby granted, provided that the above 672c33676SMaxim Ag * copyright notice and this permission notice appear in all copies. 772c33676SMaxim Ag * 872c33676SMaxim Ag * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 972c33676SMaxim Ag * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1072c33676SMaxim Ag * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 1172c33676SMaxim Ag * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1272c33676SMaxim Ag * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 1372c33676SMaxim Ag * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 1472c33676SMaxim Ag * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1572c33676SMaxim Ag */ 1672c33676SMaxim Ag 1772c33676SMaxim Ag #include <string.h> 1872c33676SMaxim Ag #include <stdlib.h> 1972c33676SMaxim Ag 2072c33676SMaxim Ag #include <openssl/hkdf.h> 2172c33676SMaxim Ag 2272c33676SMaxim Ag #include "bytestring.h" 2372c33676SMaxim Ag #include "tls13_internal.h" 2472c33676SMaxim Ag 2572c33676SMaxim Ag void 2672c33676SMaxim Ag tls13_secrets_destroy(struct tls13_secrets *secrets) 2772c33676SMaxim Ag { 2872c33676SMaxim Ag if (secrets == NULL) 2972c33676SMaxim Ag return; 3072c33676SMaxim Ag 3172c33676SMaxim Ag /* you can never be too sure :) */ 3272c33676SMaxim Ag freezero(secrets->zeros.data, secrets->zeros.len); 3372c33676SMaxim Ag freezero(secrets->empty_hash.data, secrets->empty_hash.len); 3472c33676SMaxim Ag 3572c33676SMaxim Ag freezero(secrets->extracted_early.data, 3672c33676SMaxim Ag secrets->extracted_early.len); 3772c33676SMaxim Ag freezero(secrets->binder_key.data, 3872c33676SMaxim Ag secrets->binder_key.len); 3972c33676SMaxim Ag freezero(secrets->client_early_traffic.data, 4072c33676SMaxim Ag secrets->client_early_traffic.len); 4172c33676SMaxim Ag freezero(secrets->early_exporter_master.data, 4272c33676SMaxim Ag secrets->early_exporter_master.len); 4372c33676SMaxim Ag freezero(secrets->derived_early.data, 4472c33676SMaxim Ag secrets->derived_early.len); 4572c33676SMaxim Ag freezero(secrets->extracted_handshake.data, 4672c33676SMaxim Ag secrets->extracted_handshake.len); 4772c33676SMaxim Ag freezero(secrets->client_handshake_traffic.data, 4872c33676SMaxim Ag secrets->client_handshake_traffic.len); 4972c33676SMaxim Ag freezero(secrets->server_handshake_traffic.data, 5072c33676SMaxim Ag secrets->server_handshake_traffic.len); 5172c33676SMaxim Ag freezero(secrets->derived_handshake.data, 5272c33676SMaxim Ag secrets->derived_handshake.len); 5372c33676SMaxim Ag freezero(secrets->extracted_master.data, 5472c33676SMaxim Ag secrets->extracted_master.len); 5572c33676SMaxim Ag freezero(secrets->client_application_traffic.data, 5672c33676SMaxim Ag secrets->client_application_traffic.len); 5772c33676SMaxim Ag freezero(secrets->server_application_traffic.data, 5872c33676SMaxim Ag secrets->server_application_traffic.len); 5972c33676SMaxim Ag freezero(secrets->exporter_master.data, 6072c33676SMaxim Ag secrets->exporter_master.len); 6172c33676SMaxim Ag freezero(secrets->resumption_master.data, 6272c33676SMaxim Ag secrets->resumption_master.len); 6372c33676SMaxim Ag 6472c33676SMaxim Ag freezero(secrets, sizeof(struct tls13_secrets)); 6572c33676SMaxim Ag } 6672c33676SMaxim Ag 6772c33676SMaxim Ag /* 6872c33676SMaxim Ag * Allocate a set of secrets for a key schedule using 6972c33676SMaxim Ag * a size of hash_length from RFC 8446 section 7.1. 7072c33676SMaxim Ag */ 7172c33676SMaxim Ag struct tls13_secrets * 7272c33676SMaxim Ag tls13_secrets_create(const EVP_MD *digest, int resumption) 7372c33676SMaxim Ag { 7472c33676SMaxim Ag struct tls13_secrets *secrets = NULL; 7572c33676SMaxim Ag EVP_MD_CTX *mdctx = NULL; 7672c33676SMaxim Ag unsigned int mdlen; 7772c33676SMaxim Ag size_t hash_length; 7872c33676SMaxim Ag 7972c33676SMaxim Ag hash_length = EVP_MD_size(digest); 8072c33676SMaxim Ag 8172c33676SMaxim Ag if ((secrets = calloc(1, sizeof(struct tls13_secrets))) == NULL) 8272c33676SMaxim Ag goto err; 8372c33676SMaxim Ag 8472c33676SMaxim Ag if ((secrets->zeros.data = calloc(hash_length, sizeof(uint8_t))) == 8572c33676SMaxim Ag NULL) 8672c33676SMaxim Ag goto err; 8772c33676SMaxim Ag secrets->zeros.len = hash_length; 8872c33676SMaxim Ag 8972c33676SMaxim Ag if ((secrets->empty_hash.data = malloc(hash_length)) == NULL) 9072c33676SMaxim Ag goto err; 9172c33676SMaxim Ag secrets->empty_hash.len = hash_length; 9272c33676SMaxim Ag 9372c33676SMaxim Ag if ((secrets->extracted_early.data = malloc(hash_length)) == NULL) 9472c33676SMaxim Ag goto err; 9572c33676SMaxim Ag secrets->extracted_early.len = hash_length; 9672c33676SMaxim Ag if ((secrets->binder_key.data = malloc(hash_length)) == NULL) 9772c33676SMaxim Ag goto err; 9872c33676SMaxim Ag secrets->binder_key.len = hash_length; 9972c33676SMaxim Ag if ((secrets->client_early_traffic.data = malloc(hash_length)) == NULL) 10072c33676SMaxim Ag goto err; 10172c33676SMaxim Ag secrets->client_early_traffic.len = hash_length; 10272c33676SMaxim Ag if ((secrets->early_exporter_master.data = malloc(hash_length)) == 10372c33676SMaxim Ag NULL) 10472c33676SMaxim Ag goto err; 10572c33676SMaxim Ag secrets->early_exporter_master.len = hash_length; 10672c33676SMaxim Ag if ((secrets->derived_early.data = malloc(hash_length)) == NULL) 10772c33676SMaxim Ag goto err; 10872c33676SMaxim Ag secrets->derived_early.len = hash_length; 10972c33676SMaxim Ag if ((secrets->extracted_handshake.data = malloc(hash_length)) == NULL) 11072c33676SMaxim Ag goto err; 11172c33676SMaxim Ag secrets->extracted_handshake.len = hash_length; 11272c33676SMaxim Ag if ((secrets->client_handshake_traffic.data = malloc(hash_length)) 11372c33676SMaxim Ag == NULL) 11472c33676SMaxim Ag goto err; 11572c33676SMaxim Ag secrets->client_handshake_traffic.len = hash_length; 11672c33676SMaxim Ag if ((secrets->server_handshake_traffic.data = malloc(hash_length)) 11772c33676SMaxim Ag == NULL) 11872c33676SMaxim Ag goto err; 11972c33676SMaxim Ag secrets->server_handshake_traffic.len = hash_length; 12072c33676SMaxim Ag if ((secrets->derived_handshake.data = malloc(hash_length)) == NULL) 12172c33676SMaxim Ag goto err; 12272c33676SMaxim Ag secrets->derived_handshake.len = hash_length; 12372c33676SMaxim Ag if ((secrets->extracted_master.data = malloc(hash_length)) == NULL) 12472c33676SMaxim Ag goto err; 12572c33676SMaxim Ag secrets->extracted_master.len = hash_length; 12672c33676SMaxim Ag if ((secrets->client_application_traffic.data = malloc(hash_length)) == 12772c33676SMaxim Ag NULL) 12872c33676SMaxim Ag goto err; 12972c33676SMaxim Ag secrets->client_application_traffic.len = hash_length; 13072c33676SMaxim Ag if ((secrets->server_application_traffic.data = malloc(hash_length)) == 13172c33676SMaxim Ag NULL) 13272c33676SMaxim Ag goto err; 13372c33676SMaxim Ag secrets->server_application_traffic.len = hash_length; 13472c33676SMaxim Ag if ((secrets->exporter_master.data = malloc(hash_length)) == NULL) 13572c33676SMaxim Ag goto err; 13672c33676SMaxim Ag secrets->exporter_master.len = hash_length; 13772c33676SMaxim Ag if ((secrets->resumption_master.data = malloc(hash_length)) == NULL) 13872c33676SMaxim Ag goto err; 13972c33676SMaxim Ag secrets->resumption_master.len = hash_length; 14072c33676SMaxim Ag 14172c33676SMaxim Ag /* 14272c33676SMaxim Ag * Calculate the hash of a zero-length string - this is needed during 14372c33676SMaxim Ag * the "derived" step for key extraction. 14472c33676SMaxim Ag */ 14572c33676SMaxim Ag if ((mdctx = EVP_MD_CTX_new()) == NULL) 14672c33676SMaxim Ag goto err; 14772c33676SMaxim Ag if (!EVP_DigestInit_ex(mdctx, digest, NULL)) 14872c33676SMaxim Ag goto err; 14972c33676SMaxim Ag if (!EVP_DigestUpdate(mdctx, secrets->zeros.data, 0)) 15072c33676SMaxim Ag goto err; 15172c33676SMaxim Ag if (!EVP_DigestFinal_ex(mdctx, secrets->empty_hash.data, &mdlen)) 15272c33676SMaxim Ag goto err; 15372c33676SMaxim Ag EVP_MD_CTX_free(mdctx); 15472c33676SMaxim Ag mdctx = NULL; 15572c33676SMaxim Ag 15672c33676SMaxim Ag if (secrets->empty_hash.len != mdlen) 15772c33676SMaxim Ag goto err; 15872c33676SMaxim Ag 15972c33676SMaxim Ag secrets->digest = digest; 16072c33676SMaxim Ag secrets->resumption = resumption; 16172c33676SMaxim Ag secrets->init_done = 1; 16272c33676SMaxim Ag 16372c33676SMaxim Ag return secrets; 16472c33676SMaxim Ag 16572c33676SMaxim Ag err: 16672c33676SMaxim Ag tls13_secrets_destroy(secrets); 16772c33676SMaxim Ag EVP_MD_CTX_free(mdctx); 16872c33676SMaxim Ag 16972c33676SMaxim Ag return NULL; 17072c33676SMaxim Ag } 17172c33676SMaxim Ag 17272c33676SMaxim Ag int 17372c33676SMaxim Ag tls13_hkdf_expand_label(struct tls13_secret *out, const EVP_MD *digest, 17472c33676SMaxim Ag const struct tls13_secret *secret, const char *label, 17572c33676SMaxim Ag const struct tls13_secret *context) 17672c33676SMaxim Ag { 17772c33676SMaxim Ag const char tls13_plabel[] = "tls13 "; 17872c33676SMaxim Ag uint8_t *hkdf_label; 17972c33676SMaxim Ag size_t hkdf_label_len; 18072c33676SMaxim Ag CBB cbb, child; 18172c33676SMaxim Ag int ret; 18272c33676SMaxim Ag 18372c33676SMaxim Ag if (!CBB_init(&cbb, 256)) 18472c33676SMaxim Ag return 0; 18572c33676SMaxim Ag if (!CBB_add_u16(&cbb, out->len)) 18672c33676SMaxim Ag goto err; 18772c33676SMaxim Ag if (!CBB_add_u8_length_prefixed(&cbb, &child)) 18872c33676SMaxim Ag goto err; 18972c33676SMaxim Ag if (!CBB_add_bytes(&child, tls13_plabel, strlen(tls13_plabel))) 19072c33676SMaxim Ag goto err; 19172c33676SMaxim Ag if (!CBB_add_bytes(&child, label, strlen(label))) 19272c33676SMaxim Ag goto err; 19372c33676SMaxim Ag if (!CBB_add_u8_length_prefixed(&cbb, &child)) 19472c33676SMaxim Ag goto err; 19572c33676SMaxim Ag if (!CBB_add_bytes(&child, context->data, context->len)) 19672c33676SMaxim Ag goto err; 19772c33676SMaxim Ag if (!CBB_finish(&cbb, &hkdf_label, &hkdf_label_len)) 19872c33676SMaxim Ag goto err; 19972c33676SMaxim Ag 20072c33676SMaxim Ag ret = HKDF_expand(out->data, out->len, digest, secret->data, 20172c33676SMaxim Ag secret->len, hkdf_label, hkdf_label_len); 20272c33676SMaxim Ag 20372c33676SMaxim Ag free(hkdf_label); 20472c33676SMaxim Ag return(ret); 20572c33676SMaxim Ag err: 20672c33676SMaxim Ag CBB_cleanup(&cbb); 20772c33676SMaxim Ag return(0); 20872c33676SMaxim Ag } 20972c33676SMaxim Ag 21072c33676SMaxim Ag static int 21172c33676SMaxim Ag tls13_derive_secret(struct tls13_secret *out, const EVP_MD *digest, 21272c33676SMaxim Ag const struct tls13_secret *secret, const char *label, 21372c33676SMaxim Ag const struct tls13_secret *context) 21472c33676SMaxim Ag { 21572c33676SMaxim Ag return tls13_hkdf_expand_label(out, digest, secret, label, context); 21672c33676SMaxim Ag } 21772c33676SMaxim Ag 21872c33676SMaxim Ag int 21972c33676SMaxim Ag tls13_derive_early_secrets(struct tls13_secrets *secrets, 22072c33676SMaxim Ag uint8_t *psk, size_t psk_len, const struct tls13_secret *context) 22172c33676SMaxim Ag { 22272c33676SMaxim Ag if (!secrets->init_done || secrets->early_done) 22372c33676SMaxim Ag return 0; 22472c33676SMaxim Ag 22572c33676SMaxim Ag if (!HKDF_extract(secrets->extracted_early.data, 22672c33676SMaxim Ag &secrets->extracted_early.len, secrets->digest, psk, psk_len, 22772c33676SMaxim Ag secrets->zeros.data, secrets->zeros.len)) 22872c33676SMaxim Ag return 0; 22972c33676SMaxim Ag 23072c33676SMaxim Ag if (secrets->extracted_early.len != secrets->zeros.len) 23172c33676SMaxim Ag return 0; 23272c33676SMaxim Ag 23372c33676SMaxim Ag if (!tls13_derive_secret(&secrets->binder_key, secrets->digest, 23472c33676SMaxim Ag &secrets->extracted_early, 23572c33676SMaxim Ag secrets->resumption ? "res binder" : "ext binder", 23672c33676SMaxim Ag &secrets->empty_hash)) 23772c33676SMaxim Ag return 0; 23872c33676SMaxim Ag if (!tls13_derive_secret(&secrets->client_early_traffic, 23972c33676SMaxim Ag secrets->digest, &secrets->extracted_early, "c e traffic", 24072c33676SMaxim Ag context)) 24172c33676SMaxim Ag return 0; 24272c33676SMaxim Ag if (!tls13_derive_secret(&secrets->early_exporter_master, 24372c33676SMaxim Ag secrets->digest, &secrets->extracted_early, "e exp master", 24472c33676SMaxim Ag context)) 24572c33676SMaxim Ag return 0; 24672c33676SMaxim Ag if (!tls13_derive_secret(&secrets->derived_early, 24772c33676SMaxim Ag secrets->digest, &secrets->extracted_early, "derived", 24872c33676SMaxim Ag &secrets->empty_hash)) 24972c33676SMaxim Ag return 0; 25072c33676SMaxim Ag 25172c33676SMaxim Ag /* RFC 8446 recommends */ 25272c33676SMaxim Ag if (!secrets->insecure) 25372c33676SMaxim Ag explicit_bzero(secrets->extracted_early.data, 25472c33676SMaxim Ag secrets->extracted_early.len); 25572c33676SMaxim Ag secrets->early_done = 1; 25672c33676SMaxim Ag return 1; 25772c33676SMaxim Ag } 25872c33676SMaxim Ag 25972c33676SMaxim Ag int 26072c33676SMaxim Ag tls13_derive_handshake_secrets(struct tls13_secrets *secrets, 26172c33676SMaxim Ag const uint8_t *ecdhe, size_t ecdhe_len, 26272c33676SMaxim Ag const struct tls13_secret *context) 26372c33676SMaxim Ag { 26472c33676SMaxim Ag if (!secrets->init_done || !secrets->early_done || 26572c33676SMaxim Ag secrets->handshake_done) 26672c33676SMaxim Ag return 0; 26772c33676SMaxim Ag 26872c33676SMaxim Ag if (!HKDF_extract(secrets->extracted_handshake.data, 26972c33676SMaxim Ag &secrets->extracted_handshake.len, secrets->digest, 27072c33676SMaxim Ag ecdhe, ecdhe_len, secrets->derived_early.data, 27172c33676SMaxim Ag secrets->derived_early.len)) 27272c33676SMaxim Ag return 0; 27372c33676SMaxim Ag 27472c33676SMaxim Ag if (secrets->extracted_handshake.len != secrets->zeros.len) 27572c33676SMaxim Ag return 0; 27672c33676SMaxim Ag 27772c33676SMaxim Ag /* XXX */ 27872c33676SMaxim Ag if (!secrets->insecure) 27972c33676SMaxim Ag explicit_bzero(secrets->derived_early.data, 28072c33676SMaxim Ag secrets->derived_early.len); 28172c33676SMaxim Ag 28272c33676SMaxim Ag if (!tls13_derive_secret(&secrets->client_handshake_traffic, 28372c33676SMaxim Ag secrets->digest, &secrets->extracted_handshake, "c hs traffic", 28472c33676SMaxim Ag context)) 28572c33676SMaxim Ag return 0; 28672c33676SMaxim Ag if (!tls13_derive_secret(&secrets->server_handshake_traffic, 28772c33676SMaxim Ag secrets->digest, &secrets->extracted_handshake, "s hs traffic", 28872c33676SMaxim Ag context)) 28972c33676SMaxim Ag return 0; 29072c33676SMaxim Ag if (!tls13_derive_secret(&secrets->derived_handshake, 29172c33676SMaxim Ag secrets->digest, &secrets->extracted_handshake, "derived", 29272c33676SMaxim Ag &secrets->empty_hash)) 29372c33676SMaxim Ag return 0; 29472c33676SMaxim Ag 29572c33676SMaxim Ag /* RFC 8446 recommends */ 29672c33676SMaxim Ag if (!secrets->insecure) 29772c33676SMaxim Ag explicit_bzero(secrets->extracted_handshake.data, 29872c33676SMaxim Ag secrets->extracted_handshake.len); 29972c33676SMaxim Ag 30072c33676SMaxim Ag secrets->handshake_done = 1; 30172c33676SMaxim Ag 30272c33676SMaxim Ag return 1; 30372c33676SMaxim Ag } 30472c33676SMaxim Ag 30572c33676SMaxim Ag int 30672c33676SMaxim Ag tls13_derive_application_secrets(struct tls13_secrets *secrets, 30772c33676SMaxim Ag const struct tls13_secret *context) 30872c33676SMaxim Ag { 30972c33676SMaxim Ag if (!secrets->init_done || !secrets->early_done || 31072c33676SMaxim Ag !secrets->handshake_done || secrets->schedule_done) 31172c33676SMaxim Ag return 0; 31272c33676SMaxim Ag 31372c33676SMaxim Ag if (!HKDF_extract(secrets->extracted_master.data, 31472c33676SMaxim Ag &secrets->extracted_master.len, secrets->digest, 31572c33676SMaxim Ag secrets->zeros.data, secrets->zeros.len, 31672c33676SMaxim Ag secrets->derived_handshake.data, secrets->derived_handshake.len)) 31772c33676SMaxim Ag return 0; 31872c33676SMaxim Ag 31972c33676SMaxim Ag if (secrets->extracted_master.len != secrets->zeros.len) 32072c33676SMaxim Ag return 0; 32172c33676SMaxim Ag 32272c33676SMaxim Ag /* XXX */ 32372c33676SMaxim Ag if (!secrets->insecure) 32472c33676SMaxim Ag explicit_bzero(secrets->derived_handshake.data, 32572c33676SMaxim Ag secrets->derived_handshake.len); 32672c33676SMaxim Ag 32772c33676SMaxim Ag if (!tls13_derive_secret(&secrets->client_application_traffic, 32872c33676SMaxim Ag secrets->digest, &secrets->extracted_master, "c ap traffic", 32972c33676SMaxim Ag context)) 33072c33676SMaxim Ag return 0; 33172c33676SMaxim Ag if (!tls13_derive_secret(&secrets->server_application_traffic, 33272c33676SMaxim Ag secrets->digest, &secrets->extracted_master, "s ap traffic", 33372c33676SMaxim Ag context)) 33472c33676SMaxim Ag return 0; 33572c33676SMaxim Ag if (!tls13_derive_secret(&secrets->exporter_master, 33672c33676SMaxim Ag secrets->digest, &secrets->extracted_master, "exp master", 33772c33676SMaxim Ag context)) 33872c33676SMaxim Ag return 0; 33972c33676SMaxim Ag if (!tls13_derive_secret(&secrets->resumption_master, 34072c33676SMaxim Ag secrets->digest, &secrets->extracted_master, "res master", 34172c33676SMaxim Ag context)) 34272c33676SMaxim Ag return 0; 34372c33676SMaxim Ag 34472c33676SMaxim Ag /* RFC 8446 recommends */ 34572c33676SMaxim Ag if (!secrets->insecure) 34672c33676SMaxim Ag explicit_bzero(secrets->extracted_master.data, 34772c33676SMaxim Ag secrets->extracted_master.len); 34872c33676SMaxim Ag 34972c33676SMaxim Ag secrets->schedule_done = 1; 35072c33676SMaxim Ag 35172c33676SMaxim Ag return 1; 35272c33676SMaxim Ag } 35372c33676SMaxim Ag 35472c33676SMaxim Ag int 35572c33676SMaxim Ag tls13_update_client_traffic_secret(struct tls13_secrets *secrets) 35672c33676SMaxim Ag { 35772c33676SMaxim Ag if (!secrets->init_done || !secrets->early_done || 35872c33676SMaxim Ag !secrets->handshake_done || !secrets->schedule_done) 35972c33676SMaxim Ag return 0; 36072c33676SMaxim Ag 36172c33676SMaxim Ag return tls13_hkdf_expand_label(&secrets->client_application_traffic, 36272c33676SMaxim Ag secrets->digest, &secrets->client_application_traffic, 36372c33676SMaxim Ag "traffic upd", &secrets->empty_hash); 36472c33676SMaxim Ag } 36572c33676SMaxim Ag 36672c33676SMaxim Ag int 36772c33676SMaxim Ag tls13_update_server_traffic_secret(struct tls13_secrets *secrets) 36872c33676SMaxim Ag { 36972c33676SMaxim Ag if (!secrets->init_done || !secrets->early_done || 37072c33676SMaxim Ag !secrets->handshake_done || !secrets->schedule_done) 37172c33676SMaxim Ag return 0; 37272c33676SMaxim Ag 37372c33676SMaxim Ag return tls13_hkdf_expand_label(&secrets->server_application_traffic, 37472c33676SMaxim Ag secrets->digest, &secrets->server_application_traffic, 37572c33676SMaxim Ag "traffic upd", &secrets->empty_hash); 37672c33676SMaxim Ag } 377