]>
Commit | Line | Data |
---|---|---|
0c13cdf8 | 1 | /* |
fecb3aae | 2 | * Copyright 2019-2022 The OpenSSL Project Authors. All Rights Reserved. |
0c13cdf8 MC |
3 | * |
4 | * Licensed under the Apache License 2.0 (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 <string.h> | |
11 | #include <openssl/core_names.h> | |
23c48d94 | 12 | #include <openssl/core_dispatch.h> |
0c13cdf8 MC |
13 | #include <openssl/rand.h> |
14 | #include <openssl/params.h> | |
15 | /* For TLS1_3_VERSION */ | |
16 | #include <openssl/ssl.h> | |
449bdf37 | 17 | #include "internal/nelem.h" |
0c13cdf8 | 18 | |
2b248f4e P |
19 | static OSSL_FUNC_keymgmt_import_fn xor_import; |
20 | static OSSL_FUNC_keymgmt_import_types_fn xor_import_types; | |
21 | static OSSL_FUNC_keymgmt_export_fn xor_export; | |
22 | static OSSL_FUNC_keymgmt_export_types_fn xor_export_types; | |
23 | ||
0c13cdf8 MC |
24 | int tls_provider_init(const OSSL_CORE_HANDLE *handle, |
25 | const OSSL_DISPATCH *in, | |
26 | const OSSL_DISPATCH **out, | |
27 | void **provctx); | |
28 | ||
29 | #define XOR_KEY_SIZE 32 | |
30 | ||
31 | /* | |
32 | * Top secret. This algorithm only works if no one knows what this number is. | |
33 | * Please don't tell anyone what it is. | |
34 | * | |
35 | * This algorithm is for testing only - don't really use it! | |
36 | */ | |
37 | static const unsigned char private_constant[XOR_KEY_SIZE] = { | |
38 | 0xd3, 0x6b, 0x54, 0xec, 0x5b, 0xac, 0x89, 0x96, 0x8c, 0x2c, 0x66, 0xa5, | |
39 | 0x67, 0x0d, 0xe3, 0xdd, 0x43, 0x69, 0xbc, 0x83, 0x3d, 0x60, 0xc7, 0xb8, | |
40 | 0x2b, 0x1c, 0x5a, 0xfd, 0xb5, 0xcd, 0xd0, 0xf8 | |
41 | }; | |
42 | ||
43 | typedef struct xorkey_st { | |
44 | unsigned char privkey[XOR_KEY_SIZE]; | |
45 | unsigned char pubkey[XOR_KEY_SIZE]; | |
46 | int hasprivkey; | |
47 | int haspubkey; | |
48 | } XORKEY; | |
49 | ||
5b70206c NT |
50 | |
51 | /* Key Management for the dummy XOR KEX and KEM algorithms */ | |
52 | ||
53 | static OSSL_FUNC_keymgmt_new_fn xor_newdata; | |
54 | static OSSL_FUNC_keymgmt_free_fn xor_freedata; | |
55 | static OSSL_FUNC_keymgmt_has_fn xor_has; | |
85fcc3fb | 56 | static OSSL_FUNC_keymgmt_dup_fn xor_dup; |
5b70206c NT |
57 | static OSSL_FUNC_keymgmt_gen_init_fn xor_gen_init; |
58 | static OSSL_FUNC_keymgmt_gen_set_params_fn xor_gen_set_params; | |
59 | static OSSL_FUNC_keymgmt_gen_settable_params_fn xor_gen_settable_params; | |
60 | static OSSL_FUNC_keymgmt_gen_fn xor_gen; | |
61 | static OSSL_FUNC_keymgmt_gen_cleanup_fn xor_gen_cleanup; | |
62 | static OSSL_FUNC_keymgmt_get_params_fn xor_get_params; | |
63 | static OSSL_FUNC_keymgmt_gettable_params_fn xor_gettable_params; | |
64 | static OSSL_FUNC_keymgmt_set_params_fn xor_set_params; | |
65 | static OSSL_FUNC_keymgmt_settable_params_fn xor_settable_params; | |
66 | ||
67 | /* | |
68 | * Dummy "XOR" Key Exchange algorithm. We just xor the private and public keys | |
69 | * together. Don't use this! | |
70 | */ | |
71 | ||
72 | static OSSL_FUNC_keyexch_newctx_fn xor_newctx; | |
73 | static OSSL_FUNC_keyexch_init_fn xor_init; | |
74 | static OSSL_FUNC_keyexch_set_peer_fn xor_set_peer; | |
75 | static OSSL_FUNC_keyexch_derive_fn xor_derive; | |
76 | static OSSL_FUNC_keyexch_freectx_fn xor_freectx; | |
77 | static OSSL_FUNC_keyexch_dupctx_fn xor_dupctx; | |
78 | ||
79 | /* | |
80 | * Dummy "XOR" Key Encapsulation Method. We just build a KEM over the xor KEX. | |
81 | * Don't use this! | |
82 | */ | |
83 | ||
84 | static OSSL_FUNC_kem_newctx_fn xor_newctx; | |
85 | static OSSL_FUNC_kem_freectx_fn xor_freectx; | |
86 | static OSSL_FUNC_kem_dupctx_fn xor_dupctx; | |
87 | static OSSL_FUNC_kem_encapsulate_init_fn xor_init; | |
88 | static OSSL_FUNC_kem_encapsulate_fn xor_encapsulate; | |
89 | static OSSL_FUNC_kem_decapsulate_init_fn xor_init; | |
90 | static OSSL_FUNC_kem_decapsulate_fn xor_decapsulate; | |
91 | ||
92 | ||
93 | /* | |
94 | * We define 2 dummy TLS groups called "xorgroup" and "xorkemgroup" for test | |
95 | * purposes | |
96 | */ | |
32fea070 NT |
97 | struct tls_group_st { |
98 | unsigned int group_id; /* for "tls-group-id", see provider-base(7) */ | |
99 | unsigned int secbits; | |
100 | unsigned int mintls; | |
101 | unsigned int maxtls; | |
102 | unsigned int mindtls; | |
103 | unsigned int maxdtls; | |
c1a74f59 | 104 | unsigned int is_kem; /* boolean */ |
32fea070 | 105 | }; |
0c13cdf8 | 106 | |
32fea070 NT |
107 | #define XORGROUP_NAME "xorgroup" |
108 | #define XORGROUP_NAME_INTERNAL "xorgroup-int" | |
109 | static struct tls_group_st xor_group = { | |
110 | 0, /* group_id, set by randomize_tls_group_id() */ | |
111 | 128, /* secbits */ | |
112 | TLS1_3_VERSION, /* mintls */ | |
113 | 0, /* maxtls */ | |
114 | -1, /* mindtls */ | |
c1a74f59 NT |
115 | -1, /* maxdtls */ |
116 | 0 /* is_kem */ | |
32fea070 | 117 | }; |
0c13cdf8 | 118 | |
ecff43e0 NT |
119 | #define XORKEMGROUP_NAME "xorkemgroup" |
120 | #define XORKEMGROUP_NAME_INTERNAL "xorkemgroup-int" | |
121 | static struct tls_group_st xor_kemgroup = { | |
122 | 0, /* group_id, set by randomize_tls_group_id() */ | |
123 | 128, /* secbits */ | |
124 | TLS1_3_VERSION, /* mintls */ | |
125 | 0, /* maxtls */ | |
126 | -1, /* mindtls */ | |
c1a74f59 NT |
127 | -1, /* maxdtls */ |
128 | 1 /* is_kem */ | |
ecff43e0 NT |
129 | }; |
130 | ||
0c13cdf8 MC |
131 | #define ALGORITHM "XOR" |
132 | ||
133 | static const OSSL_PARAM xor_group_params[] = { | |
134 | OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, | |
32fea070 | 135 | XORGROUP_NAME, sizeof(XORGROUP_NAME)), |
0c13cdf8 | 136 | OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, |
32fea070 NT |
137 | XORGROUP_NAME_INTERNAL, |
138 | sizeof(XORGROUP_NAME_INTERNAL)), | |
0c13cdf8 MC |
139 | OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, ALGORITHM, |
140 | sizeof(ALGORITHM)), | |
32fea070 NT |
141 | OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, &xor_group.group_id), |
142 | OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, | |
143 | &xor_group.secbits), | |
144 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, &xor_group.mintls), | |
145 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, &xor_group.maxtls), | |
146 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, &xor_group.mindtls), | |
147 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, &xor_group.maxdtls), | |
c1a74f59 | 148 | OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, &xor_group.is_kem), |
0c13cdf8 MC |
149 | OSSL_PARAM_END |
150 | }; | |
151 | ||
ecff43e0 NT |
152 | static const OSSL_PARAM xor_kemgroup_params[] = { |
153 | OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME, | |
154 | XORKEMGROUP_NAME, sizeof(XORKEMGROUP_NAME)), | |
155 | OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_NAME_INTERNAL, | |
156 | XORKEMGROUP_NAME_INTERNAL, | |
157 | sizeof(XORKEMGROUP_NAME_INTERNAL)), | |
158 | OSSL_PARAM_utf8_string(OSSL_CAPABILITY_TLS_GROUP_ALG, ALGORITHM, | |
159 | sizeof(ALGORITHM)), | |
160 | OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_ID, &xor_kemgroup.group_id), | |
161 | OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_SECURITY_BITS, | |
162 | &xor_kemgroup.secbits), | |
163 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_TLS, &xor_kemgroup.mintls), | |
164 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_TLS, &xor_kemgroup.maxtls), | |
165 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MIN_DTLS, &xor_kemgroup.mindtls), | |
166 | OSSL_PARAM_int(OSSL_CAPABILITY_TLS_GROUP_MAX_DTLS, &xor_kemgroup.maxdtls), | |
c1a74f59 | 167 | OSSL_PARAM_uint(OSSL_CAPABILITY_TLS_GROUP_IS_KEM, &xor_kemgroup.is_kem), |
ecff43e0 NT |
168 | OSSL_PARAM_END |
169 | }; | |
170 | ||
57e7401f MC |
171 | #define NUM_DUMMY_GROUPS 50 |
172 | static char *dummy_group_names[NUM_DUMMY_GROUPS]; | |
ecff43e0 | 173 | |
0c13cdf8 MC |
174 | static int tls_prov_get_capabilities(void *provctx, const char *capability, |
175 | OSSL_CALLBACK *cb, void *arg) | |
176 | { | |
57e7401f MC |
177 | int ret; |
178 | int i; | |
179 | const char *dummy_base = "dummy"; | |
180 | const size_t dummy_name_max_size = strlen(dummy_base) + 3; | |
181 | ||
182 | if (strcmp(capability, "TLS-GROUP") != 0) { | |
183 | /* We don't support this capability */ | |
184 | return 0; | |
185 | } | |
186 | ||
187 | /* Register our 2 groups */ | |
188 | ret = cb(xor_group_params, arg); | |
189 | ret &= cb(xor_kemgroup_params, arg); | |
190 | ||
191 | /* | |
192 | * Now register some dummy groups > GROUPLIST_INCREMENT (== 40) as defined | |
193 | * in ssl/t1_lib.c, to make sure we exercise the code paths for registering | |
194 | * large numbers of groups. | |
195 | */ | |
196 | ||
197 | for (i = 0; i < NUM_DUMMY_GROUPS; i++) { | |
198 | OSSL_PARAM dummygroup[OSSL_NELEM(xor_group_params)]; | |
199 | ||
200 | memcpy(dummygroup, xor_group_params, sizeof(xor_group_params)); | |
0c13cdf8 | 201 | |
57e7401f MC |
202 | /* Give the dummy group a unique name */ |
203 | if (dummy_group_names[i] == NULL) { | |
204 | dummy_group_names[i] = OPENSSL_zalloc(dummy_name_max_size); | |
205 | if (dummy_group_names[i] == NULL) | |
206 | return 0; | |
207 | BIO_snprintf(dummy_group_names[i], | |
208 | dummy_name_max_size, | |
209 | "%s%d", dummy_base, i); | |
210 | } | |
211 | dummygroup[0].data = dummy_group_names[i]; | |
212 | dummygroup[0].data_size = strlen(dummy_group_names[i]) + 1; | |
213 | ret &= cb(dummygroup, arg); | |
214 | } | |
215 | ||
216 | return ret; | |
0c13cdf8 MC |
217 | } |
218 | ||
219 | /* | |
220 | * Dummy "XOR" Key Exchange algorithm. We just xor the private and public keys | |
221 | * together. Don't use this! | |
222 | */ | |
223 | ||
0c13cdf8 MC |
224 | typedef struct { |
225 | XORKEY *key; | |
226 | XORKEY *peerkey; | |
5b70206c | 227 | void *provctx; |
0c13cdf8 MC |
228 | } PROV_XOR_CTX; |
229 | ||
230 | static void *xor_newctx(void *provctx) | |
231 | { | |
232 | PROV_XOR_CTX *pxorctx = OPENSSL_zalloc(sizeof(PROV_XOR_CTX)); | |
233 | ||
234 | if (pxorctx == NULL) | |
235 | return NULL; | |
236 | ||
5b70206c NT |
237 | pxorctx->provctx = provctx; |
238 | ||
0c13cdf8 MC |
239 | return pxorctx; |
240 | } | |
241 | ||
af6171b3 P |
242 | static int xor_init(void *vpxorctx, void *vkey, |
243 | ossl_unused const OSSL_PARAM params[]) | |
0c13cdf8 MC |
244 | { |
245 | PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx; | |
246 | ||
247 | if (pxorctx == NULL || vkey == NULL) | |
248 | return 0; | |
249 | pxorctx->key = vkey; | |
250 | return 1; | |
251 | } | |
252 | ||
253 | static int xor_set_peer(void *vpxorctx, void *vpeerkey) | |
254 | { | |
255 | PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx; | |
256 | ||
257 | if (pxorctx == NULL || vpeerkey == NULL) | |
258 | return 0; | |
259 | pxorctx->peerkey = vpeerkey; | |
260 | return 1; | |
261 | } | |
262 | ||
263 | static int xor_derive(void *vpxorctx, unsigned char *secret, size_t *secretlen, | |
264 | size_t outlen) | |
265 | { | |
266 | PROV_XOR_CTX *pxorctx = (PROV_XOR_CTX *)vpxorctx; | |
267 | int i; | |
268 | ||
269 | if (pxorctx->key == NULL || pxorctx->peerkey == NULL) | |
270 | return 0; | |
271 | ||
272 | *secretlen = XOR_KEY_SIZE; | |
273 | if (secret == NULL) | |
274 | return 1; | |
275 | ||
276 | if (outlen < XOR_KEY_SIZE) | |
277 | return 0; | |
278 | ||
279 | for (i = 0; i < XOR_KEY_SIZE; i++) | |
280 | secret[i] = pxorctx->key->privkey[i] ^ pxorctx->peerkey->pubkey[i]; | |
281 | ||
282 | return 1; | |
283 | } | |
284 | ||
285 | static void xor_freectx(void *pxorctx) | |
286 | { | |
287 | OPENSSL_free(pxorctx); | |
288 | } | |
289 | ||
290 | static void *xor_dupctx(void *vpxorctx) | |
291 | { | |
292 | PROV_XOR_CTX *srcctx = (PROV_XOR_CTX *)vpxorctx; | |
293 | PROV_XOR_CTX *dstctx; | |
294 | ||
295 | dstctx = OPENSSL_zalloc(sizeof(*srcctx)); | |
296 | if (dstctx == NULL) | |
297 | return NULL; | |
298 | ||
299 | *dstctx = *srcctx; | |
300 | ||
301 | return dstctx; | |
302 | } | |
303 | ||
304 | static const OSSL_DISPATCH xor_keyexch_functions[] = { | |
305 | { OSSL_FUNC_KEYEXCH_NEWCTX, (void (*)(void))xor_newctx }, | |
306 | { OSSL_FUNC_KEYEXCH_INIT, (void (*)(void))xor_init }, | |
307 | { OSSL_FUNC_KEYEXCH_DERIVE, (void (*)(void))xor_derive }, | |
308 | { OSSL_FUNC_KEYEXCH_SET_PEER, (void (*)(void))xor_set_peer }, | |
309 | { OSSL_FUNC_KEYEXCH_FREECTX, (void (*)(void))xor_freectx }, | |
310 | { OSSL_FUNC_KEYEXCH_DUPCTX, (void (*)(void))xor_dupctx }, | |
311 | { 0, NULL } | |
312 | }; | |
313 | ||
314 | static const OSSL_ALGORITHM tls_prov_keyexch[] = { | |
bfa6aaab | 315 | /* |
e304aa87 | 316 | * Obviously this is not FIPS approved, but in order to test in conjunction |
bfa6aaab MC |
317 | * with the FIPS provider we pretend that it is. |
318 | */ | |
319 | { "XOR", "provider=tls-provider,fips=yes", xor_keyexch_functions }, | |
0c13cdf8 MC |
320 | { NULL, NULL, NULL } |
321 | }; | |
322 | ||
5b70206c NT |
323 | /* |
324 | * Dummy "XOR" Key Encapsulation Method. We just build a KEM over the xor KEX. | |
325 | * Don't use this! | |
326 | */ | |
0c13cdf8 | 327 | |
5b70206c NT |
328 | static int xor_encapsulate(void *vpxorctx, |
329 | unsigned char *ct, size_t *ctlen, | |
330 | unsigned char *ss, size_t *sslen) | |
331 | { | |
332 | /* | |
333 | * We are building this around a KEX: | |
334 | * | |
335 | * 1. we generate ephemeral keypair | |
336 | * 2. we encode our ephemeral pubkey as the outgoing ct | |
337 | * 3. we derive using our ephemeral privkey in combination with the peer | |
338 | * pubkey from the ctx; the result is our ss. | |
339 | */ | |
340 | int rv = 0; | |
341 | void *genctx = NULL, *derivectx = NULL; | |
342 | XORKEY *ourkey = NULL; | |
343 | PROV_XOR_CTX *pxorctx = vpxorctx; | |
344 | ||
345 | if (ct == NULL || ss == NULL) { | |
346 | /* Just return sizes */ | |
347 | ||
348 | if (ctlen == NULL && sslen == NULL) | |
349 | return 0; | |
350 | if (ctlen != NULL) | |
351 | *ctlen = XOR_KEY_SIZE; | |
352 | if (sslen != NULL) | |
353 | *sslen = XOR_KEY_SIZE; | |
354 | return 1; | |
355 | } | |
356 | ||
357 | /* 1. Generate keypair */ | |
10ffdda4 | 358 | genctx = xor_gen_init(pxorctx->provctx, OSSL_KEYMGMT_SELECT_KEYPAIR, NULL); |
5b70206c NT |
359 | if (genctx == NULL) |
360 | goto end; | |
361 | ourkey = xor_gen(genctx, NULL, NULL); | |
362 | if (ourkey == NULL) | |
363 | goto end; | |
364 | ||
365 | /* 2. Encode ephemeral pubkey as ct */ | |
366 | memcpy(ct, ourkey->pubkey, XOR_KEY_SIZE); | |
367 | *ctlen = XOR_KEY_SIZE; | |
368 | ||
369 | /* 3. Derive ss via KEX */ | |
370 | derivectx = xor_newctx(pxorctx->provctx); | |
371 | if (derivectx == NULL | |
af6171b3 | 372 | || !xor_init(derivectx, ourkey, NULL) |
5b70206c NT |
373 | || !xor_set_peer(derivectx, pxorctx->key) |
374 | || !xor_derive(derivectx, ss, sslen, XOR_KEY_SIZE)) | |
375 | goto end; | |
376 | ||
377 | rv = 1; | |
378 | ||
379 | end: | |
380 | xor_gen_cleanup(genctx); | |
381 | xor_freedata(ourkey); | |
382 | xor_freectx(derivectx); | |
383 | return rv; | |
384 | } | |
385 | ||
386 | static int xor_decapsulate(void *vpxorctx, | |
387 | unsigned char *ss, size_t *sslen, | |
388 | const unsigned char *ct, size_t ctlen) | |
389 | { | |
390 | /* | |
391 | * We are building this around a KEX: | |
392 | * | |
393 | * - ct is our peer's pubkey | |
394 | * - decapsulate is just derive. | |
395 | */ | |
396 | int rv = 0; | |
397 | void *derivectx = NULL; | |
398 | XORKEY *peerkey = NULL; | |
399 | PROV_XOR_CTX *pxorctx = vpxorctx; | |
400 | ||
401 | if (ss == NULL) { | |
402 | /* Just return size */ | |
403 | if (sslen == NULL) | |
404 | return 0; | |
405 | *sslen = XOR_KEY_SIZE; | |
406 | return 1; | |
407 | } | |
408 | ||
409 | if (ctlen != XOR_KEY_SIZE) | |
410 | return 0; | |
411 | peerkey = xor_newdata(pxorctx->provctx); | |
412 | if (peerkey == NULL) | |
413 | goto end; | |
414 | memcpy(peerkey->pubkey, ct, XOR_KEY_SIZE); | |
415 | ||
416 | /* Derive ss via KEX */ | |
417 | derivectx = xor_newctx(pxorctx->provctx); | |
418 | if (derivectx == NULL | |
af6171b3 | 419 | || !xor_init(derivectx, pxorctx->key, NULL) |
5b70206c NT |
420 | || !xor_set_peer(derivectx, peerkey) |
421 | || !xor_derive(derivectx, ss, sslen, XOR_KEY_SIZE)) | |
422 | goto end; | |
423 | ||
424 | rv = 1; | |
425 | ||
426 | end: | |
427 | xor_freedata(peerkey); | |
428 | xor_freectx(derivectx); | |
429 | return rv; | |
430 | } | |
431 | ||
432 | static const OSSL_DISPATCH xor_kem_functions[] = { | |
433 | { OSSL_FUNC_KEM_NEWCTX, (void (*)(void))xor_newctx }, | |
434 | { OSSL_FUNC_KEM_FREECTX, (void (*)(void))xor_freectx }, | |
435 | { OSSL_FUNC_KEM_DUPCTX, (void (*)(void))xor_dupctx }, | |
436 | { OSSL_FUNC_KEM_ENCAPSULATE_INIT, (void (*)(void))xor_init }, | |
437 | { OSSL_FUNC_KEM_ENCAPSULATE, (void (*)(void))xor_encapsulate }, | |
438 | { OSSL_FUNC_KEM_DECAPSULATE_INIT, (void (*)(void))xor_init }, | |
439 | { OSSL_FUNC_KEM_DECAPSULATE, (void (*)(void))xor_decapsulate }, | |
440 | { 0, NULL } | |
441 | }; | |
442 | ||
443 | static const OSSL_ALGORITHM tls_prov_kem[] = { | |
444 | /* | |
e304aa87 | 445 | * Obviously this is not FIPS approved, but in order to test in conjunction |
5b70206c NT |
446 | * with the FIPS provider we pretend that it is. |
447 | */ | |
448 | { "XOR", "provider=tls-provider,fips=yes", xor_kem_functions }, | |
449 | { NULL, NULL, NULL } | |
450 | }; | |
451 | ||
452 | /* Key Management for the dummy XOR key exchange algorithm */ | |
0c13cdf8 MC |
453 | |
454 | static void *xor_newdata(void *provctx) | |
455 | { | |
456 | return OPENSSL_zalloc(sizeof(XORKEY)); | |
457 | } | |
458 | ||
459 | static void xor_freedata(void *keydata) | |
460 | { | |
461 | OPENSSL_free(keydata); | |
462 | } | |
463 | ||
3d914185 | 464 | static int xor_has(const void *vkey, int selection) |
0c13cdf8 | 465 | { |
3d914185 | 466 | const XORKEY *key = vkey; |
0c13cdf8 MC |
467 | int ok = 0; |
468 | ||
469 | if (key != NULL) { | |
470 | ok = 1; | |
471 | ||
472 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) | |
473 | ok = ok && key->haspubkey; | |
474 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) | |
475 | ok = ok && key->hasprivkey; | |
476 | } | |
477 | return ok; | |
478 | } | |
479 | ||
85fcc3fb | 480 | static void *xor_dup(const void *vfromkey, int selection) |
0c13cdf8 | 481 | { |
85fcc3fb | 482 | XORKEY *tokey = xor_newdata(NULL); |
0c13cdf8 MC |
483 | const XORKEY *fromkey = vfromkey; |
484 | int ok = 0; | |
485 | ||
486 | if (tokey != NULL && fromkey != NULL) { | |
487 | ok = 1; | |
488 | ||
489 | if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) { | |
490 | if (fromkey->haspubkey) { | |
491 | memcpy(tokey->pubkey, fromkey->pubkey, XOR_KEY_SIZE); | |
492 | tokey->haspubkey = 1; | |
493 | } else { | |
494 | tokey->haspubkey = 0; | |
495 | } | |
496 | } | |
497 | if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) { | |
498 | if (fromkey->hasprivkey) { | |
499 | memcpy(tokey->privkey, fromkey->privkey, XOR_KEY_SIZE); | |
500 | tokey->hasprivkey = 1; | |
501 | } else { | |
502 | tokey->hasprivkey = 0; | |
503 | } | |
504 | } | |
505 | } | |
85fcc3fb TM |
506 | if (!ok) { |
507 | xor_freedata(tokey); | |
508 | tokey = NULL; | |
509 | } | |
510 | return tokey; | |
0c13cdf8 MC |
511 | } |
512 | ||
513 | static ossl_inline int xor_get_params(void *vkey, OSSL_PARAM params[]) | |
514 | { | |
515 | XORKEY *key = vkey; | |
516 | OSSL_PARAM *p; | |
517 | ||
518 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL | |
519 | && !OSSL_PARAM_set_int(p, XOR_KEY_SIZE)) | |
520 | return 0; | |
521 | ||
522 | if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL | |
32fea070 | 523 | && !OSSL_PARAM_set_int(p, xor_group.secbits)) |
0c13cdf8 MC |
524 | return 0; |
525 | ||
5ac8fb58 MC |
526 | if ((p = OSSL_PARAM_locate(params, |
527 | OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL) { | |
0c13cdf8 MC |
528 | if (p->data_type != OSSL_PARAM_OCTET_STRING) |
529 | return 0; | |
530 | p->return_size = XOR_KEY_SIZE; | |
531 | if (p->data != NULL && p->data_size >= XOR_KEY_SIZE) | |
532 | memcpy(p->data, key->pubkey, XOR_KEY_SIZE); | |
533 | } | |
534 | ||
535 | return 1; | |
536 | } | |
537 | ||
538 | static const OSSL_PARAM xor_params[] = { | |
539 | OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL), | |
540 | OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL), | |
5ac8fb58 | 541 | OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), |
0c13cdf8 MC |
542 | OSSL_PARAM_END |
543 | }; | |
544 | ||
132b6160 | 545 | static const OSSL_PARAM *xor_gettable_params(void *provctx) |
0c13cdf8 MC |
546 | { |
547 | return xor_params; | |
548 | } | |
549 | ||
550 | static int xor_set_params(void *vkey, const OSSL_PARAM params[]) | |
551 | { | |
552 | XORKEY *key = vkey; | |
553 | const OSSL_PARAM *p; | |
554 | ||
5ac8fb58 | 555 | p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY); |
0c13cdf8 MC |
556 | if (p != NULL) { |
557 | if (p->data_type != OSSL_PARAM_OCTET_STRING | |
558 | || p->data_size != XOR_KEY_SIZE) | |
559 | return 0; | |
560 | memcpy(key->pubkey, p->data, XOR_KEY_SIZE); | |
561 | key->haspubkey = 1; | |
562 | } | |
563 | ||
564 | return 1; | |
565 | } | |
566 | ||
567 | static const OSSL_PARAM xor_known_settable_params[] = { | |
5ac8fb58 | 568 | OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0), |
0c13cdf8 MC |
569 | OSSL_PARAM_END |
570 | }; | |
571 | ||
132b6160 | 572 | static const OSSL_PARAM *xor_settable_params(void *provctx) |
0c13cdf8 MC |
573 | { |
574 | return xor_known_settable_params; | |
575 | } | |
576 | ||
577 | struct xor_gen_ctx { | |
578 | int selection; | |
b4250010 | 579 | OSSL_LIB_CTX *libctx; |
0c13cdf8 MC |
580 | }; |
581 | ||
10ffdda4 P |
582 | static void *xor_gen_init(void *provctx, int selection, |
583 | const OSSL_PARAM params[]) | |
0c13cdf8 MC |
584 | { |
585 | struct xor_gen_ctx *gctx = NULL; | |
586 | ||
587 | if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR | |
588 | | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS)) == 0) | |
589 | return NULL; | |
590 | ||
591 | if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) | |
592 | gctx->selection = selection; | |
593 | ||
b4250010 DMSP |
594 | /* Our provctx is really just an OSSL_LIB_CTX */ |
595 | gctx->libctx = (OSSL_LIB_CTX *)provctx; | |
0c13cdf8 | 596 | |
10ffdda4 P |
597 | if (!xor_gen_set_params(gctx, params)) { |
598 | OPENSSL_free(gctx); | |
599 | return NULL; | |
600 | } | |
0c13cdf8 MC |
601 | return gctx; |
602 | } | |
603 | ||
604 | static int xor_gen_set_params(void *genctx, const OSSL_PARAM params[]) | |
605 | { | |
606 | struct xor_gen_ctx *gctx = genctx; | |
607 | const OSSL_PARAM *p; | |
608 | ||
609 | if (gctx == NULL) | |
610 | return 0; | |
611 | ||
612 | p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); | |
613 | if (p != NULL) { | |
614 | if (p->data_type != OSSL_PARAM_UTF8_STRING | |
ecff43e0 NT |
615 | || (strcmp(p->data, XORGROUP_NAME_INTERNAL) != 0 |
616 | && strcmp(p->data, XORKEMGROUP_NAME_INTERNAL) != 0)) | |
0c13cdf8 MC |
617 | return 0; |
618 | } | |
619 | ||
620 | return 1; | |
621 | } | |
622 | ||
fb67126e TM |
623 | static const OSSL_PARAM *xor_gen_settable_params(ossl_unused void *genctx, |
624 | ossl_unused void *provctx) | |
0c13cdf8 MC |
625 | { |
626 | static OSSL_PARAM settable[] = { | |
627 | OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0), | |
628 | OSSL_PARAM_END | |
629 | }; | |
630 | return settable; | |
631 | } | |
632 | ||
633 | static void *xor_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg) | |
634 | { | |
635 | struct xor_gen_ctx *gctx = genctx; | |
636 | XORKEY *key = OPENSSL_zalloc(sizeof(*key)); | |
637 | size_t i; | |
638 | ||
639 | if (key == NULL) | |
640 | return NULL; | |
641 | ||
642 | if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) { | |
23e97567 | 643 | if (RAND_bytes_ex(gctx->libctx, key->privkey, XOR_KEY_SIZE, 0) <= 0) { |
0c13cdf8 MC |
644 | OPENSSL_free(key); |
645 | return NULL; | |
646 | } | |
647 | for (i = 0; i < XOR_KEY_SIZE; i++) | |
648 | key->pubkey[i] = key->privkey[i] ^ private_constant[i]; | |
649 | key->hasprivkey = 1; | |
650 | key->haspubkey = 1; | |
651 | } | |
652 | ||
653 | return key; | |
654 | } | |
655 | ||
2b248f4e P |
656 | /* IMPORT + EXPORT */ |
657 | ||
658 | static int xor_import(void *vkey, int select, const OSSL_PARAM params[]) | |
659 | { | |
660 | XORKEY *key = vkey; | |
661 | const OSSL_PARAM *param_priv_key, *param_pub_key; | |
662 | unsigned char privkey[XOR_KEY_SIZE]; | |
663 | unsigned char pubkey[XOR_KEY_SIZE]; | |
664 | void *pprivkey = privkey, *ppubkey = pubkey; | |
665 | size_t priv_len = 0, pub_len = 0; | |
666 | int res = 0; | |
667 | ||
668 | if (key == NULL || (select & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) | |
669 | return 0; | |
670 | ||
671 | memset(privkey, 0, sizeof(privkey)); | |
672 | memset(pubkey, 0, sizeof(pubkey)); | |
673 | param_priv_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PRIV_KEY); | |
674 | param_pub_key = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PUB_KEY); | |
675 | ||
676 | if ((param_priv_key != NULL | |
677 | && !OSSL_PARAM_get_octet_string(param_priv_key, &pprivkey, | |
678 | sizeof(privkey), &priv_len)) | |
679 | || (param_pub_key != NULL | |
680 | && !OSSL_PARAM_get_octet_string(param_pub_key, &ppubkey, | |
681 | sizeof(pubkey), &pub_len))) | |
682 | goto err; | |
683 | ||
684 | if (priv_len > 0) { | |
685 | memcpy(key->privkey, privkey, priv_len); | |
686 | key->hasprivkey = 1; | |
687 | } | |
688 | if (pub_len > 0) { | |
689 | memcpy(key->pubkey, pubkey, pub_len); | |
690 | key->haspubkey = 1; | |
691 | } | |
692 | res = 1; | |
693 | err: | |
694 | return res; | |
695 | } | |
696 | ||
697 | static int xor_export(void *vkey, int select, OSSL_CALLBACK *param_cb, | |
698 | void *cbarg) | |
699 | { | |
700 | XORKEY *key = vkey; | |
701 | OSSL_PARAM params[3], *p = params; | |
702 | ||
703 | if (key == NULL || (select & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0) | |
704 | return 0; | |
705 | ||
706 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, | |
707 | key->privkey, | |
708 | sizeof(key->privkey)); | |
709 | *p++ = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY, | |
710 | key->pubkey, sizeof(key->pubkey)); | |
711 | *p++ = OSSL_PARAM_construct_end(); | |
712 | ||
713 | return param_cb(params, cbarg); | |
714 | } | |
715 | ||
716 | static const OSSL_PARAM xor_key_types[] = { | |
717 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), | |
718 | OSSL_PARAM_BN(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0), | |
719 | OSSL_PARAM_END | |
720 | }; | |
721 | ||
722 | static const OSSL_PARAM *xor_import_types(int select) | |
723 | { | |
724 | return (select & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 ? xor_key_types : NULL; | |
725 | } | |
726 | ||
727 | static const OSSL_PARAM *xor_export_types(int select) | |
728 | { | |
729 | return (select & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0 ? xor_key_types : NULL; | |
730 | } | |
731 | ||
0c13cdf8 MC |
732 | static void xor_gen_cleanup(void *genctx) |
733 | { | |
734 | OPENSSL_free(genctx); | |
735 | } | |
736 | ||
737 | static const OSSL_DISPATCH xor_keymgmt_functions[] = { | |
738 | { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))xor_newdata }, | |
739 | { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))xor_gen_init }, | |
740 | { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))xor_gen_set_params }, | |
741 | { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, | |
742 | (void (*)(void))xor_gen_settable_params }, | |
743 | { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))xor_gen }, | |
744 | { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))xor_gen_cleanup }, | |
745 | { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))xor_get_params }, | |
746 | { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))xor_gettable_params }, | |
747 | { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))xor_set_params }, | |
748 | { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))xor_settable_params }, | |
749 | { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))xor_has }, | |
85fcc3fb | 750 | { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))xor_dup }, |
0c13cdf8 | 751 | { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))xor_freedata }, |
2b248f4e P |
752 | { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))xor_import }, |
753 | { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))xor_import_types }, | |
754 | { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))xor_export }, | |
755 | { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))xor_export_types }, | |
0c13cdf8 MC |
756 | { 0, NULL } |
757 | }; | |
758 | ||
759 | static const OSSL_ALGORITHM tls_prov_keymgmt[] = { | |
bfa6aaab | 760 | /* |
e304aa87 | 761 | * Obviously this is not FIPS approved, but in order to test in conjunction |
bfa6aaab MC |
762 | * with the FIPS provider we pretend that it is. |
763 | */ | |
764 | { "XOR", "provider=tls-provider,fips=yes", xor_keymgmt_functions }, | |
0c13cdf8 MC |
765 | { NULL, NULL, NULL } |
766 | }; | |
767 | ||
768 | static const OSSL_ALGORITHM *tls_prov_query(void *provctx, int operation_id, | |
769 | int *no_cache) | |
770 | { | |
771 | *no_cache = 0; | |
772 | switch (operation_id) { | |
773 | case OSSL_OP_KEYMGMT: | |
774 | return tls_prov_keymgmt; | |
775 | case OSSL_OP_KEYEXCH: | |
776 | return tls_prov_keyexch; | |
5b70206c NT |
777 | case OSSL_OP_KEM: |
778 | return tls_prov_kem; | |
0c13cdf8 MC |
779 | } |
780 | return NULL; | |
781 | } | |
782 | ||
57e7401f MC |
783 | static void tls_prov_teardown(void *provctx) |
784 | { | |
785 | int i; | |
786 | ||
787 | OSSL_LIB_CTX_free(provctx); | |
788 | ||
789 | for (i = 0; i < NUM_DUMMY_GROUPS; i++) { | |
790 | OPENSSL_free(dummy_group_names[i]); | |
791 | dummy_group_names[i] = NULL; | |
792 | } | |
793 | } | |
794 | ||
0c13cdf8 MC |
795 | /* Functions we provide to the core */ |
796 | static const OSSL_DISPATCH tls_prov_dispatch_table[] = { | |
57e7401f | 797 | { OSSL_FUNC_PROVIDER_TEARDOWN, (void (*)(void))tls_prov_teardown }, |
0c13cdf8 MC |
798 | { OSSL_FUNC_PROVIDER_QUERY_OPERATION, (void (*)(void))tls_prov_query }, |
799 | { OSSL_FUNC_PROVIDER_GET_CAPABILITIES, (void (*)(void))tls_prov_get_capabilities }, | |
800 | { 0, NULL } | |
801 | }; | |
802 | ||
32fea070 | 803 | static |
b4250010 | 804 | unsigned int randomize_tls_group_id(OSSL_LIB_CTX *libctx) |
0c13cdf8 | 805 | { |
0c13cdf8 MC |
806 | /* |
807 | * Randomise the group_id we're going to use to ensure we don't interoperate | |
808 | * with anything but ourselves. | |
809 | */ | |
32fea070 | 810 | unsigned int group_id; |
ecff43e0 NT |
811 | static unsigned int mem[10] = { 0 }; |
812 | static int in_mem = 0; | |
813 | int i; | |
32fea070 | 814 | |
ecff43e0 | 815 | retry: |
c9007bda | 816 | if (RAND_bytes_ex(libctx, (unsigned char *)&group_id, sizeof(group_id), 0) <= 0) |
0c13cdf8 MC |
817 | return 0; |
818 | /* | |
819 | * Ensure group_id is within the IANA Reserved for private use range | |
820 | * (65024-65279) | |
821 | */ | |
822 | group_id %= 65279 - 65024; | |
823 | group_id += 65024; | |
824 | ||
ecff43e0 NT |
825 | /* Ensure we did not already issue this group_id */ |
826 | for (i = 0; i < in_mem; i++) | |
827 | if (mem[i] == group_id) | |
828 | goto retry; | |
829 | ||
830 | /* Add this group_id to the list of ids issued by this function */ | |
831 | mem[in_mem++] = group_id; | |
832 | ||
32fea070 NT |
833 | return group_id; |
834 | } | |
835 | ||
836 | int tls_provider_init(const OSSL_CORE_HANDLE *handle, | |
837 | const OSSL_DISPATCH *in, | |
838 | const OSSL_DISPATCH **out, | |
839 | void **provctx) | |
840 | { | |
b4250010 | 841 | OSSL_LIB_CTX *libctx = OSSL_LIB_CTX_new(); |
32fea070 | 842 | |
8d215738 | 843 | if (libctx == NULL) |
844 | return 0; | |
845 | ||
32fea070 NT |
846 | *provctx = libctx; |
847 | ||
848 | /* | |
849 | * Randomise the group_id we're going to use to ensure we don't interoperate | |
850 | * with anything but ourselves. | |
851 | */ | |
852 | xor_group.group_id = randomize_tls_group_id(libctx); | |
ecff43e0 | 853 | xor_kemgroup.group_id = randomize_tls_group_id(libctx); |
32fea070 | 854 | |
0c13cdf8 MC |
855 | *out = tls_prov_dispatch_table; |
856 | return 1; | |
857 | } |