1e1051a39Sopenharmony_ci/*
2e1051a39Sopenharmony_ci * Copyright 2020-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 <assert.h>
11e1051a39Sopenharmony_ci#include <string.h>
12e1051a39Sopenharmony_ci#include <openssl/core_dispatch.h>
13e1051a39Sopenharmony_ci#include <openssl/core_names.h>
14e1051a39Sopenharmony_ci#include <openssl/params.h>
15e1051a39Sopenharmony_ci#include <openssl/err.h>
16e1051a39Sopenharmony_ci#include <openssl/proverr.h>
17e1051a39Sopenharmony_ci#include <openssl/evp.h>
18e1051a39Sopenharmony_ci#include <openssl/rand.h>
19e1051a39Sopenharmony_ci#include "internal/param_build_set.h"
20e1051a39Sopenharmony_ci#include <openssl/param_build.h>
21e1051a39Sopenharmony_ci#include "crypto/ecx.h"
22e1051a39Sopenharmony_ci#include "prov/implementations.h"
23e1051a39Sopenharmony_ci#include "prov/providercommon.h"
24e1051a39Sopenharmony_ci#include "prov/provider_ctx.h"
25e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
26e1051a39Sopenharmony_ci# include "s390x_arch.h"
27e1051a39Sopenharmony_ci# include <openssl/sha.h>   /* For SHA512_DIGEST_LENGTH */
28e1051a39Sopenharmony_ci#endif
29e1051a39Sopenharmony_ci
30e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_new_fn x25519_new_key;
31e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_new_fn x448_new_key;
32e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
33e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_new_fn ed448_new_key;
34e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
35e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
36e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
37e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
38e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_fn x25519_gen;
39e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_fn x448_gen;
40e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
41e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_fn ed448_gen;
42e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
43e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
44e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
45e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_load_fn ecx_load;
46e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
47e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
48e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
49e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
50e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
51e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
52e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
53e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
54e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
55e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
56e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
57e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
58e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
59e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
60e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
61e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
62e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_has_fn ecx_has;
63e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_match_fn ecx_match;
64e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_validate_fn x25519_validate;
65e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_validate_fn x448_validate;
66e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
67e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_validate_fn ed448_validate;
68e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_import_fn ecx_import;
69e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
70e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_export_fn ecx_export;
71e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
72e1051a39Sopenharmony_cistatic OSSL_FUNC_keymgmt_dup_fn ecx_dup;
73e1051a39Sopenharmony_ci
74e1051a39Sopenharmony_ci#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
75e1051a39Sopenharmony_ci
76e1051a39Sopenharmony_cistruct ecx_gen_ctx {
77e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx;
78e1051a39Sopenharmony_ci    char *propq;
79e1051a39Sopenharmony_ci    ECX_KEY_TYPE type;
80e1051a39Sopenharmony_ci    int selection;
81e1051a39Sopenharmony_ci};
82e1051a39Sopenharmony_ci
83e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
84e1051a39Sopenharmony_cistatic void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
85e1051a39Sopenharmony_cistatic void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
86e1051a39Sopenharmony_cistatic void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
87e1051a39Sopenharmony_cistatic void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
88e1051a39Sopenharmony_ci#endif
89e1051a39Sopenharmony_ci
90e1051a39Sopenharmony_cistatic void *x25519_new_key(void *provctx)
91e1051a39Sopenharmony_ci{
92e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
93e1051a39Sopenharmony_ci        return 0;
94e1051a39Sopenharmony_ci    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
95e1051a39Sopenharmony_ci                            NULL);
96e1051a39Sopenharmony_ci}
97e1051a39Sopenharmony_ci
98e1051a39Sopenharmony_cistatic void *x448_new_key(void *provctx)
99e1051a39Sopenharmony_ci{
100e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
101e1051a39Sopenharmony_ci        return 0;
102e1051a39Sopenharmony_ci    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
103e1051a39Sopenharmony_ci                            NULL);
104e1051a39Sopenharmony_ci}
105e1051a39Sopenharmony_ci
106e1051a39Sopenharmony_cistatic void *ed25519_new_key(void *provctx)
107e1051a39Sopenharmony_ci{
108e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
109e1051a39Sopenharmony_ci        return 0;
110e1051a39Sopenharmony_ci    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
111e1051a39Sopenharmony_ci                            NULL);
112e1051a39Sopenharmony_ci}
113e1051a39Sopenharmony_ci
114e1051a39Sopenharmony_cistatic void *ed448_new_key(void *provctx)
115e1051a39Sopenharmony_ci{
116e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
117e1051a39Sopenharmony_ci        return 0;
118e1051a39Sopenharmony_ci    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
119e1051a39Sopenharmony_ci                            NULL);
120e1051a39Sopenharmony_ci}
121e1051a39Sopenharmony_ci
122e1051a39Sopenharmony_cistatic int ecx_has(const void *keydata, int selection)
123e1051a39Sopenharmony_ci{
124e1051a39Sopenharmony_ci    const ECX_KEY *key = keydata;
125e1051a39Sopenharmony_ci    int ok = 0;
126e1051a39Sopenharmony_ci
127e1051a39Sopenharmony_ci    if (ossl_prov_is_running() && key != NULL) {
128e1051a39Sopenharmony_ci        /*
129e1051a39Sopenharmony_ci         * ECX keys always have all the parameters they need (i.e. none).
130e1051a39Sopenharmony_ci         * Therefore we always return with 1, if asked about parameters.
131e1051a39Sopenharmony_ci         */
132e1051a39Sopenharmony_ci        ok = 1;
133e1051a39Sopenharmony_ci
134e1051a39Sopenharmony_ci        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
135e1051a39Sopenharmony_ci            ok = ok && key->haspubkey;
136e1051a39Sopenharmony_ci
137e1051a39Sopenharmony_ci        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
138e1051a39Sopenharmony_ci            ok = ok && key->privkey != NULL;
139e1051a39Sopenharmony_ci    }
140e1051a39Sopenharmony_ci    return ok;
141e1051a39Sopenharmony_ci}
142e1051a39Sopenharmony_ci
143e1051a39Sopenharmony_cistatic int ecx_match(const void *keydata1, const void *keydata2, int selection)
144e1051a39Sopenharmony_ci{
145e1051a39Sopenharmony_ci    const ECX_KEY *key1 = keydata1;
146e1051a39Sopenharmony_ci    const ECX_KEY *key2 = keydata2;
147e1051a39Sopenharmony_ci    int ok = 1;
148e1051a39Sopenharmony_ci
149e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
150e1051a39Sopenharmony_ci        return 0;
151e1051a39Sopenharmony_ci
152e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
153e1051a39Sopenharmony_ci        ok = ok && key1->type == key2->type;
154e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
155e1051a39Sopenharmony_ci        int key_checked = 0;
156e1051a39Sopenharmony_ci
157e1051a39Sopenharmony_ci        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
158e1051a39Sopenharmony_ci            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
159e1051a39Sopenharmony_ci            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
160e1051a39Sopenharmony_ci            size_t pal = key1->keylen;
161e1051a39Sopenharmony_ci            size_t pbl = key2->keylen;
162e1051a39Sopenharmony_ci
163e1051a39Sopenharmony_ci            if (pa != NULL && pb != NULL) {
164e1051a39Sopenharmony_ci                ok = ok
165e1051a39Sopenharmony_ci                    && key1->type == key2->type
166e1051a39Sopenharmony_ci                    && pal == pbl
167e1051a39Sopenharmony_ci                    && CRYPTO_memcmp(pa, pb, pal) == 0;
168e1051a39Sopenharmony_ci                key_checked = 1;
169e1051a39Sopenharmony_ci            }
170e1051a39Sopenharmony_ci        }
171e1051a39Sopenharmony_ci        if (!key_checked
172e1051a39Sopenharmony_ci            && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
173e1051a39Sopenharmony_ci            const unsigned char *pa = key1->privkey;
174e1051a39Sopenharmony_ci            const unsigned char *pb = key2->privkey;
175e1051a39Sopenharmony_ci            size_t pal = key1->keylen;
176e1051a39Sopenharmony_ci            size_t pbl = key2->keylen;
177e1051a39Sopenharmony_ci
178e1051a39Sopenharmony_ci            if (pa != NULL && pb != NULL) {
179e1051a39Sopenharmony_ci                ok = ok
180e1051a39Sopenharmony_ci                    && key1->type == key2->type
181e1051a39Sopenharmony_ci                    && pal == pbl
182e1051a39Sopenharmony_ci                    && CRYPTO_memcmp(pa, pb, pal) == 0;
183e1051a39Sopenharmony_ci                key_checked = 1;
184e1051a39Sopenharmony_ci            }
185e1051a39Sopenharmony_ci        }
186e1051a39Sopenharmony_ci        ok = ok && key_checked;
187e1051a39Sopenharmony_ci    }
188e1051a39Sopenharmony_ci    return ok;
189e1051a39Sopenharmony_ci}
190e1051a39Sopenharmony_ci
191e1051a39Sopenharmony_cistatic int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
192e1051a39Sopenharmony_ci{
193e1051a39Sopenharmony_ci    ECX_KEY *key = keydata;
194e1051a39Sopenharmony_ci    int ok = 1;
195e1051a39Sopenharmony_ci    int include_private;
196e1051a39Sopenharmony_ci
197e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || key == NULL)
198e1051a39Sopenharmony_ci        return 0;
199e1051a39Sopenharmony_ci
200e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
201e1051a39Sopenharmony_ci        return 0;
202e1051a39Sopenharmony_ci
203e1051a39Sopenharmony_ci    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
204e1051a39Sopenharmony_ci    ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
205e1051a39Sopenharmony_ci
206e1051a39Sopenharmony_ci    return ok;
207e1051a39Sopenharmony_ci}
208e1051a39Sopenharmony_ci
209e1051a39Sopenharmony_cistatic int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
210e1051a39Sopenharmony_ci                         OSSL_PARAM params[], int include_private)
211e1051a39Sopenharmony_ci{
212e1051a39Sopenharmony_ci    if (key == NULL)
213e1051a39Sopenharmony_ci        return 0;
214e1051a39Sopenharmony_ci
215e1051a39Sopenharmony_ci    if (!ossl_param_build_set_octet_string(tmpl, params,
216e1051a39Sopenharmony_ci                                           OSSL_PKEY_PARAM_PUB_KEY,
217e1051a39Sopenharmony_ci                                           key->pubkey, key->keylen))
218e1051a39Sopenharmony_ci        return 0;
219e1051a39Sopenharmony_ci
220e1051a39Sopenharmony_ci    if (include_private
221e1051a39Sopenharmony_ci        && key->privkey != NULL
222e1051a39Sopenharmony_ci        && !ossl_param_build_set_octet_string(tmpl, params,
223e1051a39Sopenharmony_ci                                              OSSL_PKEY_PARAM_PRIV_KEY,
224e1051a39Sopenharmony_ci                                              key->privkey, key->keylen))
225e1051a39Sopenharmony_ci        return 0;
226e1051a39Sopenharmony_ci
227e1051a39Sopenharmony_ci    return 1;
228e1051a39Sopenharmony_ci}
229e1051a39Sopenharmony_ci
230e1051a39Sopenharmony_cistatic int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
231e1051a39Sopenharmony_ci                      void *cbarg)
232e1051a39Sopenharmony_ci{
233e1051a39Sopenharmony_ci    ECX_KEY *key = keydata;
234e1051a39Sopenharmony_ci    OSSL_PARAM_BLD *tmpl;
235e1051a39Sopenharmony_ci    OSSL_PARAM *params = NULL;
236e1051a39Sopenharmony_ci    int ret = 0;
237e1051a39Sopenharmony_ci
238e1051a39Sopenharmony_ci    if (!ossl_prov_is_running() || key == NULL)
239e1051a39Sopenharmony_ci        return 0;
240e1051a39Sopenharmony_ci
241e1051a39Sopenharmony_ci    tmpl = OSSL_PARAM_BLD_new();
242e1051a39Sopenharmony_ci    if (tmpl == NULL)
243e1051a39Sopenharmony_ci        return 0;
244e1051a39Sopenharmony_ci
245e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
246e1051a39Sopenharmony_ci        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
247e1051a39Sopenharmony_ci
248e1051a39Sopenharmony_ci        if (!key_to_params(key, tmpl, NULL, include_private))
249e1051a39Sopenharmony_ci            goto err;
250e1051a39Sopenharmony_ci    }
251e1051a39Sopenharmony_ci
252e1051a39Sopenharmony_ci    params = OSSL_PARAM_BLD_to_param(tmpl);
253e1051a39Sopenharmony_ci    if (params == NULL)
254e1051a39Sopenharmony_ci        goto err;
255e1051a39Sopenharmony_ci
256e1051a39Sopenharmony_ci    ret = param_cb(params, cbarg);
257e1051a39Sopenharmony_ci    OSSL_PARAM_free(params);
258e1051a39Sopenharmony_cierr:
259e1051a39Sopenharmony_ci    OSSL_PARAM_BLD_free(tmpl);
260e1051a39Sopenharmony_ci    return ret;
261e1051a39Sopenharmony_ci}
262e1051a39Sopenharmony_ci
263e1051a39Sopenharmony_ci#define ECX_KEY_TYPES()                                                        \
264e1051a39Sopenharmony_ciOSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0),                     \
265e1051a39Sopenharmony_ciOSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
266e1051a39Sopenharmony_ci
267e1051a39Sopenharmony_cistatic const OSSL_PARAM ecx_key_types[] = {
268e1051a39Sopenharmony_ci    ECX_KEY_TYPES(),
269e1051a39Sopenharmony_ci    OSSL_PARAM_END
270e1051a39Sopenharmony_ci};
271e1051a39Sopenharmony_cistatic const OSSL_PARAM *ecx_imexport_types(int selection)
272e1051a39Sopenharmony_ci{
273e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
274e1051a39Sopenharmony_ci        return ecx_key_types;
275e1051a39Sopenharmony_ci    return NULL;
276e1051a39Sopenharmony_ci}
277e1051a39Sopenharmony_ci
278e1051a39Sopenharmony_cistatic int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
279e1051a39Sopenharmony_ci                          int size)
280e1051a39Sopenharmony_ci{
281e1051a39Sopenharmony_ci    ECX_KEY *ecx = key;
282e1051a39Sopenharmony_ci    OSSL_PARAM *p;
283e1051a39Sopenharmony_ci
284e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
285e1051a39Sopenharmony_ci        && !OSSL_PARAM_set_int(p, bits))
286e1051a39Sopenharmony_ci        return 0;
287e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
288e1051a39Sopenharmony_ci        && !OSSL_PARAM_set_int(p, secbits))
289e1051a39Sopenharmony_ci        return 0;
290e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
291e1051a39Sopenharmony_ci        && !OSSL_PARAM_set_int(p, size))
292e1051a39Sopenharmony_ci        return 0;
293e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
294e1051a39Sopenharmony_ci            && (ecx->type == ECX_KEY_TYPE_X25519
295e1051a39Sopenharmony_ci                || ecx->type == ECX_KEY_TYPE_X448)) {
296e1051a39Sopenharmony_ci        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
297e1051a39Sopenharmony_ci            return 0;
298e1051a39Sopenharmony_ci    }
299e1051a39Sopenharmony_ci
300e1051a39Sopenharmony_ci    return key_to_params(ecx, NULL, params, 1);
301e1051a39Sopenharmony_ci}
302e1051a39Sopenharmony_ci
303e1051a39Sopenharmony_cistatic int ed_get_params(void *key, OSSL_PARAM params[])
304e1051a39Sopenharmony_ci{
305e1051a39Sopenharmony_ci    OSSL_PARAM *p;
306e1051a39Sopenharmony_ci
307e1051a39Sopenharmony_ci    if ((p = OSSL_PARAM_locate(params,
308e1051a39Sopenharmony_ci                               OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
309e1051a39Sopenharmony_ci        && !OSSL_PARAM_set_utf8_string(p, ""))
310e1051a39Sopenharmony_ci        return 0;
311e1051a39Sopenharmony_ci    return 1;
312e1051a39Sopenharmony_ci}
313e1051a39Sopenharmony_ci
314e1051a39Sopenharmony_cistatic int x25519_get_params(void *key, OSSL_PARAM params[])
315e1051a39Sopenharmony_ci{
316e1051a39Sopenharmony_ci    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
317e1051a39Sopenharmony_ci                          X25519_KEYLEN);
318e1051a39Sopenharmony_ci}
319e1051a39Sopenharmony_ci
320e1051a39Sopenharmony_cistatic int x448_get_params(void *key, OSSL_PARAM params[])
321e1051a39Sopenharmony_ci{
322e1051a39Sopenharmony_ci    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
323e1051a39Sopenharmony_ci                          X448_KEYLEN);
324e1051a39Sopenharmony_ci}
325e1051a39Sopenharmony_ci
326e1051a39Sopenharmony_cistatic int ed25519_get_params(void *key, OSSL_PARAM params[])
327e1051a39Sopenharmony_ci{
328e1051a39Sopenharmony_ci    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
329e1051a39Sopenharmony_ci                          ED25519_SIGSIZE)
330e1051a39Sopenharmony_ci        && ed_get_params(key, params);
331e1051a39Sopenharmony_ci}
332e1051a39Sopenharmony_ci
333e1051a39Sopenharmony_cistatic int ed448_get_params(void *key, OSSL_PARAM params[])
334e1051a39Sopenharmony_ci{
335e1051a39Sopenharmony_ci    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
336e1051a39Sopenharmony_ci                          ED448_SIGSIZE)
337e1051a39Sopenharmony_ci        && ed_get_params(key, params);
338e1051a39Sopenharmony_ci}
339e1051a39Sopenharmony_ci
340e1051a39Sopenharmony_cistatic const OSSL_PARAM ecx_gettable_params[] = {
341e1051a39Sopenharmony_ci    OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
342e1051a39Sopenharmony_ci    OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
343e1051a39Sopenharmony_ci    OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
344e1051a39Sopenharmony_ci    OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
345e1051a39Sopenharmony_ci    OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
346e1051a39Sopenharmony_ci    ECX_KEY_TYPES(),
347e1051a39Sopenharmony_ci    OSSL_PARAM_END
348e1051a39Sopenharmony_ci};
349e1051a39Sopenharmony_ci
350e1051a39Sopenharmony_cistatic const OSSL_PARAM ed_gettable_params[] = {
351e1051a39Sopenharmony_ci    OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
352e1051a39Sopenharmony_ci    OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
353e1051a39Sopenharmony_ci    OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
354e1051a39Sopenharmony_ci    ECX_KEY_TYPES(),
355e1051a39Sopenharmony_ci    OSSL_PARAM_END
356e1051a39Sopenharmony_ci};
357e1051a39Sopenharmony_ci
358e1051a39Sopenharmony_cistatic const OSSL_PARAM *x25519_gettable_params(void *provctx)
359e1051a39Sopenharmony_ci{
360e1051a39Sopenharmony_ci    return ecx_gettable_params;
361e1051a39Sopenharmony_ci}
362e1051a39Sopenharmony_ci
363e1051a39Sopenharmony_cistatic const OSSL_PARAM *x448_gettable_params(void *provctx)
364e1051a39Sopenharmony_ci{
365e1051a39Sopenharmony_ci    return ecx_gettable_params;
366e1051a39Sopenharmony_ci}
367e1051a39Sopenharmony_ci
368e1051a39Sopenharmony_cistatic const OSSL_PARAM *ed25519_gettable_params(void *provctx)
369e1051a39Sopenharmony_ci{
370e1051a39Sopenharmony_ci    return ed_gettable_params;
371e1051a39Sopenharmony_ci}
372e1051a39Sopenharmony_ci
373e1051a39Sopenharmony_cistatic const OSSL_PARAM *ed448_gettable_params(void *provctx)
374e1051a39Sopenharmony_ci{
375e1051a39Sopenharmony_ci    return ed_gettable_params;
376e1051a39Sopenharmony_ci}
377e1051a39Sopenharmony_ci
378e1051a39Sopenharmony_cistatic int set_property_query(ECX_KEY *ecxkey, const char *propq)
379e1051a39Sopenharmony_ci{
380e1051a39Sopenharmony_ci    OPENSSL_free(ecxkey->propq);
381e1051a39Sopenharmony_ci    ecxkey->propq = NULL;
382e1051a39Sopenharmony_ci    if (propq != NULL) {
383e1051a39Sopenharmony_ci        ecxkey->propq = OPENSSL_strdup(propq);
384e1051a39Sopenharmony_ci        if (ecxkey->propq == NULL) {
385e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
386e1051a39Sopenharmony_ci            return 0;
387e1051a39Sopenharmony_ci        }
388e1051a39Sopenharmony_ci    }
389e1051a39Sopenharmony_ci    return 1;
390e1051a39Sopenharmony_ci}
391e1051a39Sopenharmony_ci
392e1051a39Sopenharmony_cistatic int ecx_set_params(void *key, const OSSL_PARAM params[])
393e1051a39Sopenharmony_ci{
394e1051a39Sopenharmony_ci    ECX_KEY *ecxkey = key;
395e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
396e1051a39Sopenharmony_ci
397e1051a39Sopenharmony_ci    if (params == NULL)
398e1051a39Sopenharmony_ci        return 1;
399e1051a39Sopenharmony_ci
400e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
401e1051a39Sopenharmony_ci    if (p != NULL) {
402e1051a39Sopenharmony_ci        void *buf = ecxkey->pubkey;
403e1051a39Sopenharmony_ci
404e1051a39Sopenharmony_ci        if (p->data_size != ecxkey->keylen
405e1051a39Sopenharmony_ci                || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
406e1051a39Sopenharmony_ci                                                NULL))
407e1051a39Sopenharmony_ci            return 0;
408e1051a39Sopenharmony_ci        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
409e1051a39Sopenharmony_ci        ecxkey->privkey = NULL;
410e1051a39Sopenharmony_ci        ecxkey->haspubkey = 1;
411e1051a39Sopenharmony_ci    }
412e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
413e1051a39Sopenharmony_ci    if (p != NULL) {
414e1051a39Sopenharmony_ci        if (p->data_type != OSSL_PARAM_UTF8_STRING
415e1051a39Sopenharmony_ci            || !set_property_query(ecxkey, p->data))
416e1051a39Sopenharmony_ci            return 0;
417e1051a39Sopenharmony_ci    }
418e1051a39Sopenharmony_ci
419e1051a39Sopenharmony_ci    return 1;
420e1051a39Sopenharmony_ci}
421e1051a39Sopenharmony_ci
422e1051a39Sopenharmony_cistatic int x25519_set_params(void *key, const OSSL_PARAM params[])
423e1051a39Sopenharmony_ci{
424e1051a39Sopenharmony_ci    return ecx_set_params(key, params);
425e1051a39Sopenharmony_ci}
426e1051a39Sopenharmony_ci
427e1051a39Sopenharmony_cistatic int x448_set_params(void *key, const OSSL_PARAM params[])
428e1051a39Sopenharmony_ci{
429e1051a39Sopenharmony_ci    return ecx_set_params(key, params);
430e1051a39Sopenharmony_ci}
431e1051a39Sopenharmony_ci
432e1051a39Sopenharmony_cistatic int ed25519_set_params(void *key, const OSSL_PARAM params[])
433e1051a39Sopenharmony_ci{
434e1051a39Sopenharmony_ci    return 1;
435e1051a39Sopenharmony_ci}
436e1051a39Sopenharmony_ci
437e1051a39Sopenharmony_cistatic int ed448_set_params(void *key, const OSSL_PARAM params[])
438e1051a39Sopenharmony_ci{
439e1051a39Sopenharmony_ci    return 1;
440e1051a39Sopenharmony_ci}
441e1051a39Sopenharmony_ci
442e1051a39Sopenharmony_cistatic const OSSL_PARAM ecx_settable_params[] = {
443e1051a39Sopenharmony_ci    OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
444e1051a39Sopenharmony_ci    OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
445e1051a39Sopenharmony_ci    OSSL_PARAM_END
446e1051a39Sopenharmony_ci};
447e1051a39Sopenharmony_ci
448e1051a39Sopenharmony_cistatic const OSSL_PARAM ed_settable_params[] = {
449e1051a39Sopenharmony_ci    OSSL_PARAM_END
450e1051a39Sopenharmony_ci};
451e1051a39Sopenharmony_ci
452e1051a39Sopenharmony_cistatic const OSSL_PARAM *x25519_settable_params(void *provctx)
453e1051a39Sopenharmony_ci{
454e1051a39Sopenharmony_ci    return ecx_settable_params;
455e1051a39Sopenharmony_ci}
456e1051a39Sopenharmony_ci
457e1051a39Sopenharmony_cistatic const OSSL_PARAM *x448_settable_params(void *provctx)
458e1051a39Sopenharmony_ci{
459e1051a39Sopenharmony_ci    return ecx_settable_params;
460e1051a39Sopenharmony_ci}
461e1051a39Sopenharmony_ci
462e1051a39Sopenharmony_cistatic const OSSL_PARAM *ed25519_settable_params(void *provctx)
463e1051a39Sopenharmony_ci{
464e1051a39Sopenharmony_ci    return ed_settable_params;
465e1051a39Sopenharmony_ci}
466e1051a39Sopenharmony_ci
467e1051a39Sopenharmony_cistatic const OSSL_PARAM *ed448_settable_params(void *provctx)
468e1051a39Sopenharmony_ci{
469e1051a39Sopenharmony_ci    return ed_settable_params;
470e1051a39Sopenharmony_ci}
471e1051a39Sopenharmony_ci
472e1051a39Sopenharmony_cistatic void *ecx_gen_init(void *provctx, int selection,
473e1051a39Sopenharmony_ci                          const OSSL_PARAM params[], ECX_KEY_TYPE type)
474e1051a39Sopenharmony_ci{
475e1051a39Sopenharmony_ci    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
476e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = NULL;
477e1051a39Sopenharmony_ci
478e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
479e1051a39Sopenharmony_ci        return NULL;
480e1051a39Sopenharmony_ci
481e1051a39Sopenharmony_ci    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
482e1051a39Sopenharmony_ci        gctx->libctx = libctx;
483e1051a39Sopenharmony_ci        gctx->type = type;
484e1051a39Sopenharmony_ci        gctx->selection = selection;
485e1051a39Sopenharmony_ci    }
486e1051a39Sopenharmony_ci    if (!ecx_gen_set_params(gctx, params)) {
487e1051a39Sopenharmony_ci        OPENSSL_free(gctx);
488e1051a39Sopenharmony_ci        gctx = NULL;
489e1051a39Sopenharmony_ci    }
490e1051a39Sopenharmony_ci    return gctx;
491e1051a39Sopenharmony_ci}
492e1051a39Sopenharmony_ci
493e1051a39Sopenharmony_cistatic void *x25519_gen_init(void *provctx, int selection,
494e1051a39Sopenharmony_ci                             const OSSL_PARAM params[])
495e1051a39Sopenharmony_ci{
496e1051a39Sopenharmony_ci    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
497e1051a39Sopenharmony_ci}
498e1051a39Sopenharmony_ci
499e1051a39Sopenharmony_cistatic void *x448_gen_init(void *provctx, int selection,
500e1051a39Sopenharmony_ci                           const OSSL_PARAM params[])
501e1051a39Sopenharmony_ci{
502e1051a39Sopenharmony_ci    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
503e1051a39Sopenharmony_ci}
504e1051a39Sopenharmony_ci
505e1051a39Sopenharmony_cistatic void *ed25519_gen_init(void *provctx, int selection,
506e1051a39Sopenharmony_ci                              const OSSL_PARAM params[])
507e1051a39Sopenharmony_ci{
508e1051a39Sopenharmony_ci    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
509e1051a39Sopenharmony_ci}
510e1051a39Sopenharmony_ci
511e1051a39Sopenharmony_cistatic void *ed448_gen_init(void *provctx, int selection,
512e1051a39Sopenharmony_ci                            const OSSL_PARAM params[])
513e1051a39Sopenharmony_ci{
514e1051a39Sopenharmony_ci    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
515e1051a39Sopenharmony_ci}
516e1051a39Sopenharmony_ci
517e1051a39Sopenharmony_cistatic int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
518e1051a39Sopenharmony_ci{
519e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = genctx;
520e1051a39Sopenharmony_ci    const OSSL_PARAM *p;
521e1051a39Sopenharmony_ci
522e1051a39Sopenharmony_ci    if (gctx == NULL)
523e1051a39Sopenharmony_ci        return 0;
524e1051a39Sopenharmony_ci
525e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
526e1051a39Sopenharmony_ci    if (p != NULL) {
527e1051a39Sopenharmony_ci        const char *groupname = NULL;
528e1051a39Sopenharmony_ci
529e1051a39Sopenharmony_ci        /*
530e1051a39Sopenharmony_ci         * We optionally allow setting a group name - but each algorithm only
531e1051a39Sopenharmony_ci         * support one such name, so all we do is verify that it is the one we
532e1051a39Sopenharmony_ci         * expected.
533e1051a39Sopenharmony_ci         */
534e1051a39Sopenharmony_ci        switch (gctx->type) {
535e1051a39Sopenharmony_ci            case ECX_KEY_TYPE_X25519:
536e1051a39Sopenharmony_ci                groupname = "x25519";
537e1051a39Sopenharmony_ci                break;
538e1051a39Sopenharmony_ci            case ECX_KEY_TYPE_X448:
539e1051a39Sopenharmony_ci                groupname = "x448";
540e1051a39Sopenharmony_ci                break;
541e1051a39Sopenharmony_ci            default:
542e1051a39Sopenharmony_ci                /* We only support this for key exchange at the moment */
543e1051a39Sopenharmony_ci                break;
544e1051a39Sopenharmony_ci        }
545e1051a39Sopenharmony_ci        if (p->data_type != OSSL_PARAM_UTF8_STRING
546e1051a39Sopenharmony_ci                || groupname == NULL
547e1051a39Sopenharmony_ci                || OPENSSL_strcasecmp(p->data, groupname) != 0) {
548e1051a39Sopenharmony_ci            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
549e1051a39Sopenharmony_ci            return 0;
550e1051a39Sopenharmony_ci        }
551e1051a39Sopenharmony_ci    }
552e1051a39Sopenharmony_ci    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
553e1051a39Sopenharmony_ci    if (p != NULL) {
554e1051a39Sopenharmony_ci        if (p->data_type != OSSL_PARAM_UTF8_STRING)
555e1051a39Sopenharmony_ci            return 0;
556e1051a39Sopenharmony_ci        OPENSSL_free(gctx->propq);
557e1051a39Sopenharmony_ci        gctx->propq = OPENSSL_strdup(p->data);
558e1051a39Sopenharmony_ci        if (gctx->propq == NULL)
559e1051a39Sopenharmony_ci            return 0;
560e1051a39Sopenharmony_ci    }
561e1051a39Sopenharmony_ci
562e1051a39Sopenharmony_ci    return 1;
563e1051a39Sopenharmony_ci}
564e1051a39Sopenharmony_ci
565e1051a39Sopenharmony_cistatic const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
566e1051a39Sopenharmony_ci                                                 ossl_unused void *provctx)
567e1051a39Sopenharmony_ci{
568e1051a39Sopenharmony_ci    static OSSL_PARAM settable[] = {
569e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
570e1051a39Sopenharmony_ci        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
571e1051a39Sopenharmony_ci        OSSL_PARAM_END
572e1051a39Sopenharmony_ci    };
573e1051a39Sopenharmony_ci    return settable;
574e1051a39Sopenharmony_ci}
575e1051a39Sopenharmony_ci
576e1051a39Sopenharmony_cistatic void *ecx_gen(struct ecx_gen_ctx *gctx)
577e1051a39Sopenharmony_ci{
578e1051a39Sopenharmony_ci    ECX_KEY *key;
579e1051a39Sopenharmony_ci    unsigned char *privkey;
580e1051a39Sopenharmony_ci
581e1051a39Sopenharmony_ci    if (gctx == NULL)
582e1051a39Sopenharmony_ci        return NULL;
583e1051a39Sopenharmony_ci    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
584e1051a39Sopenharmony_ci                                gctx->propq)) == NULL) {
585e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
586e1051a39Sopenharmony_ci        return NULL;
587e1051a39Sopenharmony_ci    }
588e1051a39Sopenharmony_ci
589e1051a39Sopenharmony_ci    /* If we're doing parameter generation then we just return a blank key */
590e1051a39Sopenharmony_ci    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
591e1051a39Sopenharmony_ci        return key;
592e1051a39Sopenharmony_ci
593e1051a39Sopenharmony_ci    if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
594e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
595e1051a39Sopenharmony_ci        goto err;
596e1051a39Sopenharmony_ci    }
597e1051a39Sopenharmony_ci    if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
598e1051a39Sopenharmony_ci        goto err;
599e1051a39Sopenharmony_ci    switch (gctx->type) {
600e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_X25519:
601e1051a39Sopenharmony_ci        privkey[0] &= 248;
602e1051a39Sopenharmony_ci        privkey[X25519_KEYLEN - 1] &= 127;
603e1051a39Sopenharmony_ci        privkey[X25519_KEYLEN - 1] |= 64;
604e1051a39Sopenharmony_ci        ossl_x25519_public_from_private(key->pubkey, privkey);
605e1051a39Sopenharmony_ci        break;
606e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_X448:
607e1051a39Sopenharmony_ci        privkey[0] &= 252;
608e1051a39Sopenharmony_ci        privkey[X448_KEYLEN - 1] |= 128;
609e1051a39Sopenharmony_ci        ossl_x448_public_from_private(key->pubkey, privkey);
610e1051a39Sopenharmony_ci        break;
611e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_ED25519:
612e1051a39Sopenharmony_ci        if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
613e1051a39Sopenharmony_ci                                              gctx->propq))
614e1051a39Sopenharmony_ci            goto err;
615e1051a39Sopenharmony_ci        break;
616e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_ED448:
617e1051a39Sopenharmony_ci        if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
618e1051a39Sopenharmony_ci                                            gctx->propq))
619e1051a39Sopenharmony_ci            goto err;
620e1051a39Sopenharmony_ci        break;
621e1051a39Sopenharmony_ci    }
622e1051a39Sopenharmony_ci    key->haspubkey = 1;
623e1051a39Sopenharmony_ci    return key;
624e1051a39Sopenharmony_cierr:
625e1051a39Sopenharmony_ci    ossl_ecx_key_free(key);
626e1051a39Sopenharmony_ci    return NULL;
627e1051a39Sopenharmony_ci}
628e1051a39Sopenharmony_ci
629e1051a39Sopenharmony_cistatic void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
630e1051a39Sopenharmony_ci{
631e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = genctx;
632e1051a39Sopenharmony_ci
633e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
634e1051a39Sopenharmony_ci        return 0;
635e1051a39Sopenharmony_ci
636e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
637e1051a39Sopenharmony_ci    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
638e1051a39Sopenharmony_ci        return s390x_ecx_keygen25519(gctx);
639e1051a39Sopenharmony_ci#endif
640e1051a39Sopenharmony_ci    return ecx_gen(gctx);
641e1051a39Sopenharmony_ci}
642e1051a39Sopenharmony_ci
643e1051a39Sopenharmony_cistatic void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
644e1051a39Sopenharmony_ci{
645e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = genctx;
646e1051a39Sopenharmony_ci
647e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
648e1051a39Sopenharmony_ci        return 0;
649e1051a39Sopenharmony_ci
650e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
651e1051a39Sopenharmony_ci    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
652e1051a39Sopenharmony_ci        return s390x_ecx_keygen448(gctx);
653e1051a39Sopenharmony_ci#endif
654e1051a39Sopenharmony_ci    return ecx_gen(gctx);
655e1051a39Sopenharmony_ci}
656e1051a39Sopenharmony_ci
657e1051a39Sopenharmony_cistatic void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
658e1051a39Sopenharmony_ci{
659e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = genctx;
660e1051a39Sopenharmony_ci
661e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
662e1051a39Sopenharmony_ci        return 0;
663e1051a39Sopenharmony_ci
664e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
665e1051a39Sopenharmony_ci    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
666e1051a39Sopenharmony_ci        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
667e1051a39Sopenharmony_ci        && OPENSSL_s390xcap_P.kdsa[0]
668e1051a39Sopenharmony_ci            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
669e1051a39Sopenharmony_ci        return s390x_ecd_keygen25519(gctx);
670e1051a39Sopenharmony_ci#endif
671e1051a39Sopenharmony_ci    return ecx_gen(gctx);
672e1051a39Sopenharmony_ci}
673e1051a39Sopenharmony_ci
674e1051a39Sopenharmony_cistatic void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
675e1051a39Sopenharmony_ci{
676e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = genctx;
677e1051a39Sopenharmony_ci
678e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
679e1051a39Sopenharmony_ci        return 0;
680e1051a39Sopenharmony_ci
681e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
682e1051a39Sopenharmony_ci    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
683e1051a39Sopenharmony_ci        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
684e1051a39Sopenharmony_ci        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
685e1051a39Sopenharmony_ci        return s390x_ecd_keygen448(gctx);
686e1051a39Sopenharmony_ci#endif
687e1051a39Sopenharmony_ci    return ecx_gen(gctx);
688e1051a39Sopenharmony_ci}
689e1051a39Sopenharmony_ci
690e1051a39Sopenharmony_cistatic void ecx_gen_cleanup(void *genctx)
691e1051a39Sopenharmony_ci{
692e1051a39Sopenharmony_ci    struct ecx_gen_ctx *gctx = genctx;
693e1051a39Sopenharmony_ci
694e1051a39Sopenharmony_ci    OPENSSL_free(gctx->propq);
695e1051a39Sopenharmony_ci    OPENSSL_free(gctx);
696e1051a39Sopenharmony_ci}
697e1051a39Sopenharmony_ci
698e1051a39Sopenharmony_civoid *ecx_load(const void *reference, size_t reference_sz)
699e1051a39Sopenharmony_ci{
700e1051a39Sopenharmony_ci    ECX_KEY *key = NULL;
701e1051a39Sopenharmony_ci
702e1051a39Sopenharmony_ci    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
703e1051a39Sopenharmony_ci        /* The contents of the reference is the address to our object */
704e1051a39Sopenharmony_ci        key = *(ECX_KEY **)reference;
705e1051a39Sopenharmony_ci        /* We grabbed, so we detach it */
706e1051a39Sopenharmony_ci        *(ECX_KEY **)reference = NULL;
707e1051a39Sopenharmony_ci        return key;
708e1051a39Sopenharmony_ci    }
709e1051a39Sopenharmony_ci    return NULL;
710e1051a39Sopenharmony_ci}
711e1051a39Sopenharmony_ci
712e1051a39Sopenharmony_cistatic void *ecx_dup(const void *keydata_from, int selection)
713e1051a39Sopenharmony_ci{
714e1051a39Sopenharmony_ci    if (ossl_prov_is_running())
715e1051a39Sopenharmony_ci        return ossl_ecx_key_dup(keydata_from, selection);
716e1051a39Sopenharmony_ci    return NULL;
717e1051a39Sopenharmony_ci}
718e1051a39Sopenharmony_ci
719e1051a39Sopenharmony_cistatic int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
720e1051a39Sopenharmony_ci{
721e1051a39Sopenharmony_ci    uint8_t pub[64];
722e1051a39Sopenharmony_ci
723e1051a39Sopenharmony_ci    switch (type) {
724e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_X25519:
725e1051a39Sopenharmony_ci        ossl_x25519_public_from_private(pub, ecx->privkey);
726e1051a39Sopenharmony_ci        break;
727e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_X448:
728e1051a39Sopenharmony_ci        ossl_x448_public_from_private(pub, ecx->privkey);
729e1051a39Sopenharmony_ci        break;
730e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_ED25519:
731e1051a39Sopenharmony_ci        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
732e1051a39Sopenharmony_ci                                              ecx->propq))
733e1051a39Sopenharmony_ci            return 0;
734e1051a39Sopenharmony_ci        break;
735e1051a39Sopenharmony_ci    case ECX_KEY_TYPE_ED448:
736e1051a39Sopenharmony_ci        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
737e1051a39Sopenharmony_ci                                            ecx->propq))
738e1051a39Sopenharmony_ci            return 0;
739e1051a39Sopenharmony_ci        break;
740e1051a39Sopenharmony_ci    default:
741e1051a39Sopenharmony_ci        return 0;
742e1051a39Sopenharmony_ci    }
743e1051a39Sopenharmony_ci    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
744e1051a39Sopenharmony_ci}
745e1051a39Sopenharmony_ci
746e1051a39Sopenharmony_cistatic int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
747e1051a39Sopenharmony_ci{
748e1051a39Sopenharmony_ci    const ECX_KEY *ecx = keydata;
749e1051a39Sopenharmony_ci    int ok = keylen == ecx->keylen;
750e1051a39Sopenharmony_ci
751e1051a39Sopenharmony_ci    if (!ossl_prov_is_running())
752e1051a39Sopenharmony_ci        return 0;
753e1051a39Sopenharmony_ci
754e1051a39Sopenharmony_ci    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
755e1051a39Sopenharmony_ci        return 1; /* nothing to validate */
756e1051a39Sopenharmony_ci
757e1051a39Sopenharmony_ci    if (!ok) {
758e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
759e1051a39Sopenharmony_ci        return 0;
760e1051a39Sopenharmony_ci    }
761e1051a39Sopenharmony_ci
762e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
763e1051a39Sopenharmony_ci        ok = ok && ecx->haspubkey;
764e1051a39Sopenharmony_ci
765e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
766e1051a39Sopenharmony_ci        ok = ok && ecx->privkey != NULL;
767e1051a39Sopenharmony_ci
768e1051a39Sopenharmony_ci    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
769e1051a39Sopenharmony_ci        ok = ok && ecx_key_pairwise_check(ecx, type);
770e1051a39Sopenharmony_ci
771e1051a39Sopenharmony_ci    return ok;
772e1051a39Sopenharmony_ci}
773e1051a39Sopenharmony_ci
774e1051a39Sopenharmony_cistatic int x25519_validate(const void *keydata, int selection, int checktype)
775e1051a39Sopenharmony_ci{
776e1051a39Sopenharmony_ci    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
777e1051a39Sopenharmony_ci}
778e1051a39Sopenharmony_ci
779e1051a39Sopenharmony_cistatic int x448_validate(const void *keydata, int selection, int checktype)
780e1051a39Sopenharmony_ci{
781e1051a39Sopenharmony_ci    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
782e1051a39Sopenharmony_ci}
783e1051a39Sopenharmony_ci
784e1051a39Sopenharmony_cistatic int ed25519_validate(const void *keydata, int selection, int checktype)
785e1051a39Sopenharmony_ci{
786e1051a39Sopenharmony_ci    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
787e1051a39Sopenharmony_ci}
788e1051a39Sopenharmony_ci
789e1051a39Sopenharmony_cistatic int ed448_validate(const void *keydata, int selection, int checktype)
790e1051a39Sopenharmony_ci{
791e1051a39Sopenharmony_ci    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
792e1051a39Sopenharmony_ci}
793e1051a39Sopenharmony_ci
794e1051a39Sopenharmony_ci#define MAKE_KEYMGMT_FUNCTIONS(alg) \
795e1051a39Sopenharmony_ci    const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
796e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
797e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
798e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
799e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
800e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
801e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
802e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
803e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
804e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
805e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
806e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
807e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
808e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
809e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
810e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
811e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
812e1051a39Sopenharmony_ci          (void (*)(void))ecx_gen_settable_params }, \
813e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
814e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
815e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
816e1051a39Sopenharmony_ci        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
817e1051a39Sopenharmony_ci        { 0, NULL } \
818e1051a39Sopenharmony_ci    };
819e1051a39Sopenharmony_ci
820e1051a39Sopenharmony_ciMAKE_KEYMGMT_FUNCTIONS(x25519)
821e1051a39Sopenharmony_ciMAKE_KEYMGMT_FUNCTIONS(x448)
822e1051a39Sopenharmony_ciMAKE_KEYMGMT_FUNCTIONS(ed25519)
823e1051a39Sopenharmony_ciMAKE_KEYMGMT_FUNCTIONS(ed448)
824e1051a39Sopenharmony_ci
825e1051a39Sopenharmony_ci#ifdef S390X_EC_ASM
826e1051a39Sopenharmony_ci# include "s390x_arch.h"
827e1051a39Sopenharmony_ci
828e1051a39Sopenharmony_cistatic void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
829e1051a39Sopenharmony_ci{
830e1051a39Sopenharmony_ci    static const unsigned char generator[] = {
831e1051a39Sopenharmony_ci        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832e1051a39Sopenharmony_ci        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
833e1051a39Sopenharmony_ci        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
834e1051a39Sopenharmony_ci    };
835e1051a39Sopenharmony_ci    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
836e1051a39Sopenharmony_ci                                    gctx->propq);
837e1051a39Sopenharmony_ci    unsigned char *privkey = NULL, *pubkey;
838e1051a39Sopenharmony_ci
839e1051a39Sopenharmony_ci    if (key == NULL) {
840e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
841e1051a39Sopenharmony_ci        goto err;
842e1051a39Sopenharmony_ci    }
843e1051a39Sopenharmony_ci
844e1051a39Sopenharmony_ci    /* If we're doing parameter generation then we just return a blank key */
845e1051a39Sopenharmony_ci    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
846e1051a39Sopenharmony_ci        return key;
847e1051a39Sopenharmony_ci
848e1051a39Sopenharmony_ci    pubkey = key->pubkey;
849e1051a39Sopenharmony_ci
850e1051a39Sopenharmony_ci    privkey = ossl_ecx_key_allocate_privkey(key);
851e1051a39Sopenharmony_ci    if (privkey == NULL) {
852e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
853e1051a39Sopenharmony_ci        goto err;
854e1051a39Sopenharmony_ci    }
855e1051a39Sopenharmony_ci
856e1051a39Sopenharmony_ci    if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
857e1051a39Sopenharmony_ci        goto err;
858e1051a39Sopenharmony_ci
859e1051a39Sopenharmony_ci    privkey[0] &= 248;
860e1051a39Sopenharmony_ci    privkey[31] &= 127;
861e1051a39Sopenharmony_ci    privkey[31] |= 64;
862e1051a39Sopenharmony_ci
863e1051a39Sopenharmony_ci    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
864e1051a39Sopenharmony_ci        goto err;
865e1051a39Sopenharmony_ci    key->haspubkey = 1;
866e1051a39Sopenharmony_ci    return key;
867e1051a39Sopenharmony_ci err:
868e1051a39Sopenharmony_ci    ossl_ecx_key_free(key);
869e1051a39Sopenharmony_ci    return NULL;
870e1051a39Sopenharmony_ci}
871e1051a39Sopenharmony_ci
872e1051a39Sopenharmony_cistatic void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
873e1051a39Sopenharmony_ci{
874e1051a39Sopenharmony_ci    static const unsigned char generator[] = {
875e1051a39Sopenharmony_ci        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
876e1051a39Sopenharmony_ci        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
877e1051a39Sopenharmony_ci        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
878e1051a39Sopenharmony_ci        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879e1051a39Sopenharmony_ci        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
880e1051a39Sopenharmony_ci    };
881e1051a39Sopenharmony_ci    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
882e1051a39Sopenharmony_ci                                    gctx->propq);
883e1051a39Sopenharmony_ci    unsigned char *privkey = NULL, *pubkey;
884e1051a39Sopenharmony_ci
885e1051a39Sopenharmony_ci    if (key == NULL) {
886e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
887e1051a39Sopenharmony_ci        goto err;
888e1051a39Sopenharmony_ci    }
889e1051a39Sopenharmony_ci
890e1051a39Sopenharmony_ci    /* If we're doing parameter generation then we just return a blank key */
891e1051a39Sopenharmony_ci    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
892e1051a39Sopenharmony_ci        return key;
893e1051a39Sopenharmony_ci
894e1051a39Sopenharmony_ci    pubkey = key->pubkey;
895e1051a39Sopenharmony_ci
896e1051a39Sopenharmony_ci    privkey = ossl_ecx_key_allocate_privkey(key);
897e1051a39Sopenharmony_ci    if (privkey == NULL) {
898e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
899e1051a39Sopenharmony_ci        goto err;
900e1051a39Sopenharmony_ci    }
901e1051a39Sopenharmony_ci
902e1051a39Sopenharmony_ci    if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
903e1051a39Sopenharmony_ci        goto err;
904e1051a39Sopenharmony_ci
905e1051a39Sopenharmony_ci    privkey[0] &= 252;
906e1051a39Sopenharmony_ci    privkey[55] |= 128;
907e1051a39Sopenharmony_ci
908e1051a39Sopenharmony_ci    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
909e1051a39Sopenharmony_ci        goto err;
910e1051a39Sopenharmony_ci    key->haspubkey = 1;
911e1051a39Sopenharmony_ci    return key;
912e1051a39Sopenharmony_ci err:
913e1051a39Sopenharmony_ci    ossl_ecx_key_free(key);
914e1051a39Sopenharmony_ci    return NULL;
915e1051a39Sopenharmony_ci}
916e1051a39Sopenharmony_ci
917e1051a39Sopenharmony_cistatic void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
918e1051a39Sopenharmony_ci{
919e1051a39Sopenharmony_ci    static const unsigned char generator_x[] = {
920e1051a39Sopenharmony_ci        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
921e1051a39Sopenharmony_ci        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
922e1051a39Sopenharmony_ci        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
923e1051a39Sopenharmony_ci    };
924e1051a39Sopenharmony_ci    static const unsigned char generator_y[] = {
925e1051a39Sopenharmony_ci        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
926e1051a39Sopenharmony_ci        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
927e1051a39Sopenharmony_ci        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
928e1051a39Sopenharmony_ci    };
929e1051a39Sopenharmony_ci    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
930e1051a39Sopenharmony_ci    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
931e1051a39Sopenharmony_ci                                    gctx->propq);
932e1051a39Sopenharmony_ci    unsigned char *privkey = NULL, *pubkey;
933e1051a39Sopenharmony_ci    unsigned int sz;
934e1051a39Sopenharmony_ci    EVP_MD *sha = NULL;
935e1051a39Sopenharmony_ci    int j;
936e1051a39Sopenharmony_ci
937e1051a39Sopenharmony_ci    if (key == NULL) {
938e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
939e1051a39Sopenharmony_ci        goto err;
940e1051a39Sopenharmony_ci    }
941e1051a39Sopenharmony_ci
942e1051a39Sopenharmony_ci    /* If we're doing parameter generation then we just return a blank key */
943e1051a39Sopenharmony_ci    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
944e1051a39Sopenharmony_ci        return key;
945e1051a39Sopenharmony_ci
946e1051a39Sopenharmony_ci    pubkey = key->pubkey;
947e1051a39Sopenharmony_ci
948e1051a39Sopenharmony_ci    privkey = ossl_ecx_key_allocate_privkey(key);
949e1051a39Sopenharmony_ci    if (privkey == NULL) {
950e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
951e1051a39Sopenharmony_ci        goto err;
952e1051a39Sopenharmony_ci    }
953e1051a39Sopenharmony_ci
954e1051a39Sopenharmony_ci    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
955e1051a39Sopenharmony_ci        goto err;
956e1051a39Sopenharmony_ci
957e1051a39Sopenharmony_ci    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
958e1051a39Sopenharmony_ci    if (sha == NULL)
959e1051a39Sopenharmony_ci        goto err;
960e1051a39Sopenharmony_ci    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
961e1051a39Sopenharmony_ci    EVP_MD_free(sha);
962e1051a39Sopenharmony_ci    if (!j)
963e1051a39Sopenharmony_ci        goto err;
964e1051a39Sopenharmony_ci
965e1051a39Sopenharmony_ci    buff[0] &= 248;
966e1051a39Sopenharmony_ci    buff[31] &= 63;
967e1051a39Sopenharmony_ci    buff[31] |= 64;
968e1051a39Sopenharmony_ci
969e1051a39Sopenharmony_ci    if (s390x_ed25519_mul(x_dst, pubkey,
970e1051a39Sopenharmony_ci                          generator_x, generator_y, buff) != 1)
971e1051a39Sopenharmony_ci        goto err;
972e1051a39Sopenharmony_ci
973e1051a39Sopenharmony_ci    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
974e1051a39Sopenharmony_ci    key->haspubkey = 1;
975e1051a39Sopenharmony_ci    return key;
976e1051a39Sopenharmony_ci err:
977e1051a39Sopenharmony_ci    ossl_ecx_key_free(key);
978e1051a39Sopenharmony_ci    return NULL;
979e1051a39Sopenharmony_ci}
980e1051a39Sopenharmony_ci
981e1051a39Sopenharmony_cistatic void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
982e1051a39Sopenharmony_ci{
983e1051a39Sopenharmony_ci    static const unsigned char generator_x[] = {
984e1051a39Sopenharmony_ci        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
985e1051a39Sopenharmony_ci        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
986e1051a39Sopenharmony_ci        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
987e1051a39Sopenharmony_ci        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
988e1051a39Sopenharmony_ci        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
989e1051a39Sopenharmony_ci    };
990e1051a39Sopenharmony_ci    static const unsigned char generator_y[] = {
991e1051a39Sopenharmony_ci        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
992e1051a39Sopenharmony_ci        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
993e1051a39Sopenharmony_ci        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
994e1051a39Sopenharmony_ci        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
995e1051a39Sopenharmony_ci        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
996e1051a39Sopenharmony_ci    };
997e1051a39Sopenharmony_ci    unsigned char x_dst[57], buff[114];
998e1051a39Sopenharmony_ci    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
999e1051a39Sopenharmony_ci                                    gctx->propq);
1000e1051a39Sopenharmony_ci    unsigned char *privkey = NULL, *pubkey;
1001e1051a39Sopenharmony_ci    EVP_MD_CTX *hashctx = NULL;
1002e1051a39Sopenharmony_ci    EVP_MD *shake = NULL;
1003e1051a39Sopenharmony_ci
1004e1051a39Sopenharmony_ci    if (key == NULL) {
1005e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1006e1051a39Sopenharmony_ci        goto err;
1007e1051a39Sopenharmony_ci    }
1008e1051a39Sopenharmony_ci
1009e1051a39Sopenharmony_ci    /* If we're doing parameter generation then we just return a blank key */
1010e1051a39Sopenharmony_ci    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1011e1051a39Sopenharmony_ci        return key;
1012e1051a39Sopenharmony_ci
1013e1051a39Sopenharmony_ci    pubkey = key->pubkey;
1014e1051a39Sopenharmony_ci
1015e1051a39Sopenharmony_ci    privkey = ossl_ecx_key_allocate_privkey(key);
1016e1051a39Sopenharmony_ci    if (privkey == NULL) {
1017e1051a39Sopenharmony_ci        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1018e1051a39Sopenharmony_ci        goto err;
1019e1051a39Sopenharmony_ci    }
1020e1051a39Sopenharmony_ci
1021e1051a39Sopenharmony_ci    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1022e1051a39Sopenharmony_ci    if (shake == NULL)
1023e1051a39Sopenharmony_ci        goto err;
1024e1051a39Sopenharmony_ci    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1025e1051a39Sopenharmony_ci        goto err;
1026e1051a39Sopenharmony_ci
1027e1051a39Sopenharmony_ci    hashctx = EVP_MD_CTX_new();
1028e1051a39Sopenharmony_ci    if (hashctx == NULL)
1029e1051a39Sopenharmony_ci        goto err;
1030e1051a39Sopenharmony_ci    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1031e1051a39Sopenharmony_ci        goto err;
1032e1051a39Sopenharmony_ci    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1033e1051a39Sopenharmony_ci        goto err;
1034e1051a39Sopenharmony_ci    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1035e1051a39Sopenharmony_ci        goto err;
1036e1051a39Sopenharmony_ci
1037e1051a39Sopenharmony_ci    buff[0] &= -4;
1038e1051a39Sopenharmony_ci    buff[55] |= 0x80;
1039e1051a39Sopenharmony_ci    buff[56] = 0;
1040e1051a39Sopenharmony_ci
1041e1051a39Sopenharmony_ci    if (s390x_ed448_mul(x_dst, pubkey,
1042e1051a39Sopenharmony_ci                        generator_x, generator_y, buff) != 1)
1043e1051a39Sopenharmony_ci        goto err;
1044e1051a39Sopenharmony_ci
1045e1051a39Sopenharmony_ci    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1046e1051a39Sopenharmony_ci    EVP_MD_CTX_free(hashctx);
1047e1051a39Sopenharmony_ci    EVP_MD_free(shake);
1048e1051a39Sopenharmony_ci    key->haspubkey = 1;
1049e1051a39Sopenharmony_ci    return key;
1050e1051a39Sopenharmony_ci err:
1051e1051a39Sopenharmony_ci    ossl_ecx_key_free(key);
1052e1051a39Sopenharmony_ci    EVP_MD_CTX_free(hashctx);
1053e1051a39Sopenharmony_ci    EVP_MD_free(shake);
1054e1051a39Sopenharmony_ci    return NULL;
1055e1051a39Sopenharmony_ci}
1056e1051a39Sopenharmony_ci#endif
1057