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