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