Coverage Report

Created: 2025-12-04 06:33

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