1 /* $OpenBSD: exportertest.c,v 1.3 2023/04/14 14:23:05 tb Exp $ */
2 /*
3  * Copyright (c) 2022 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 <openssl/err.h>
19 #include <openssl/ssl.h>
20 
21 #include <err.h>
22 #include <stdio.h>
23 #include <string.h>
24 
25 #include "ssl_local.h"
26 
27 static void
28 hexdump(const unsigned char *buf, size_t len)
29 {
30 	size_t i;
31 
32 	for (i = 1; i <= len; i++)
33 		fprintf(stderr, " 0x%02hhx,%s", buf[i - 1], i % 8 ? "" : "\n");
34 
35 	fprintf(stderr, "\n");
36 }
37 
38 struct exporter_test {
39 	uint16_t tls_version;
40 	unsigned int cipher_id;
41 	const uint8_t *label;
42 	size_t label_len;
43 	const uint8_t context_value[64];
44 	size_t context_value_len;
45 	int use_context;
46 	const uint8_t client_random[SSL3_RANDOM_SIZE];
47 	const uint8_t server_random[SSL3_RANDOM_SIZE];
48 	const uint8_t master_key[SSL_MAX_MASTER_KEY_LENGTH];
49 	const uint8_t shared_key[64];
50 	size_t shared_key_len;
51 	const uint8_t export[64];
52 	size_t export_len;
53 	int want_error;
54 };
55 
56 static const struct exporter_test exporter_tests[] = {
57 	{
58 		/* Valid export, no context - 32 bytes. */
59 		.tls_version = TLS1_2_VERSION,
60 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
61 		.label = "EXPERIMENTAL testing",
62 		.label_len = 20,
63 		.use_context = 0,
64 		.client_random = {
65 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
66 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
67 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
68 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
69 		},
70 		.server_random = {
71 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
72 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
73 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
74 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
75 		},
76 		.master_key = {
77 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
78 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
79 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
80 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
81 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
82 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
83 		},
84 		.export = {
85 			0x14, 0x08, 0x00, 0x9e, 0x6a, 0x67, 0x75, 0x4c,
86 			0xc4, 0xf3, 0x51, 0x57, 0x2f, 0x75, 0x0b, 0xf8,
87 			0x16, 0xfa, 0x61, 0x74, 0xd2, 0x12, 0x8f, 0x78,
88 			0x77, 0xf9, 0x8a, 0x3e, 0x58, 0x70, 0xf3, 0xd8,
89 		},
90 		.export_len = 32,
91 	},
92 	{
93 		/* Valid export, no context - 32 bytes. */
94 		.tls_version = TLS1_3_VERSION,
95 		.label = "EXPERIMENTAL testing",
96 		.label_len = 20,
97 		.use_context = 0,
98 		.shared_key = {
99 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
100 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
101 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
102 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
103 		},
104 		.shared_key_len = 32,
105 		.export = {
106 			0x69, 0xf4, 0xac, 0xec, 0x80, 0x67, 0xac, 0x5c,
107 			0xa6, 0x24, 0x47, 0xb1, 0x0f, 0xc8, 0xa1, 0x13,
108 			0x3b, 0x91, 0x33, 0x82, 0x97, 0x0a, 0xc0, 0xbf,
109 			0xac, 0x6d, 0x6b, 0x34, 0x20, 0xd3, 0x3a, 0x02,
110 		},
111 		.export_len = 32,
112 	},
113 	{
114 		/* Valid export, no context - 64 bytes. */
115 		.tls_version = TLS1_2_VERSION,
116 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
117 		.label = "EXPERIMENTAL testing",
118 		.label_len = 20,
119 		.use_context = 0,
120 		.client_random = {
121 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
122 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
123 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
124 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
125 		},
126 		.server_random = {
127 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
128 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
129 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
130 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
131 		},
132 		.master_key = {
133 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
134 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
135 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
136 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
137 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
138 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
139 		},
140 		.export = {
141 			0x14, 0x08, 0x00, 0x9e, 0x6a, 0x67, 0x75, 0x4c,
142 			0xc4, 0xf3, 0x51, 0x57, 0x2f, 0x75, 0x0b, 0xf8,
143 			0x16, 0xfa, 0x61, 0x74, 0xd2, 0x12, 0x8f, 0x78,
144 			0x77, 0xf9, 0x8a, 0x3e, 0x58, 0x70, 0xf3, 0xd8,
145 			0xe8, 0xd2, 0xb7, 0xcd, 0xbc, 0x37, 0xdf, 0x16,
146 			0x12, 0xf1, 0xe8, 0xb2, 0x62, 0x79, 0x91, 0x45,
147 			0x77, 0xe0, 0x68, 0x6d, 0xd5, 0x31, 0x54, 0x55,
148 			0x22, 0x63, 0xc0, 0x36, 0x31, 0x07, 0xda, 0x33,
149 		},
150 		.export_len = 64,
151 	},
152 	{
153 		/* Valid export, no context - 64 bytes. */
154 		.tls_version = TLS1_3_VERSION,
155 		.label = "EXPERIMENTAL testing",
156 		.label_len = 20,
157 		.use_context = 0,
158 		.shared_key = {
159 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
160 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
161 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
162 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
163 		},
164 		.shared_key_len = 32,
165 		.export = {
166 			0x77, 0x15, 0xe2, 0x07, 0x65, 0x64, 0x3b, 0x14,
167 			0x38, 0xcb, 0x73, 0x93, 0xda, 0x70, 0xfa, 0x86,
168 			0x2c, 0x34, 0xcc, 0x94, 0x52, 0xc2, 0xd3, 0xb4,
169 			0x59, 0x2c, 0xc8, 0x05, 0x70, 0xfe, 0x48, 0x61,
170 			0xd3, 0xea, 0x57, 0x66, 0xa9, 0x66, 0x2f, 0x4a,
171 			0x35, 0xc9, 0x88, 0x86, 0x28, 0x52, 0xe3, 0x64,
172 			0x5e, 0xf9, 0x28, 0x53, 0x8a, 0x3a, 0x92, 0x92,
173 			0x40, 0x8c, 0x89, 0x17, 0x59, 0xd0, 0xd0, 0x82,
174 		},
175 		.export_len = 64,
176 	},
177 	{
178 		/* Valid export, zero length context - 32 bytes. */
179 		.tls_version = TLS1_2_VERSION,
180 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
181 		.label = "EXPERIMENTAL testing",
182 		.label_len = 20,
183 		.context_value_len = 0,
184 		.use_context = 1,
185 		.client_random = {
186 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
187 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
188 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
189 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
190 		},
191 		.server_random = {
192 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
193 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
194 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
195 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
196 		},
197 		.master_key = {
198 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
199 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
200 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
201 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
202 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
203 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
204 		},
205 		.export = {
206 			0xdb, 0xc9, 0xdf, 0x7c, 0x04, 0x39, 0xdd, 0x23,
207 			0xc3, 0x68, 0xdc, 0xf3, 0x04, 0xcf, 0x4c, 0x4d,
208 			0x86, 0x5b, 0xe6, 0x48, 0xc5, 0x6d, 0xe5, 0x1e,
209 			0xea, 0xc5, 0xe4, 0x00, 0x27, 0x72, 0xda, 0xb6,
210 		},
211 		.export_len = 32,
212 	},
213 	{
214 		/* Valid export, zero length context - 32 bytes. */
215 		.tls_version = TLS1_3_VERSION,
216 		.label = "EXPERIMENTAL testing",
217 		.label_len = 20,
218 		.context_value_len = 0,
219 		.use_context = 1,
220 		.shared_key = {
221 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
222 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
223 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
224 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
225 		},
226 		.shared_key_len = 32,
227 		.export = {
228 			0x69, 0xf4, 0xac, 0xec, 0x80, 0x67, 0xac, 0x5c,
229 			0xa6, 0x24, 0x47, 0xb1, 0x0f, 0xc8, 0xa1, 0x13,
230 			0x3b, 0x91, 0x33, 0x82, 0x97, 0x0a, 0xc0, 0xbf,
231 			0xac, 0x6d, 0x6b, 0x34, 0x20, 0xd3, 0x3a, 0x02,
232 		},
233 		.export_len = 32,
234 	},
235 	{
236 		/* Valid export, with context value - 32 bytes. */
237 		.tls_version = TLS1_2_VERSION,
238 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
239 		.label = "EXPERIMENTAL testing",
240 		.label_len = 20,
241 		.context_value = {
242 			0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
243 			0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
244 		},
245 		.context_value_len = 16,
246 		.use_context = 1,
247 		.client_random = {
248 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
249 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
250 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
251 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
252 		},
253 		.server_random = {
254 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
255 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
256 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
257 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
258 		},
259 		.master_key = {
260 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
261 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
262 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
263 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
264 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
265 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
266 		},
267 		.export = {
268 			0x0e, 0xb4, 0xd1, 0x3a, 0x0e, 0x24, 0xab, 0x0d,
269 			0x4c, 0x48, 0x35, 0x25, 0xf6, 0x4d, 0xa2, 0x9b,
270 			0xaa, 0x1d, 0xbc, 0x54, 0x7e, 0xb0, 0x3c, 0x4b,
271 			0x07, 0x04, 0x9c, 0x7c, 0x06, 0xa7, 0xea, 0x70,
272 		},
273 		.export_len = 32,
274 	},
275 	{
276 		/* Valid export, with context value - 32 bytes. */
277 		.tls_version = TLS1_3_VERSION,
278 		.label = "EXPERIMENTAL testing",
279 		.label_len = 20,
280 		.context_value = {
281 			0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
282 			0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
283 		},
284 		.context_value_len = 16,
285 		.use_context = 1,
286 		.shared_key = {
287 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
288 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
289 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
290 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
291 		},
292 		.shared_key_len = 32,
293 		.export = {
294 			0x34, 0xb8, 0x00, 0x6a, 0xb2, 0x62, 0xab, 0xea,
295 			0xc7, 0x2b, 0x15, 0xa0, 0x85, 0xda, 0xaa, 0xa5,
296 			0x12, 0x85, 0xbf, 0x4a, 0xa4, 0x71, 0x42, 0xc8,
297 			0xd4, 0xa6, 0x66, 0x18, 0xc6, 0xc9, 0x26, 0x6f,
298 		},
299 		.export_len = 32,
300 	},
301 	{
302 		/* Valid export, with different label - 32 bytes. */
303 		.tls_version = TLS1_2_VERSION,
304 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
305 		.label = "EXPERIMENTAL more testing",
306 		.label_len = 20,
307 		.context_value = {
308 			0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
309 			0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
310 		},
311 		.context_value_len = 16,
312 		.use_context = 1,
313 		.client_random = {
314 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
315 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
316 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
317 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
318 		},
319 		.server_random = {
320 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
321 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
322 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
323 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
324 		},
325 		.master_key = {
326 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
327 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
328 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
329 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
330 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
331 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
332 		},
333 		.export = {
334 			0xb0, 0xb6, 0x45, 0xdd, 0x30, 0x76, 0xf0, 0x57,
335 			0x22, 0x31, 0xbb, 0x8d, 0xe1, 0xf9, 0xe3, 0xed,
336 			0xae, 0x74, 0x6f, 0x40, 0x94, 0xf6, 0xc2, 0xfc,
337 			0x21, 0xff, 0xf7, 0x00, 0x86, 0x54, 0xb6, 0x06,
338 		},
339 		.export_len = 32,
340 	},
341 	{
342 		/* Valid export, with different label - 32 bytes. */
343 		.tls_version = TLS1_3_VERSION,
344 		.label = "EXPERIMENTAL more testing",
345 		.label_len = 20,
346 		.context_value = {
347 			0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
348 			0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
349 		},
350 		.context_value_len = 16,
351 		.use_context = 1,
352 		.shared_key = {
353 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
354 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
355 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
356 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
357 		},
358 		.shared_key_len = 32,
359 		.export = {
360 			0x18, 0x4e, 0x65, 0x3c, 0x91, 0x5d, 0x6a, 0xc3,
361 			0x25, 0x38, 0xbe, 0x6e, 0xca, 0x12, 0x54, 0x76,
362 			0x5a, 0x84, 0xf7, 0x19, 0x44, 0x78, 0xec, 0xc0,
363 			0x83, 0xf6, 0x22, 0xb8, 0x86, 0x31, 0xe9, 0x2e,
364 		},
365 		.export_len = 32,
366 	},
367 	{
368 		/* Invalid - illegal label. */
369 		.tls_version = TLS1_2_VERSION,
370 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
371 		.label = TLS_MD_CLIENT_FINISH_CONST,
372 		.label_len = TLS_MD_CLIENT_FINISH_CONST_SIZE,
373 		.use_context = 0,
374 		.client_random = {
375 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
376 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
377 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
378 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
379 		},
380 		.server_random = {
381 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
382 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
383 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
384 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
385 		},
386 		.master_key = {
387 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
388 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
389 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
390 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
391 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
392 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
393 		},
394 		.export_len = 32,
395 		.want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL,
396 	},
397 	{
398 		/* Invalid - illegal label. */
399 		.tls_version = TLS1_2_VERSION,
400 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
401 		.label = TLS_MD_SERVER_FINISH_CONST,
402 		.label_len = TLS_MD_SERVER_FINISH_CONST_SIZE,
403 		.use_context = 0,
404 		.client_random = {
405 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
406 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
407 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
408 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
409 		},
410 		.server_random = {
411 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
412 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
413 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
414 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
415 		},
416 		.master_key = {
417 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
418 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
419 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
420 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
421 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
422 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
423 		},
424 		.export_len = 32,
425 		.want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL,
426 	},
427 	{
428 		/* Invalid - illegal label. */
429 		.tls_version = TLS1_2_VERSION,
430 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
431 		.label = TLS_MD_KEY_EXPANSION_CONST,
432 		.label_len = TLS_MD_KEY_EXPANSION_CONST_SIZE,
433 		.use_context = 0,
434 		.client_random = {
435 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
436 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
437 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
438 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
439 		},
440 		.server_random = {
441 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
442 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
443 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
444 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
445 		},
446 		.master_key = {
447 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
448 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
449 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
450 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
451 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
452 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
453 		},
454 		.export_len = 32,
455 		.want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL,
456 	},
457 	{
458 		/* Invalid - illegal label. */
459 		.tls_version = TLS1_2_VERSION,
460 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
461 		.label = TLS_MD_MASTER_SECRET_CONST,
462 		.label_len = TLS_MD_MASTER_SECRET_CONST_SIZE,
463 		.use_context = 0,
464 		.client_random = {
465 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
466 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
467 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
468 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
469 		},
470 		.server_random = {
471 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
472 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
473 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
474 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
475 		},
476 		.master_key = {
477 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
478 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
479 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
480 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
481 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
482 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
483 		},
484 		.export_len = 32,
485 		.want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL,
486 	},
487 	{
488 		/* Invalid - illegal label, split over label and seed. */
489 		.tls_version = TLS1_2_VERSION,
490 		.cipher_id = TLS1_CK_ECDHE_RSA_CHACHA20_POLY1305,
491 		.label = "master ",
492 		.label_len = 7,
493 		.use_context = 0,
494 		.client_random = {
495 			 's',  'e',  'c',  'r',  'e',  't', 0x06, 0x07,
496 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
497 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
498 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
499 		},
500 		.server_random = {
501 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
502 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
503 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
504 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
505 		},
506 		.master_key = {
507 			0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
508 			0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
509 			0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
510 			0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
511 			0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
512 			0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
513 		},
514 		.export = {
515 			0x40, 0x70, 0xba, 0xfa, 0xba, 0x44, 0x74, 0x93,
516 			0xa2, 0x43, 0x18, 0x07, 0xa4, 0x4f, 0x3f, 0xda,
517 			0x88, 0x7b, 0x0e, 0x79, 0x70, 0xcf, 0xdb, 0x91,
518 			0xfc, 0x3f, 0x96, 0x78, 0x6b, 0x50, 0xe3, 0xa6,
519 		},
520 		.export_len = 32,
521 		.want_error = SSL_R_TLS_ILLEGAL_EXPORTER_LABEL,
522 	},
523 };
524 
525 #define N_EXPORTER_TESTS (sizeof(exporter_tests) / sizeof(exporter_tests[0]))
526 
527 static int
528 exporter_test(size_t test_no, const struct exporter_test *et)
529 {
530 	struct tls13_secret tls13_context = { .data = "", .len = 0 };
531 	struct tls13_ctx *tls13_ctx;
532 	struct tls13_secrets *tls13_secrets;
533 	SSL_SESSION *ssl_session = NULL;
534 	SSL_CTX *ssl_ctx = NULL;
535 	SSL *ssl = NULL;
536 	uint8_t export[256];
537 	int err, ret;
538 	int failed = 1;
539 
540 	memset(export, 0, sizeof(export));
541 
542 	if ((ssl_ctx = SSL_CTX_new(TLS_method())) == NULL) {
543 		fprintf(stderr, "FAIL: SSL_CTX_new\n");
544 		goto failure;
545 	}
546 	if ((ssl = SSL_new(ssl_ctx)) == NULL) {
547 		fprintf(stderr, "FAIL: SSL_new\n");
548 		goto failure;
549 	}
550 	if ((ssl_session = SSL_SESSION_new()) == NULL) {
551 		fprintf(stderr, "FAIL: SSL_SESSION_new\n");
552 		goto failure;
553 	}
554 
555 	ssl_session->ssl_version = et->tls_version;
556 
557 	if (!SSL_set_session(ssl, ssl_session)) {
558 		fprintf(stderr, "FAIL: SSL_set_session\n");
559 		goto failure;
560 	}
561 
562 	memcpy(ssl_session->master_key, et->master_key,
563 	    sizeof(ssl_session->master_key));
564 	memcpy(ssl->s3->client_random, et->client_random,
565 	    sizeof(ssl->s3->client_random));
566 	memcpy(ssl->s3->server_random, et->server_random,
567 	    sizeof(ssl->s3->server_random));
568 
569 	if (et->tls_version >= TLS1_3_VERSION) {
570 		if ((tls13_ctx = tls13_ctx_new(TLS13_HS_CLIENT, ssl)) == NULL) {
571 			fprintf(stderr, "FAIL: tls13_ctx_new\n");
572 			goto failure;
573 		}
574 		ssl->tls13 = tls13_ctx;
575 
576 		if ((tls13_secrets = tls13_secrets_create(EVP_sha384(),
577 		    0)) == NULL) {
578 			fprintf(stderr, "FAIL: tls13_secrets_create\n");
579 			goto failure;
580 		}
581 		ssl->s3->hs.tls13.secrets = tls13_secrets;
582 
583 		if (!tls13_derive_early_secrets(tls13_secrets,
584 		    tls13_secrets->zeros.data, tls13_secrets->zeros.len,
585 		    &tls13_context)) {
586 			fprintf(stderr, "FAIL: tls13_derive_early_secrets\n");
587 			goto failure;
588 		}
589 		if (!tls13_derive_handshake_secrets(tls13_secrets, et->shared_key,
590 		    et->shared_key_len, &tls13_context)) {
591 			fprintf(stderr, "FAIL: tls13_derive_handshake_secrets\n");
592 			goto failure;
593 		}
594 		if (!tls13_derive_application_secrets(tls13_secrets,
595 		    &tls13_context)) {
596 			fprintf(stderr, "FAIL: tls13_derive_early_secrets\n");
597 			goto failure;
598 		}
599 
600 		tls13_ctx->handshake_completed = 1;
601 	}
602 
603 	ssl->s3->hs.state = SSL_ST_OK;
604 	ssl->s3->hs.negotiated_tls_version = et->tls_version;
605 	ssl->s3->hs.cipher = SSL_CIPHER_get_by_id(et->cipher_id);
606 
607 	ret = SSL_export_keying_material(ssl, export, et->export_len, et->label,
608 	    et->label_len, et->context_value, et->context_value_len,
609 	    et->use_context);
610 
611 	if (et->want_error != 0) {
612 		if (ret) {
613 			fprintf(stderr, "FAIL: test %zu - "
614 			    "SSL_export_keying_material() succeeded, want "
615 			    "error\n", test_no);
616 			goto failure;
617 		}
618 
619 		err = ERR_peek_error();
620 		if (ERR_GET_REASON(err) != et->want_error) {
621 			fprintf(stderr, "FAIL: %zu - got error reason %d, "
622 			    "want %d\n", test_no, ERR_GET_REASON(err),
623 			    et->want_error);
624 			goto failure;
625 		}
626 	} else {
627 		if (!ret) {
628 			fprintf(stderr, "FAIL: test %zu - "
629 			    "SSL_export_keying_material() failed\n", test_no);
630 			ERR_print_errors_fp(stderr);
631 			goto failure;
632 		}
633 
634 		if (memcmp(et->export, export, et->export_len) != 0) {
635 			fprintf(stderr, "FAIL: test %zu\n", test_no);
636 			fprintf(stderr, "Got export:\n");
637 			hexdump(export, et->export_len);
638 			fprintf(stderr, "Want export:\n");
639 			hexdump(et->export, et->export_len);
640 			goto failure;
641 		}
642 	}
643 
644 	failed = 0;
645 
646  failure:
647 	SSL_SESSION_free(ssl_session);
648 	SSL_CTX_free(ssl_ctx);
649 	SSL_free(ssl);
650 
651 	return failed;
652 }
653 
654 int
655 main(int argc, char **argv)
656 {
657 	int failed = 0;
658 	size_t i;
659 
660 	for (i = 0; i < N_EXPORTER_TESTS; i++)
661 		failed |= exporter_test(i, &exporter_tests[i]);
662 
663 	return (failed);
664 }
665