diff options
author | jsing <> | 2021-05-05 10:05:27 +0000 |
---|---|---|
committer | jsing <> | 2021-05-05 10:05:27 +0000 |
commit | 61ec18da26d0571bc925e8f60b9f8b60ce5ca1fb (patch) | |
tree | 07f64696b23229ab3deb8b5ecb2d4da5b3116265 /src/lib/libssl/tls12_key_schedule.c | |
parent | c157b585ad23f1585c90daafcbac523ea9685e35 (diff) | |
download | openbsd-61ec18da26d0571bc925e8f60b9f8b60ce5ca1fb.tar.gz openbsd-61ec18da26d0571bc925e8f60b9f8b60ce5ca1fb.tar.bz2 openbsd-61ec18da26d0571bc925e8f60b9f8b60ce5ca1fb.zip |
Rewrite TLSv1.2 key block handling.
For TLSv1.2 a single key block is generated, then partitioned into
individual secrets for use as IVs and keys. The previous implementation
splits this across two functions tls1_setup_key_block() and
tls1_change_cipher_state(), which means that the IV and key sizes have to
be known in multiple places.
This implementation generates and partitions the key block in a single
step, meaning that the secrets are then simply handed out when requested.
ok inoguchi@ tb@
Diffstat (limited to 'src/lib/libssl/tls12_key_schedule.c')
-rw-r--r-- | src/lib/libssl/tls12_key_schedule.c | 175 |
1 files changed, 175 insertions, 0 deletions
diff --git a/src/lib/libssl/tls12_key_schedule.c b/src/lib/libssl/tls12_key_schedule.c new file mode 100644 index 0000000000..c206460d95 --- /dev/null +++ b/src/lib/libssl/tls12_key_schedule.c | |||
@@ -0,0 +1,175 @@ | |||
1 | /* $OpenBSD: tls12_key_schedule.c,v 1.1 2021/05/05 10:05:27 jsing 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_locl.h" | ||
24 | |||
25 | struct tls12_key_block { | ||
26 | CBS client_write_mac_key; | ||
27 | CBS server_write_mac_key; | ||
28 | CBS client_write_key; | ||
29 | CBS server_write_key; | ||
30 | CBS client_write_iv; | ||
31 | CBS server_write_iv; | ||
32 | |||
33 | uint8_t *key_block; | ||
34 | size_t key_block_len; | ||
35 | }; | ||
36 | |||
37 | struct tls12_key_block * | ||
38 | tls12_key_block_new(void) | ||
39 | { | ||
40 | return calloc(1, sizeof(struct tls12_key_block)); | ||
41 | } | ||
42 | |||
43 | static void | ||
44 | tls12_key_block_clear(struct tls12_key_block *kb) | ||
45 | { | ||
46 | CBS_init(&kb->client_write_mac_key, NULL, 0); | ||
47 | CBS_init(&kb->server_write_mac_key, NULL, 0); | ||
48 | CBS_init(&kb->client_write_key, NULL, 0); | ||
49 | CBS_init(&kb->server_write_key, NULL, 0); | ||
50 | CBS_init(&kb->client_write_iv, NULL, 0); | ||
51 | CBS_init(&kb->server_write_iv, NULL, 0); | ||
52 | |||
53 | freezero(kb->key_block, kb->key_block_len); | ||
54 | kb->key_block = NULL; | ||
55 | kb->key_block_len = 0; | ||
56 | } | ||
57 | |||
58 | void | ||
59 | tls12_key_block_free(struct tls12_key_block *kb) | ||
60 | { | ||
61 | if (kb == NULL) | ||
62 | return; | ||
63 | |||
64 | tls12_key_block_clear(kb); | ||
65 | |||
66 | freezero(kb, sizeof(struct tls12_key_block)); | ||
67 | } | ||
68 | |||
69 | void | ||
70 | tls12_key_block_client_write(struct tls12_key_block *kb, CBS *mac_key, | ||
71 | CBS *key, CBS *iv) | ||
72 | { | ||
73 | CBS_dup(&kb->client_write_mac_key, mac_key); | ||
74 | CBS_dup(&kb->client_write_key, key); | ||
75 | CBS_dup(&kb->client_write_iv, iv); | ||
76 | } | ||
77 | |||
78 | void | ||
79 | tls12_key_block_server_write(struct tls12_key_block *kb, CBS *mac_key, | ||
80 | CBS *key, CBS *iv) | ||
81 | { | ||
82 | CBS_dup(&kb->server_write_mac_key, mac_key); | ||
83 | CBS_dup(&kb->server_write_key, key); | ||
84 | CBS_dup(&kb->server_write_iv, iv); | ||
85 | } | ||
86 | |||
87 | int | ||
88 | tls12_key_block_generate(struct tls12_key_block *kb, SSL *s, | ||
89 | const EVP_AEAD *aead, const EVP_CIPHER *cipher, const EVP_MD *mac_hash) | ||
90 | { | ||
91 | size_t mac_key_len = 0, key_len = 0, iv_len = 0; | ||
92 | uint8_t *key_block = NULL; | ||
93 | size_t key_block_len = 0; | ||
94 | CBS cbs; | ||
95 | |||
96 | /* | ||
97 | * Generate a TLSv1.2 key block and partition into individual secrets, | ||
98 | * as per RFC 5246 section 6.3. | ||
99 | */ | ||
100 | |||
101 | tls12_key_block_clear(kb); | ||
102 | |||
103 | /* Must have AEAD or cipher/MAC pair. */ | ||
104 | if (aead == NULL && (cipher == NULL || mac_hash == NULL)) | ||
105 | goto err; | ||
106 | |||
107 | if (aead != NULL) { | ||
108 | key_len = EVP_AEAD_key_length(aead); | ||
109 | |||
110 | /* AEAD fixed nonce length. */ | ||
111 | if (aead == EVP_aead_aes_128_gcm() || | ||
112 | aead == EVP_aead_aes_256_gcm()) | ||
113 | iv_len = 4; | ||
114 | else if (aead == EVP_aead_chacha20_poly1305()) | ||
115 | iv_len = 12; | ||
116 | else | ||
117 | goto err; | ||
118 | } else if (cipher != NULL && mac_hash != NULL) { | ||
119 | /* | ||
120 | * A negative integer return value will be detected via the | ||
121 | * EVP_MAX_* checks against the size_t variables below. | ||
122 | */ | ||
123 | mac_key_len = EVP_MD_size(mac_hash); | ||
124 | key_len = EVP_CIPHER_key_length(cipher); | ||
125 | iv_len = EVP_CIPHER_iv_length(cipher); | ||
126 | |||
127 | /* Special handling for GOST... */ | ||
128 | if (EVP_MD_type(mac_hash) == NID_id_Gost28147_89_MAC) | ||
129 | mac_key_len = 32; | ||
130 | } | ||
131 | |||
132 | if (mac_key_len > EVP_MAX_MD_SIZE) | ||
133 | goto err; | ||
134 | if (key_len > EVP_MAX_KEY_LENGTH) | ||
135 | goto err; | ||
136 | if (iv_len > EVP_MAX_IV_LENGTH) | ||
137 | goto err; | ||
138 | |||
139 | key_block_len = 2 * mac_key_len + 2 * key_len + 2 * iv_len; | ||
140 | if ((key_block = calloc(1, key_block_len)) == NULL) | ||
141 | goto err; | ||
142 | |||
143 | if (!tls1_generate_key_block(s, key_block, key_block_len)) | ||
144 | goto err; | ||
145 | |||
146 | kb->key_block = key_block; | ||
147 | kb->key_block_len = key_block_len; | ||
148 | key_block = NULL; | ||
149 | key_block_len = 0; | ||
150 | |||
151 | /* Partition key block into individual secrets. */ | ||
152 | CBS_init(&cbs, kb->key_block, kb->key_block_len); | ||
153 | if (!CBS_get_bytes(&cbs, &kb->client_write_mac_key, mac_key_len)) | ||
154 | goto err; | ||
155 | if (!CBS_get_bytes(&cbs, &kb->server_write_mac_key, mac_key_len)) | ||
156 | goto err; | ||
157 | if (!CBS_get_bytes(&cbs, &kb->client_write_key, key_len)) | ||
158 | goto err; | ||
159 | if (!CBS_get_bytes(&cbs, &kb->server_write_key, key_len)) | ||
160 | goto err; | ||
161 | if (!CBS_get_bytes(&cbs, &kb->client_write_iv, iv_len)) | ||
162 | goto err; | ||
163 | if (!CBS_get_bytes(&cbs, &kb->server_write_iv, iv_len)) | ||
164 | goto err; | ||
165 | if (CBS_len(&cbs) != 0) | ||
166 | goto err; | ||
167 | |||
168 | return 1; | ||
169 | |||
170 | err: | ||
171 | tls12_key_block_clear(kb); | ||
172 | freezero(key_block, key_block_len); | ||
173 | |||
174 | return 0; | ||
175 | } | ||