Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved. |
| 3 | * |
| 4 | * Licensed under the OpenSSL license (the "License"). You may not use |
| 5 | * this file except in compliance with the License. You can obtain a copy |
| 6 | * in the file LICENSE in the source distribution or at |
| 7 | * https://www.openssl.org/source/license.html |
| 8 | */ |
| 9 | |
| 10 | #include <stdlib.h> |
| 11 | #include "ssl_locl.h" |
| 12 | #include <openssl/evp.h> |
| 13 | #include <openssl/kdf.h> |
| 14 | |
| 15 | #define TLS13_MAX_LABEL_LEN 246 |
| 16 | |
| 17 | /* Always filled with zeros */ |
| 18 | static const unsigned char default_zeros[EVP_MAX_MD_SIZE]; |
| 19 | |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 20 | /* |
| 21 | * Given a |secret|; a |label| of length |labellen|; and a |hash| of the |
| 22 | * handshake messages, derive a new secret |outlen| bytes long and store it in |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 23 | * the location pointed to be |out|. The |hash| value may be NULL. Returns 1 on |
| 24 | * success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 25 | */ |
| 26 | static int tls13_hkdf_expand(SSL *s, const unsigned char *secret, |
| 27 | const unsigned char *label, size_t labellen, |
| 28 | const unsigned char *hash, |
| 29 | unsigned char *out, size_t outlen) |
| 30 | { |
| 31 | const unsigned char label_prefix[] = "TLS 1.3, "; |
| 32 | const EVP_MD *md = ssl_handshake_md(s); |
| 33 | EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); |
| 34 | int ret; |
| 35 | size_t hkdflabellen; |
| 36 | size_t hashlen; |
| 37 | /* |
| 38 | * 2 bytes for length of whole HkdfLabel + 1 byte for length of combined |
| 39 | * prefix and label + bytes for the label itself + bytes for the hash |
| 40 | */ |
| 41 | unsigned char hkdflabel[sizeof(uint16_t) + sizeof(uint8_t) + |
| 42 | + sizeof(label_prefix) + TLS13_MAX_LABEL_LEN |
| 43 | + EVP_MAX_MD_SIZE]; |
| 44 | WPACKET pkt; |
| 45 | |
| 46 | if (pctx == NULL) |
| 47 | return 0; |
| 48 | |
| 49 | hashlen = EVP_MD_size(md); |
| 50 | |
| 51 | if (!WPACKET_init_static_len(&pkt, hkdflabel, sizeof(hkdflabel), 0) |
| 52 | || !WPACKET_put_bytes_u16(&pkt, outlen) |
| 53 | || !WPACKET_start_sub_packet_u8(&pkt) |
| 54 | || !WPACKET_memcpy(&pkt, label_prefix, sizeof(label_prefix) - 1) |
| 55 | || !WPACKET_memcpy(&pkt, label, labellen) |
| 56 | || !WPACKET_close(&pkt) |
| 57 | || !WPACKET_sub_memcpy_u8(&pkt, hash, (hash == NULL) ? 0 : hashlen) |
| 58 | || !WPACKET_get_total_written(&pkt, &hkdflabellen) |
| 59 | || !WPACKET_finish(&pkt)) { |
| 60 | WPACKET_cleanup(&pkt); |
| 61 | return 0; |
| 62 | } |
| 63 | |
| 64 | ret = EVP_PKEY_derive_init(pctx) <= 0 |
| 65 | || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXPAND_ONLY) |
| 66 | <= 0 |
| 67 | || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0 |
| 68 | || EVP_PKEY_CTX_set1_hkdf_key(pctx, secret, hashlen) <= 0 |
| 69 | || EVP_PKEY_CTX_add1_hkdf_info(pctx, hkdflabel, hkdflabellen) <= 0 |
| 70 | || EVP_PKEY_derive(pctx, out, &outlen) <= 0; |
| 71 | |
| 72 | EVP_PKEY_CTX_free(pctx); |
| 73 | |
| 74 | return ret == 0; |
| 75 | } |
| 76 | |
| 77 | /* |
| 78 | * Given a input secret |insecret| and a |label| of length |labellen|, derive a |
| 79 | * new |secret|. This will be the length of the current hash output size and |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 80 | * will be based on the current state of the handshake hashes. Returns 1 on |
| 81 | * success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 82 | */ |
| 83 | int tls13_derive_secret(SSL *s, const unsigned char *insecret, |
| 84 | const unsigned char *label, size_t labellen, |
| 85 | unsigned char *secret) |
| 86 | { |
| 87 | unsigned char hash[EVP_MAX_MD_SIZE]; |
| 88 | size_t hashlen; |
| 89 | |
| 90 | if (!ssl3_digest_cached_records(s, 1)) |
| 91 | return 0; |
| 92 | |
| 93 | if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) |
| 94 | return 0; |
| 95 | |
| 96 | return tls13_hkdf_expand(s, insecret, label, labellen, hash, secret, |
| 97 | hashlen); |
| 98 | } |
| 99 | |
| 100 | /* |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 101 | * Given a |secret| generate a |key| of length |keylen| bytes. Returns 1 on |
| 102 | * success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 103 | */ |
| 104 | int tls13_derive_key(SSL *s, const unsigned char *secret, unsigned char *key, |
| 105 | size_t keylen) |
| 106 | { |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 107 | static const unsigned char keylabel[] = "key"; |
| 108 | |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 109 | return tls13_hkdf_expand(s, secret, keylabel, sizeof(keylabel) - 1, NULL, |
| 110 | key, keylen); |
| 111 | } |
| 112 | |
| 113 | /* |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 114 | * Given a |secret| generate an |iv| of length |ivlen| bytes. Returns 1 on |
| 115 | * success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 116 | */ |
| 117 | int tls13_derive_iv(SSL *s, const unsigned char *secret, unsigned char *iv, |
| 118 | size_t ivlen) |
| 119 | { |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 120 | static const unsigned char ivlabel[] = "iv"; |
| 121 | |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 122 | return tls13_hkdf_expand(s, secret, ivlabel, sizeof(ivlabel) - 1, NULL, |
| 123 | iv, ivlen); |
| 124 | } |
| 125 | |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 126 | static int tls13_derive_finishedkey(SSL *s, const unsigned char *secret, |
| 127 | unsigned char *fin, size_t finlen) |
| 128 | { |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 129 | static const unsigned char finishedlabel[] = "finished"; |
| 130 | |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 131 | return tls13_hkdf_expand(s, secret, finishedlabel, |
| 132 | sizeof(finishedlabel) - 1, NULL, fin, finlen); |
| 133 | } |
| 134 | |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 135 | /* |
| 136 | * Given the previous secret |prevsecret| and a new input secret |insecret| of |
| 137 | * length |insecretlen|, generate a new secret and store it in the location |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 138 | * pointed to by |outsecret|. Returns 1 on success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 139 | */ |
| 140 | static int tls13_generate_secret(SSL *s, const unsigned char *prevsecret, |
| 141 | const unsigned char *insecret, |
| 142 | size_t insecretlen, |
| 143 | unsigned char *outsecret) |
| 144 | { |
| 145 | const EVP_MD *md = ssl_handshake_md(s); |
| 146 | size_t mdlen, prevsecretlen; |
| 147 | int ret; |
| 148 | EVP_PKEY_CTX *pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_HKDF, NULL); |
| 149 | |
| 150 | if (pctx == NULL) |
| 151 | return 0; |
| 152 | |
| 153 | mdlen = EVP_MD_size(md); |
| 154 | |
| 155 | if (insecret == NULL) { |
| 156 | insecret = default_zeros; |
| 157 | insecretlen = mdlen; |
| 158 | } |
| 159 | if (prevsecret == NULL) { |
| 160 | prevsecret = default_zeros; |
| 161 | prevsecretlen = 0; |
| 162 | } else { |
| 163 | prevsecretlen = mdlen; |
| 164 | } |
| 165 | |
| 166 | ret = EVP_PKEY_derive_init(pctx) <= 0 |
| 167 | || EVP_PKEY_CTX_hkdf_mode(pctx, EVP_PKEY_HKDEF_MODE_EXTRACT_ONLY) |
| 168 | <= 0 |
| 169 | || EVP_PKEY_CTX_set_hkdf_md(pctx, md) <= 0 |
| 170 | || EVP_PKEY_CTX_set1_hkdf_key(pctx, insecret, insecretlen) <= 0 |
| 171 | || EVP_PKEY_CTX_set1_hkdf_salt(pctx, prevsecret, prevsecretlen) |
| 172 | <= 0 |
| 173 | || EVP_PKEY_derive(pctx, outsecret, &mdlen) |
| 174 | <= 0; |
| 175 | |
| 176 | EVP_PKEY_CTX_free(pctx); |
| 177 | return ret == 0; |
| 178 | } |
| 179 | |
| 180 | /* |
| 181 | * Given an input secret |insecret| of length |insecretlen| generate the early |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 182 | * secret. Returns 1 on success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 183 | */ |
| 184 | int tls13_generate_early_secret(SSL *s, const unsigned char *insecret, |
| 185 | size_t insecretlen) |
| 186 | { |
| 187 | return tls13_generate_secret(s, NULL, insecret, insecretlen, |
| 188 | (unsigned char *)&s->early_secret); |
| 189 | } |
| 190 | |
| 191 | /* |
| 192 | * Given an input secret |insecret| of length |insecretlen| generate the |
| 193 | * handshake secret. This requires the early secret to already have been |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 194 | * generated. Returns 1 on success 0 on failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 195 | */ |
| 196 | int tls13_generate_handshake_secret(SSL *s, const unsigned char *insecret, |
| 197 | size_t insecretlen) |
| 198 | { |
| 199 | return tls13_generate_secret(s, s->early_secret, insecret, insecretlen, |
| 200 | (unsigned char *)&s->handshake_secret); |
| 201 | } |
| 202 | |
| 203 | /* |
| 204 | * Given the handshake secret |prev| of length |prevlen| generate the master |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 205 | * secret and store its length in |*secret_size|. Returns 1 on success 0 on |
| 206 | * failure. |
Matt Caswell | 34574f1 | 2016-11-08 10:34:28 +0000 | [diff] [blame] | 207 | */ |
| 208 | int tls13_generate_master_secret(SSL *s, unsigned char *out, |
| 209 | unsigned char *prev, size_t prevlen, |
| 210 | size_t *secret_size) |
| 211 | { |
| 212 | *secret_size = EVP_MD_size(ssl_handshake_md(s)); |
| 213 | return tls13_generate_secret(s, prev, NULL, 0, out); |
| 214 | } |
| 215 | |
Matt Caswell | 92760c2 | 2016-11-09 14:06:12 +0000 | [diff] [blame] | 216 | /* |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 217 | * Generates the mac for the Finished message. Returns the length of the MAC or |
| 218 | * 0 on error. |
Matt Caswell | 92760c2 | 2016-11-09 14:06:12 +0000 | [diff] [blame] | 219 | */ |
| 220 | size_t tls13_final_finish_mac(SSL *s, const char *str, size_t slen, |
| 221 | unsigned char *out) |
| 222 | { |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 223 | const EVP_MD *md = ssl_handshake_md(s); |
| 224 | unsigned char hash[EVP_MAX_MD_SIZE]; |
| 225 | size_t hashlen, ret = 0; |
| 226 | EVP_PKEY *key = NULL; |
| 227 | EVP_MD_CTX *ctx = EVP_MD_CTX_new(); |
Matt Caswell | 92760c2 | 2016-11-09 14:06:12 +0000 | [diff] [blame] | 228 | |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 229 | if (!ssl_handshake_hash(s, hash, sizeof(hash), &hashlen)) |
| 230 | goto err; |
Matt Caswell | 92760c2 | 2016-11-09 14:06:12 +0000 | [diff] [blame] | 231 | |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 232 | if (str == s->method->ssl3_enc->server_finished_label) |
| 233 | key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, |
| 234 | s->server_finished_secret, hashlen); |
| 235 | else |
| 236 | key = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, |
| 237 | s->client_finished_secret, hashlen); |
| 238 | |
| 239 | if (key == NULL |
| 240 | || ctx == NULL |
| 241 | || EVP_DigestSignInit(ctx, NULL, md, NULL, key) <= 0 |
| 242 | || EVP_DigestSignUpdate(ctx, hash, hashlen) <= 0 |
| 243 | || EVP_DigestSignFinal(ctx, out, &hashlen) <= 0) |
| 244 | goto err; |
| 245 | |
| 246 | ret = hashlen; |
| 247 | err: |
| 248 | EVP_PKEY_free(key); |
| 249 | EVP_MD_CTX_free(ctx); |
| 250 | return ret; |
Matt Caswell | 92760c2 | 2016-11-09 14:06:12 +0000 | [diff] [blame] | 251 | } |
| 252 | |
| 253 | /* |
| 254 | * There isn't really a key block in TLSv1.3, but we still need this function |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 255 | * for initialising the cipher and hash. Returns 1 on success or 0 on failure. |
Matt Caswell | 92760c2 | 2016-11-09 14:06:12 +0000 | [diff] [blame] | 256 | */ |
| 257 | int tls13_setup_key_block(SSL *s) |
| 258 | { |
| 259 | const EVP_CIPHER *c; |
| 260 | const EVP_MD *hash; |
| 261 | int mac_type = NID_undef; |
| 262 | |
| 263 | s->session->cipher = s->s3->tmp.new_cipher; |
| 264 | if (!ssl_cipher_get_evp |
| 265 | (s->session, &c, &hash, &mac_type, NULL, NULL, 0)) { |
| 266 | SSLerr(SSL_F_TLS13_SETUP_KEY_BLOCK, SSL_R_CIPHER_OR_HASH_UNAVAILABLE); |
| 267 | return 0; |
| 268 | } |
| 269 | |
| 270 | s->s3->tmp.new_sym_enc = c; |
| 271 | s->s3->tmp.new_hash = hash; |
| 272 | |
| 273 | return 1; |
| 274 | } |
| 275 | |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 276 | int tls13_change_cipher_state(SSL *s, int which) |
| 277 | { |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 278 | static const unsigned char client_handshake_traffic[] = |
| 279 | "client handshake traffic secret"; |
| 280 | static const unsigned char client_application_traffic[] = |
| 281 | "client application traffic secret"; |
| 282 | static const unsigned char server_handshake_traffic[] = |
| 283 | "server handshake traffic secret"; |
| 284 | static const unsigned char server_application_traffic[] = |
| 285 | "server application traffic secret"; |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 286 | unsigned char key[EVP_MAX_KEY_LENGTH]; |
| 287 | unsigned char iv[EVP_MAX_IV_LENGTH]; |
| 288 | unsigned char secret[EVP_MAX_MD_SIZE]; |
| 289 | unsigned char *insecret; |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 290 | unsigned char *finsecret = NULL; |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 291 | EVP_CIPHER_CTX *ciph_ctx; |
| 292 | const EVP_CIPHER *ciph = s->s3->tmp.new_sym_enc;; |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 293 | size_t ivlen, keylen, finsecretlen; |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 294 | const unsigned char *label; |
| 295 | size_t labellen; |
Matt Caswell | 6530c49 | 2016-11-23 15:38:32 +0000 | [diff] [blame^] | 296 | int ret = 0; |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 297 | |
| 298 | if (which & SSL3_CC_READ) { |
| 299 | if (s->enc_read_ctx != NULL) { |
| 300 | EVP_CIPHER_CTX_reset(s->enc_read_ctx); |
| 301 | } else { |
| 302 | s->enc_read_ctx = EVP_CIPHER_CTX_new(); |
| 303 | if (s->enc_read_ctx == NULL) { |
| 304 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); |
| 305 | goto err; |
| 306 | } |
| 307 | } |
| 308 | ciph_ctx = s->enc_read_ctx; |
| 309 | |
| 310 | RECORD_LAYER_reset_read_sequence(&s->rlayer); |
| 311 | } else { |
| 312 | if (s->enc_write_ctx != NULL) { |
| 313 | EVP_CIPHER_CTX_reset(s->enc_write_ctx); |
| 314 | } else { |
| 315 | s->enc_write_ctx = EVP_CIPHER_CTX_new(); |
| 316 | if (s->enc_write_ctx == NULL) { |
| 317 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_MALLOC_FAILURE); |
| 318 | goto err; |
| 319 | } |
| 320 | } |
| 321 | ciph_ctx = s->enc_write_ctx; |
| 322 | |
| 323 | RECORD_LAYER_reset_write_sequence(&s->rlayer); |
| 324 | } |
| 325 | |
| 326 | if (((which & SSL3_CC_CLIENT) && (which & SSL3_CC_WRITE)) |
| 327 | || ((which & SSL3_CC_SERVER) && (which & SSL3_CC_READ))) { |
| 328 | if (which & SSL3_CC_HANDSHAKE) { |
| 329 | insecret = s->handshake_secret; |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 330 | finsecret = s->client_finished_secret; |
| 331 | finsecretlen = sizeof(s->client_finished_secret); |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 332 | label = client_handshake_traffic; |
| 333 | labellen = sizeof(client_handshake_traffic) - 1; |
| 334 | } else { |
| 335 | insecret = s->session->master_key; |
| 336 | label = client_application_traffic; |
| 337 | labellen = sizeof(client_application_traffic) - 1; |
| 338 | } |
| 339 | } else { |
| 340 | if (which & SSL3_CC_HANDSHAKE) { |
| 341 | insecret = s->handshake_secret; |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 342 | finsecret = s->server_finished_secret; |
| 343 | finsecretlen = sizeof(s->server_finished_secret); |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 344 | label = server_handshake_traffic; |
| 345 | labellen = sizeof(server_handshake_traffic) - 1; |
| 346 | } else { |
| 347 | insecret = s->session->master_key; |
| 348 | label = server_application_traffic; |
| 349 | labellen = sizeof(server_application_traffic) - 1; |
| 350 | } |
| 351 | } |
| 352 | |
| 353 | if (!tls13_derive_secret(s, insecret, label, labellen, secret)) { |
| 354 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); |
| 355 | goto err; |
| 356 | } |
| 357 | |
| 358 | /* TODO(size_t): convert me */ |
| 359 | keylen = EVP_CIPHER_key_length(ciph); |
| 360 | |
| 361 | if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) |
| 362 | ivlen = EVP_GCM_TLS_FIXED_IV_LEN; |
| 363 | else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) |
| 364 | ivlen = EVP_CCM_TLS_FIXED_IV_LEN; |
| 365 | else |
| 366 | ivlen = EVP_CIPHER_iv_length(ciph); |
| 367 | |
| 368 | if (!tls13_derive_key(s, secret, key, keylen) |
Matt Caswell | 6484776 | 2016-11-11 00:20:19 +0000 | [diff] [blame] | 369 | || !tls13_derive_iv(s, secret, iv, ivlen) |
| 370 | || (finsecret != NULL && !tls13_derive_finishedkey(s, secret, |
| 371 | finsecret, |
| 372 | finsecretlen))) { |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 373 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_INTERNAL_ERROR); |
| 374 | goto err; |
| 375 | } |
| 376 | |
| 377 | if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) { |
| 378 | if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, NULL, |
| 379 | (which & SSL3_CC_WRITE)) |
| 380 | || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_GCM_SET_IV_FIXED, |
| 381 | (int)ivlen, iv)) { |
| 382 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); |
| 383 | goto err; |
| 384 | } |
| 385 | } else if (EVP_CIPHER_mode(ciph) == EVP_CIPH_CCM_MODE) { |
| 386 | int taglen; |
Matt Caswell | f5ca0b0 | 2016-11-21 12:10:35 +0000 | [diff] [blame] | 387 | |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 388 | if (s->s3->tmp.new_cipher->algorithm_enc |
| 389 | & (SSL_AES128CCM8 | SSL_AES256CCM8)) |
| 390 | taglen = 8; |
| 391 | else |
| 392 | taglen = 16; |
| 393 | if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, NULL, NULL, |
| 394 | (which & SSL3_CC_WRITE)) |
| 395 | || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_IVLEN, 12, |
| 396 | NULL) |
| 397 | || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_AEAD_SET_TAG, taglen, |
| 398 | NULL) |
| 399 | || !EVP_CIPHER_CTX_ctrl(ciph_ctx, EVP_CTRL_CCM_SET_IV_FIXED, |
| 400 | (int)ivlen, iv) |
| 401 | || !EVP_CipherInit_ex(ciph_ctx, NULL, NULL, key, NULL, -1)) { |
| 402 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); |
| 403 | goto err; |
| 404 | } |
| 405 | } else { |
| 406 | if (!EVP_CipherInit_ex(ciph_ctx, ciph, NULL, key, iv, |
| 407 | (which & SSL3_CC_WRITE))) { |
| 408 | SSLerr(SSL_F_TLS13_CHANGE_CIPHER_STATE, ERR_R_EVP_LIB); |
| 409 | goto err; |
| 410 | } |
| 411 | } |
| 412 | |
| 413 | #ifdef OPENSSL_SSL_TRACE_CRYPTO |
| 414 | if (s->msg_callback) { |
| 415 | int wh = which & SSL3_CC_WRITE ? TLS1_RT_CRYPTO_WRITE : 0; |
| 416 | |
| 417 | if (ciph->key_len) |
| 418 | s->msg_callback(2, s->version, wh | TLS1_RT_CRYPTO_KEY, |
| 419 | key, ciph->key_len, s, s->msg_callback_arg); |
| 420 | if (ivlen) { |
| 421 | if (EVP_CIPHER_mode(ciph) == EVP_CIPH_GCM_MODE) |
| 422 | wh |= TLS1_RT_CRYPTO_FIXED_IV; |
| 423 | else |
| 424 | wh |= TLS1_RT_CRYPTO_IV; |
| 425 | s->msg_callback(2, s->version, wh, iv, ivlen, s, |
| 426 | s->msg_callback_arg); |
| 427 | } |
| 428 | } |
| 429 | #endif |
| 430 | |
Matt Caswell | 6530c49 | 2016-11-23 15:38:32 +0000 | [diff] [blame^] | 431 | ret = 1; |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 432 | |
| 433 | err: |
| 434 | OPENSSL_cleanse(secret, sizeof(secret)); |
| 435 | OPENSSL_cleanse(key, sizeof(key)); |
| 436 | OPENSSL_cleanse(iv, sizeof(iv)); |
Matt Caswell | 6530c49 | 2016-11-23 15:38:32 +0000 | [diff] [blame^] | 437 | return ret; |
Matt Caswell | 0d9824c | 2016-11-08 23:20:31 +0000 | [diff] [blame] | 438 | } |