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