1*de0e0e4dSAntonio Huete Jimenez /* $OpenBSD: tls12_key_schedule.c,v 1.1 2021/05/05 10:05:27 jsing Exp $ */
2*de0e0e4dSAntonio Huete Jimenez /*
3*de0e0e4dSAntonio Huete Jimenez * Copyright (c) 2021 Joel Sing <jsing@openbsd.org>
4*de0e0e4dSAntonio Huete Jimenez *
5*de0e0e4dSAntonio Huete Jimenez * Permission to use, copy, modify, and distribute this software for any
6*de0e0e4dSAntonio Huete Jimenez * purpose with or without fee is hereby granted, provided that the above
7*de0e0e4dSAntonio Huete Jimenez * copyright notice and this permission notice appear in all copies.
8*de0e0e4dSAntonio Huete Jimenez *
9*de0e0e4dSAntonio Huete Jimenez * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*de0e0e4dSAntonio Huete Jimenez * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*de0e0e4dSAntonio Huete Jimenez * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*de0e0e4dSAntonio Huete Jimenez * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*de0e0e4dSAntonio Huete Jimenez * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*de0e0e4dSAntonio Huete Jimenez * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*de0e0e4dSAntonio Huete Jimenez * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*de0e0e4dSAntonio Huete Jimenez */
17*de0e0e4dSAntonio Huete Jimenez
18*de0e0e4dSAntonio Huete Jimenez #include <stdlib.h>
19*de0e0e4dSAntonio Huete Jimenez
20*de0e0e4dSAntonio Huete Jimenez #include <openssl/evp.h>
21*de0e0e4dSAntonio Huete Jimenez
22*de0e0e4dSAntonio Huete Jimenez #include "bytestring.h"
23*de0e0e4dSAntonio Huete Jimenez #include "ssl_locl.h"
24*de0e0e4dSAntonio Huete Jimenez
25*de0e0e4dSAntonio Huete Jimenez struct tls12_key_block {
26*de0e0e4dSAntonio Huete Jimenez CBS client_write_mac_key;
27*de0e0e4dSAntonio Huete Jimenez CBS server_write_mac_key;
28*de0e0e4dSAntonio Huete Jimenez CBS client_write_key;
29*de0e0e4dSAntonio Huete Jimenez CBS server_write_key;
30*de0e0e4dSAntonio Huete Jimenez CBS client_write_iv;
31*de0e0e4dSAntonio Huete Jimenez CBS server_write_iv;
32*de0e0e4dSAntonio Huete Jimenez
33*de0e0e4dSAntonio Huete Jimenez uint8_t *key_block;
34*de0e0e4dSAntonio Huete Jimenez size_t key_block_len;
35*de0e0e4dSAntonio Huete Jimenez };
36*de0e0e4dSAntonio Huete Jimenez
37*de0e0e4dSAntonio Huete Jimenez struct tls12_key_block *
tls12_key_block_new(void)38*de0e0e4dSAntonio Huete Jimenez tls12_key_block_new(void)
39*de0e0e4dSAntonio Huete Jimenez {
40*de0e0e4dSAntonio Huete Jimenez return calloc(1, sizeof(struct tls12_key_block));
41*de0e0e4dSAntonio Huete Jimenez }
42*de0e0e4dSAntonio Huete Jimenez
43*de0e0e4dSAntonio Huete Jimenez static void
tls12_key_block_clear(struct tls12_key_block * kb)44*de0e0e4dSAntonio Huete Jimenez tls12_key_block_clear(struct tls12_key_block *kb)
45*de0e0e4dSAntonio Huete Jimenez {
46*de0e0e4dSAntonio Huete Jimenez CBS_init(&kb->client_write_mac_key, NULL, 0);
47*de0e0e4dSAntonio Huete Jimenez CBS_init(&kb->server_write_mac_key, NULL, 0);
48*de0e0e4dSAntonio Huete Jimenez CBS_init(&kb->client_write_key, NULL, 0);
49*de0e0e4dSAntonio Huete Jimenez CBS_init(&kb->server_write_key, NULL, 0);
50*de0e0e4dSAntonio Huete Jimenez CBS_init(&kb->client_write_iv, NULL, 0);
51*de0e0e4dSAntonio Huete Jimenez CBS_init(&kb->server_write_iv, NULL, 0);
52*de0e0e4dSAntonio Huete Jimenez
53*de0e0e4dSAntonio Huete Jimenez freezero(kb->key_block, kb->key_block_len);
54*de0e0e4dSAntonio Huete Jimenez kb->key_block = NULL;
55*de0e0e4dSAntonio Huete Jimenez kb->key_block_len = 0;
56*de0e0e4dSAntonio Huete Jimenez }
57*de0e0e4dSAntonio Huete Jimenez
58*de0e0e4dSAntonio Huete Jimenez void
tls12_key_block_free(struct tls12_key_block * kb)59*de0e0e4dSAntonio Huete Jimenez tls12_key_block_free(struct tls12_key_block *kb)
60*de0e0e4dSAntonio Huete Jimenez {
61*de0e0e4dSAntonio Huete Jimenez if (kb == NULL)
62*de0e0e4dSAntonio Huete Jimenez return;
63*de0e0e4dSAntonio Huete Jimenez
64*de0e0e4dSAntonio Huete Jimenez tls12_key_block_clear(kb);
65*de0e0e4dSAntonio Huete Jimenez
66*de0e0e4dSAntonio Huete Jimenez freezero(kb, sizeof(struct tls12_key_block));
67*de0e0e4dSAntonio Huete Jimenez }
68*de0e0e4dSAntonio Huete Jimenez
69*de0e0e4dSAntonio Huete Jimenez void
tls12_key_block_client_write(struct tls12_key_block * kb,CBS * mac_key,CBS * key,CBS * iv)70*de0e0e4dSAntonio Huete Jimenez tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key,
71*de0e0e4dSAntonio Huete Jimenez CBS *key, CBS *iv)
72*de0e0e4dSAntonio Huete Jimenez {
73*de0e0e4dSAntonio Huete Jimenez CBS_dup(&kb->client_write_mac_key, mac_key);
74*de0e0e4dSAntonio Huete Jimenez CBS_dup(&kb->client_write_key, key);
75*de0e0e4dSAntonio Huete Jimenez CBS_dup(&kb->client_write_iv, iv);
76*de0e0e4dSAntonio Huete Jimenez }
77*de0e0e4dSAntonio Huete Jimenez
78*de0e0e4dSAntonio Huete Jimenez void
tls12_key_block_server_write(struct tls12_key_block * kb,CBS * mac_key,CBS * key,CBS * iv)79*de0e0e4dSAntonio Huete Jimenez tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key,
80*de0e0e4dSAntonio Huete Jimenez CBS *key, CBS *iv)
81*de0e0e4dSAntonio Huete Jimenez {
82*de0e0e4dSAntonio Huete Jimenez CBS_dup(&kb->server_write_mac_key, mac_key);
83*de0e0e4dSAntonio Huete Jimenez CBS_dup(&kb->server_write_key, key);
84*de0e0e4dSAntonio Huete Jimenez CBS_dup(&kb->server_write_iv, iv);
85*de0e0e4dSAntonio Huete Jimenez }
86*de0e0e4dSAntonio Huete Jimenez
87*de0e0e4dSAntonio Huete Jimenez int
tls12_key_block_generate(struct tls12_key_block * kb,SSL * s,const EVP_AEAD * aead,const EVP_CIPHER * cipher,const EVP_MD * mac_hash)88*de0e0e4dSAntonio Huete Jimenez tls12_key_block_generate(struct tls12_key_block *kb, SSL *s,
89*de0e0e4dSAntonio Huete Jimenez const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash)
90*de0e0e4dSAntonio Huete Jimenez {
91*de0e0e4dSAntonio Huete Jimenez size_t mac_key_len = 0, key_len = 0, iv_len = 0;
92*de0e0e4dSAntonio Huete Jimenez uint8_t *key_block = NULL;
93*de0e0e4dSAntonio Huete Jimenez size_t key_block_len = 0;
94*de0e0e4dSAntonio Huete Jimenez CBS cbs;
95*de0e0e4dSAntonio Huete Jimenez
96*de0e0e4dSAntonio Huete Jimenez /*
97*de0e0e4dSAntonio Huete Jimenez * Generate a TLSv1.2 key block and partition into individual secrets,
98*de0e0e4dSAntonio Huete Jimenez * as per RFC 5246 section 6.3.
99*de0e0e4dSAntonio Huete Jimenez */
100*de0e0e4dSAntonio Huete Jimenez
101*de0e0e4dSAntonio Huete Jimenez tls12_key_block_clear(kb);
102*de0e0e4dSAntonio Huete Jimenez
103*de0e0e4dSAntonio Huete Jimenez /* Must have AEAD or cipher/MAC pair. */
104*de0e0e4dSAntonio Huete Jimenez if (aead == NULL && (cipher == NULL || mac_hash == NULL))
105*de0e0e4dSAntonio Huete Jimenez goto err;
106*de0e0e4dSAntonio Huete Jimenez
107*de0e0e4dSAntonio Huete Jimenez if (aead != NULL) {
108*de0e0e4dSAntonio Huete Jimenez key_len = EVP_AEAD_key_length(aead);
109*de0e0e4dSAntonio Huete Jimenez
110*de0e0e4dSAntonio Huete Jimenez /* AEAD fixed nonce length. */
111*de0e0e4dSAntonio Huete Jimenez if (aead == EVP_aead_aes_128_gcm() ||
112*de0e0e4dSAntonio Huete Jimenez aead == EVP_aead_aes_256_gcm())
113*de0e0e4dSAntonio Huete Jimenez iv_len = 4;
114*de0e0e4dSAntonio Huete Jimenez else if (aead == EVP_aead_chacha20_poly1305())
115*de0e0e4dSAntonio Huete Jimenez iv_len = 12;
116*de0e0e4dSAntonio Huete Jimenez else
117*de0e0e4dSAntonio Huete Jimenez goto err;
118*de0e0e4dSAntonio Huete Jimenez } else if (cipher != NULL && mac_hash != NULL) {
119*de0e0e4dSAntonio Huete Jimenez /*
120*de0e0e4dSAntonio Huete Jimenez * A negative integer return value will be detected via the
121*de0e0e4dSAntonio Huete Jimenez * EVP_MAX_* checks against the size_t variables below.
122*de0e0e4dSAntonio Huete Jimenez */
123*de0e0e4dSAntonio Huete Jimenez mac_key_len = EVP_MD_size(mac_hash);
124*de0e0e4dSAntonio Huete Jimenez key_len = EVP_CIPHER_key_length(cipher);
125*de0e0e4dSAntonio Huete Jimenez iv_len = EVP_CIPHER_iv_length(cipher);
126*de0e0e4dSAntonio Huete Jimenez
127*de0e0e4dSAntonio Huete Jimenez /* Special handling for GOST... */
128*de0e0e4dSAntonio Huete Jimenez if (EVP_MD_type(mac_hash) == NID_id_Gost28147_89_MAC)
129*de0e0e4dSAntonio Huete Jimenez mac_key_len = 32;
130*de0e0e4dSAntonio Huete Jimenez }
131*de0e0e4dSAntonio Huete Jimenez
132*de0e0e4dSAntonio Huete Jimenez if (mac_key_len > EVP_MAX_MD_SIZE)
133*de0e0e4dSAntonio Huete Jimenez goto err;
134*de0e0e4dSAntonio Huete Jimenez if (key_len > EVP_MAX_KEY_LENGTH)
135*de0e0e4dSAntonio Huete Jimenez goto err;
136*de0e0e4dSAntonio Huete Jimenez if (iv_len > EVP_MAX_IV_LENGTH)
137*de0e0e4dSAntonio Huete Jimenez goto err;
138*de0e0e4dSAntonio Huete Jimenez
139*de0e0e4dSAntonio Huete Jimenez key_block_len = 2 * mac_key_len + 2 * key_len + 2 * iv_len;
140*de0e0e4dSAntonio Huete Jimenez if ((key_block = calloc(1, key_block_len)) == NULL)
141*de0e0e4dSAntonio Huete Jimenez goto err;
142*de0e0e4dSAntonio Huete Jimenez
143*de0e0e4dSAntonio Huete Jimenez if (!tls1_generate_key_block(s, key_block, key_block_len))
144*de0e0e4dSAntonio Huete Jimenez goto err;
145*de0e0e4dSAntonio Huete Jimenez
146*de0e0e4dSAntonio Huete Jimenez kb->key_block = key_block;
147*de0e0e4dSAntonio Huete Jimenez kb->key_block_len = key_block_len;
148*de0e0e4dSAntonio Huete Jimenez key_block = NULL;
149*de0e0e4dSAntonio Huete Jimenez key_block_len = 0;
150*de0e0e4dSAntonio Huete Jimenez
151*de0e0e4dSAntonio Huete Jimenez /* Partition key block into individual secrets. */
152*de0e0e4dSAntonio Huete Jimenez CBS_init(&cbs, kb->key_block, kb->key_block_len);
153*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_bytes(&cbs, &kb->client_write_mac_key, mac_key_len))
154*de0e0e4dSAntonio Huete Jimenez goto err;
155*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_bytes(&cbs, &kb->server_write_mac_key, mac_key_len))
156*de0e0e4dSAntonio Huete Jimenez goto err;
157*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_bytes(&cbs, &kb->client_write_key, key_len))
158*de0e0e4dSAntonio Huete Jimenez goto err;
159*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_bytes(&cbs, &kb->server_write_key, key_len))
160*de0e0e4dSAntonio Huete Jimenez goto err;
161*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_bytes(&cbs, &kb->client_write_iv, iv_len))
162*de0e0e4dSAntonio Huete Jimenez goto err;
163*de0e0e4dSAntonio Huete Jimenez if (!CBS_get_bytes(&cbs, &kb->server_write_iv, iv_len))
164*de0e0e4dSAntonio Huete Jimenez goto err;
165*de0e0e4dSAntonio Huete Jimenez if (CBS_len(&cbs) != 0)
166*de0e0e4dSAntonio Huete Jimenez goto err;
167*de0e0e4dSAntonio Huete Jimenez
168*de0e0e4dSAntonio Huete Jimenez return 1;
169*de0e0e4dSAntonio Huete Jimenez
170*de0e0e4dSAntonio Huete Jimenez err:
171*de0e0e4dSAntonio Huete Jimenez tls12_key_block_clear(kb);
172*de0e0e4dSAntonio Huete Jimenez freezero(key_block, key_block_len);
173*de0e0e4dSAntonio Huete Jimenez
174*de0e0e4dSAntonio Huete Jimenez return 0;
175*de0e0e4dSAntonio Huete Jimenez }
176