1 /* $OpenBSD: tls12_key_schedule.c,v 1.3 2022/11/26 16:08:56 tb Exp $ */ 2 /* 3 * Copyright (c) 2021 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <stdlib.h> 19 20 #include <openssl/evp.h> 21 22 #include "bytestring.h" 23 #include "ssl_local.h" 24 #include "tls12_internal.h" 25 26 struct tls12_key_block { 27 CBS client_write_mac_key; 28 CBS server_write_mac_key; 29 CBS client_write_key; 30 CBS server_write_key; 31 CBS client_write_iv; 32 CBS server_write_iv; 33 34 uint8_t *key_block; 35 size_t key_block_len; 36 }; 37 38 struct tls12_key_block * 39 tls12_key_block_new(void) 40 { 41 return calloc(1, sizeof(struct tls12_key_block)); 42 } 43 44 static void 45 tls12_key_block_clear(struct tls12_key_block *kb) 46 { 47 CBS_init(&kb->client_write_mac_key, NULL, 0); 48 CBS_init(&kb->server_write_mac_key, NULL, 0); 49 CBS_init(&kb->client_write_key, NULL, 0); 50 CBS_init(&kb->server_write_key, NULL, 0); 51 CBS_init(&kb->client_write_iv, NULL, 0); 52 CBS_init(&kb->server_write_iv, NULL, 0); 53 54 freezero(kb->key_block, kb->key_block_len); 55 kb->key_block = NULL; 56 kb->key_block_len = 0; 57 } 58 59 void 60 tls12_key_block_free(struct tls12_key_block *kb) 61 { 62 if (kb == NULL) 63 return; 64 65 tls12_key_block_clear(kb); 66 67 freezero(kb, sizeof(struct tls12_key_block)); 68 } 69 70 void 71 tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key, 72 CBS *key, CBS *iv) 73 { 74 CBS_dup(&kb->client_write_mac_key, mac_key); 75 CBS_dup(&kb->client_write_key, key); 76 CBS_dup(&kb->client_write_iv, iv); 77 } 78 79 void 80 tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key, 81 CBS *key, CBS *iv) 82 { 83 CBS_dup(&kb->server_write_mac_key, mac_key); 84 CBS_dup(&kb->server_write_key, key); 85 CBS_dup(&kb->server_write_iv, iv); 86 } 87 88 int 89 tls12_key_block_generate(struct tls12_key_block *kb, SSL *s, 90 const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash) 91 { 92 size_t mac_key_len = 0, key_len = 0, iv_len = 0; 93 uint8_t *key_block = NULL; 94 size_t key_block_len = 0; 95 CBS cbs; 96 97 /* 98 * Generate a TLSv1.2 key block and partition into individual secrets, 99 * as per RFC 5246 section 6.3. 100 */ 101 102 tls12_key_block_clear(kb); 103 104 /* Must have AEAD or cipher/MAC pair. */ 105 if (aead == NULL && (cipher == NULL || mac_hash == NULL)) 106 goto err; 107 108 if (aead != NULL) { 109 key_len = EVP_AEAD_key_length(aead); 110 111 /* AEAD fixed nonce length. */ 112 if (aead == EVP_aead_aes_128_gcm() || 113 aead == EVP_aead_aes_256_gcm()) 114 iv_len = 4; 115 else if (aead == EVP_aead_chacha20_poly1305()) 116 iv_len = 12; 117 else 118 goto err; 119 } else if (cipher != NULL && mac_hash != NULL) { 120 /* 121 * A negative integer return value will be detected via the 122 * EVP_MAX_* checks against the size_t variables below. 123 */ 124 mac_key_len = EVP_MD_size(mac_hash); 125 key_len = EVP_CIPHER_key_length(cipher); 126 iv_len = EVP_CIPHER_iv_length(cipher); 127 128 /* Special handling for GOST... */ 129 if (EVP_MD_type(mac_hash) == NID_id_Gost28147_89_MAC) 130 mac_key_len = 32; 131 } 132 133 if (mac_key_len > EVP_MAX_MD_SIZE) 134 goto err; 135 if (key_len > EVP_MAX_KEY_LENGTH) 136 goto err; 137 if (iv_len > EVP_MAX_IV_LENGTH) 138 goto err; 139 140 key_block_len = 2 * mac_key_len + 2 * key_len + 2 * iv_len; 141 if ((key_block = calloc(1, key_block_len)) == NULL) 142 goto err; 143 144 if (!tls1_generate_key_block(s, key_block, key_block_len)) 145 goto err; 146 147 kb->key_block = key_block; 148 kb->key_block_len = key_block_len; 149 key_block = NULL; 150 key_block_len = 0; 151 152 /* Partition key block into individual secrets. */ 153 CBS_init(&cbs, kb->key_block, kb->key_block_len); 154 if (!CBS_get_bytes(&cbs, &kb->client_write_mac_key, mac_key_len)) 155 goto err; 156 if (!CBS_get_bytes(&cbs, &kb->server_write_mac_key, mac_key_len)) 157 goto err; 158 if (!CBS_get_bytes(&cbs, &kb->client_write_key, key_len)) 159 goto err; 160 if (!CBS_get_bytes(&cbs, &kb->server_write_key, key_len)) 161 goto err; 162 if (!CBS_get_bytes(&cbs, &kb->client_write_iv, iv_len)) 163 goto err; 164 if (!CBS_get_bytes(&cbs, &kb->server_write_iv, iv_len)) 165 goto err; 166 if (CBS_len(&cbs) != 0) 167 goto err; 168 169 return 1; 170 171 err: 172 tls12_key_block_clear(kb); 173 freezero(key_block, key_block_len); 174 175 return 0; 176 } 177 178 struct tls12_reserved_label { 179 const char *label; 180 size_t label_len; 181 }; 182 183 /* 184 * RFC 5705 section 6. 185 */ 186 static const struct tls12_reserved_label tls12_reserved_labels[] = { 187 { 188 .label = TLS_MD_CLIENT_FINISH_CONST, 189 .label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE, 190 }, 191 { 192 .label = TLS_MD_SERVER_FINISH_CONST, 193 .label_len = TLS_MD_SERVER_FINISH_CONST_SIZE, 194 }, 195 { 196 .label = TLS_MD_MASTER_SECRET_CONST, 197 .label_len = TLS_MD_MASTER_SECRET_CONST_SIZE, 198 }, 199 { 200 .label = TLS_MD_KEY_EXPANSION_CONST, 201 .label_len = TLS_MD_KEY_EXPANSION_CONST_SIZE, 202 }, 203 { 204 .label = NULL, 205 .label_len = 0, 206 }, 207 }; 208 209 int 210 tls12_exporter(SSL *s, const uint8_t *label, size_t label_len, 211 const uint8_t *context_value, size_t context_value_len, int use_context, 212 uint8_t *out, size_t out_len) 213 { 214 uint8_t *data = NULL; 215 size_t data_len = 0; 216 CBB cbb, context; 217 CBS seed; 218 size_t i; 219 int ret = 0; 220 221 /* 222 * RFC 5705 - Key Material Exporters for TLS. 223 */ 224 225 memset(&cbb, 0, sizeof(cbb)); 226 227 if (!SSL_is_init_finished(s)) { 228 SSLerror(s, SSL_R_BAD_STATE); 229 goto err; 230 } 231 232 if (s->s3->hs.negotiated_tls_version >= TLS1_3_VERSION) 233 goto err; 234 235 /* 236 * Due to exceptional design choices, we need to build a concatenation 237 * of the label and the seed value, before checking for reserved 238 * labels. This prevents a reserved label from being split across the 239 * label and the seed (that includes the client random), which are 240 * concatenated by the PRF. 241 */ 242 if (!CBB_init(&cbb, 0)) 243 goto err; 244 if (!CBB_add_bytes(&cbb, label, label_len)) 245 goto err; 246 if (!CBB_add_bytes(&cbb, s->s3->client_random, SSL3_RANDOM_SIZE)) 247 goto err; 248 if (!CBB_add_bytes(&cbb, s->s3->server_random, SSL3_RANDOM_SIZE)) 249 goto err; 250 if (use_context) { 251 if (!CBB_add_u16_length_prefixed(&cbb, &context)) 252 goto err; 253 if (context_value_len > 0) { 254 if (!CBB_add_bytes(&context, context_value, 255 context_value_len)) 256 goto err; 257 } 258 } 259 if (!CBB_finish(&cbb, &data, &data_len)) 260 goto err; 261 262 /* 263 * Ensure that the block (label + seed) does not start with a reserved 264 * label - in an ideal world we would ensure that the label has an 265 * explicitly permitted prefix instead, but of course this also got 266 * messed up by the standards. 267 */ 268 for (i = 0; tls12_reserved_labels[i].label != NULL; i++) { 269 /* XXX - consider adding/using CBS_has_prefix(). */ 270 if (tls12_reserved_labels[i].label_len > data_len) 271 goto err; 272 if (memcmp(data, tls12_reserved_labels[i].label, 273 tls12_reserved_labels[i].label_len) == 0) { 274 SSLerror(s, SSL_R_TLS_ILLEGAL_EXPORTER_LABEL); 275 goto err; 276 } 277 } 278 279 CBS_init(&seed, data, data_len); 280 if (!CBS_skip(&seed, label_len)) 281 goto err; 282 283 if (!tls1_PRF(s, s->session->master_key, s->session->master_key_length, 284 label, label_len, CBS_data(&seed), CBS_len(&seed), NULL, 0, NULL, 0, 285 NULL, 0, out, out_len)) 286 goto err; 287 288 ret = 1; 289 290 err: 291 freezero(data, data_len); 292 CBB_cleanup(&cbb); 293 294 return ret; 295 } 296