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