Coverage Report

Created: 2025-06-13 06:58

/src/openssl30/providers/implementations/keymgmt/ecx_kmgmt.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2020-2023 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
8.91k
#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
28
{
92
28
    if (!ossl_prov_is_running())
93
0
        return 0;
94
28
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
95
28
                            NULL);
96
28
}
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
26.1k
{
124
26.1k
    const ECX_KEY *key = keydata;
125
26.1k
    int ok = 0;
126
127
26.1k
    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
13.2k
        ok = 1;
133
134
13.2k
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
135
44
            ok = ok && key->haspubkey;
136
137
13.2k
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
138
26
            ok = ok && key->privkey != NULL;
139
13.2k
    }
140
26.1k
    return ok;
141
26.1k
}
142
143
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
144
22
{
145
22
    const ECX_KEY *key1 = keydata1;
146
22
    const ECX_KEY *key2 = keydata2;
147
22
    int ok = 1;
148
149
22
    if (!ossl_prov_is_running())
150
0
        return 0;
151
152
22
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
153
22
        ok = ok && key1->type == key2->type;
154
22
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
155
22
        int key_checked = 0;
156
157
22
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
158
22
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
159
22
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
160
22
            size_t pal = key1->keylen;
161
22
            size_t pbl = key2->keylen;
162
163
22
            if (pa != NULL && pb != NULL) {
164
22
                ok = ok
165
22
                    && key1->type == key2->type
166
22
                    && pal == pbl
167
22
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
168
22
                key_checked = 1;
169
22
            }
170
22
        }
171
22
        if (!key_checked
172
22
            && (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
22
        ok = ok && key_checked;
187
22
    }
188
22
    return ok;
189
22
}
190
191
static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
192
28
{
193
28
    ECX_KEY *key = keydata;
194
28
    int ok = 1;
195
28
    int include_private;
196
197
28
    if (!ossl_prov_is_running() || key == NULL)
198
0
        return 0;
199
200
28
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
201
0
        return 0;
202
203
28
    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
204
28
    ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
205
206
28
    return ok;
207
28
}
208
209
static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
210
                         OSSL_PARAM params[], int include_private)
211
227k
{
212
227k
    if (key == NULL)
213
0
        return 0;
214
215
227k
    if (!ossl_param_build_set_octet_string(tmpl, params,
216
227k
                                           OSSL_PKEY_PARAM_PUB_KEY,
217
227k
                                           key->pubkey, key->keylen))
218
0
        return 0;
219
220
227k
    if (include_private
221
227k
        && key->privkey != NULL
222
227k
        && !ossl_param_build_set_octet_string(tmpl, params,
223
186k
                                              OSSL_PKEY_PARAM_PRIV_KEY,
224
186k
                                              key->privkey, key->keylen))
225
0
        return 0;
226
227
227k
    return 1;
228
227k
}
229
230
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
231
                      void *cbarg)
232
18.1k
{
233
18.1k
    ECX_KEY *key = keydata;
234
18.1k
    OSSL_PARAM_BLD *tmpl;
235
18.1k
    OSSL_PARAM *params = NULL;
236
18.1k
    int ret = 0;
237
238
18.1k
    if (!ossl_prov_is_running() || key == NULL)
239
0
        return 0;
240
241
18.1k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
242
0
        return 0;
243
244
18.1k
    tmpl = OSSL_PARAM_BLD_new();
245
18.1k
    if (tmpl == NULL)
246
0
        return 0;
247
248
18.1k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
249
18.1k
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
250
251
18.1k
        if (!key_to_params(key, tmpl, NULL, include_private))
252
0
            goto err;
253
18.1k
    }
254
255
18.1k
    params = OSSL_PARAM_BLD_to_param(tmpl);
256
18.1k
    if (params == NULL)
257
0
        goto err;
258
259
18.1k
    ret = param_cb(params, cbarg);
260
18.1k
    OSSL_PARAM_free(params);
261
18.1k
err:
262
18.1k
    OSSL_PARAM_BLD_free(tmpl);
263
18.1k
    return ret;
264
18.1k
}
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
122k
{
284
122k
    ECX_KEY *ecx = key;
285
122k
    OSSL_PARAM *p;
286
287
122k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
288
122k
        && !OSSL_PARAM_set_int(p, bits))
289
0
        return 0;
290
122k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
291
122k
        && !OSSL_PARAM_set_int(p, secbits))
292
0
        return 0;
293
122k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
294
122k
        && !OSSL_PARAM_set_int(p, size))
295
0
        return 0;
296
122k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
297
122k
            && (ecx->type == ECX_KEY_TYPE_X25519
298
71.9k
                || ecx->type == ECX_KEY_TYPE_X448)) {
299
71.9k
        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
300
0
            return 0;
301
71.9k
    }
302
303
122k
    return key_to_params(ecx, NULL, params, 1);
304
122k
}
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
1.03k
        && !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
205k
{
319
205k
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
320
205k
                          X25519_KEYLEN);
321
205k
}
322
323
static int x448_get_params(void *key, OSSL_PARAM params[])
324
2.90k
{
325
2.90k
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
326
2.90k
                          X448_KEYLEN);
327
2.90k
}
328
329
static int ed25519_get_params(void *key, OSSL_PARAM params[])
330
430
{
331
430
    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
332
430
                          ED25519_SIGSIZE)
333
430
        && ed_get_params(key, params);
334
430
}
335
336
static int ed448_get_params(void *key, OSSL_PARAM params[])
337
602
{
338
602
    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
339
602
                          ED448_SIGSIZE)
340
602
        && ed_get_params(key, params);
341
602
}
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
11.1k
{
397
11.1k
    ECX_KEY *ecxkey = key;
398
11.1k
    const OSSL_PARAM *p;
399
400
11.1k
    if (params == NULL)
401
0
        return 1;
402
403
11.1k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
404
11.1k
    if (p != NULL) {
405
11.1k
        void *buf = ecxkey->pubkey;
406
407
11.1k
        if (p->data_size != ecxkey->keylen
408
11.1k
                || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
409
11.1k
                                                NULL))
410
48
            return 0;
411
11.1k
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
412
11.1k
        ecxkey->privkey = NULL;
413
11.1k
        ecxkey->haspubkey = 1;
414
11.1k
    }
415
11.1k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
416
11.1k
    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
11.1k
    return 1;
423
11.1k
}
424
425
static int x25519_set_params(void *key, const OSSL_PARAM params[])
426
19.0k
{
427
19.0k
    return ecx_set_params(key, params);
428
19.0k
}
429
430
static int x448_set_params(void *key, const OSSL_PARAM params[])
431
29
{
432
29
    return ecx_set_params(key, params);
433
29
}
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
70.3k
{
478
70.3k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
479
70.3k
    struct ecx_gen_ctx *gctx = NULL;
480
481
70.3k
    if (!ossl_prov_is_running())
482
0
        return NULL;
483
484
70.3k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
485
70.3k
        gctx->libctx = libctx;
486
70.3k
        gctx->type = type;
487
70.3k
        gctx->selection = selection;
488
70.3k
    } else {
489
0
        return NULL;
490
0
    }
491
70.3k
    if (!ecx_gen_set_params(gctx, params)) {
492
0
        ecx_gen_cleanup(gctx);
493
0
        gctx = NULL;
494
0
    }
495
70.3k
    return gctx;
496
70.3k
}
497
498
static void *x25519_gen_init(void *provctx, int selection,
499
                             const OSSL_PARAM params[])
500
80.3k
{
501
80.3k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
502
80.3k
}
503
504
static void *x448_gen_init(void *provctx, int selection,
505
                           const OSSL_PARAM params[])
506
78
{
507
78
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
508
78
}
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
37.1k
{
524
37.1k
    struct ecx_gen_ctx *gctx = genctx;
525
37.1k
    const OSSL_PARAM *p;
526
527
37.1k
    if (gctx == NULL)
528
0
        return 0;
529
530
37.1k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
531
37.1k
    if (p != NULL) {
532
17.8k
        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
17.8k
        switch (gctx->type) {
540
17.8k
            case ECX_KEY_TYPE_X25519:
541
17.8k
                groupname = "x25519";
542
17.8k
                break;
543
29
            case ECX_KEY_TYPE_X448:
544
29
                groupname = "x448";
545
29
                break;
546
0
            default:
547
                /* We only support this for key exchange at the moment */
548
0
                break;
549
17.8k
        }
550
17.8k
        if (p->data_type != OSSL_PARAM_UTF8_STRING
551
17.8k
                || groupname == NULL
552
17.8k
                || 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
17.8k
    }
557
37.1k
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
558
37.1k
    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
37.1k
    return 1;
568
37.1k
}
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
19.2k
{
583
19.2k
    ECX_KEY *key;
584
19.2k
    unsigned char *privkey;
585
586
19.2k
    if (gctx == NULL)
587
0
        return NULL;
588
19.2k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
589
19.2k
                                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
19.2k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
596
3.07k
        return key;
597
598
16.1k
    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
16.1k
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
603
0
        goto err;
604
16.1k
    switch (gctx->type) {
605
16.1k
    case ECX_KEY_TYPE_X25519:
606
16.1k
        privkey[0] &= 248;
607
16.1k
        privkey[X25519_KEYLEN - 1] &= 127;
608
16.1k
        privkey[X25519_KEYLEN - 1] |= 64;
609
16.1k
        ossl_x25519_public_from_private(key->pubkey, privkey);
610
16.1k
        break;
611
23
    case ECX_KEY_TYPE_X448:
612
23
        privkey[0] &= 252;
613
23
        privkey[X448_KEYLEN - 1] |= 128;
614
23
        ossl_x448_public_from_private(key->pubkey, privkey);
615
23
        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
16.1k
    }
627
16.1k
    key->haspubkey = 1;
628
16.1k
    return key;
629
0
err:
630
0
    ossl_ecx_key_free(key);
631
0
    return NULL;
632
16.1k
}
633
634
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
635
80.3k
{
636
80.3k
    struct ecx_gen_ctx *gctx = genctx;
637
638
80.3k
    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
80.3k
    return ecx_gen(gctx);
646
80.3k
}
647
648
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
649
78
{
650
78
    struct ecx_gen_ctx *gctx = genctx;
651
652
78
    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
78
    return ecx_gen(gctx);
660
78
}
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
40.6k
{
697
40.6k
    struct ecx_gen_ctx *gctx = genctx;
698
699
40.6k
    OPENSSL_free(gctx->propq);
700
40.6k
    OPENSSL_free(gctx);
701
40.6k
}
702
703
void *ecx_load(const void *reference, size_t reference_sz)
704
3.74k
{
705
3.74k
    ECX_KEY *key = NULL;
706
707
3.74k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
708
        /* The contents of the reference is the address to our object */
709
3.74k
        key = *(ECX_KEY **)reference;
710
        /* We grabbed, so we detach it */
711
3.74k
        *(ECX_KEY **)reference = NULL;
712
3.74k
        return key;
713
3.74k
    }
714
0
    return NULL;
715
3.74k
}
716
717
static void *ecx_dup(const void *keydata_from, int selection)
718
12.8k
{
719
12.8k
    if (ossl_prov_is_running())
720
12.8k
        return ossl_ecx_key_dup(keydata_from, selection);
721
0
    return NULL;
722
12.8k
}
723
724
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
725
10
{
726
10
    uint8_t pub[64];
727
728
10
    switch (type) {
729
1
    case ECX_KEY_TYPE_X25519:
730
1
        ossl_x25519_public_from_private(pub, ecx->privkey);
731
1
        break;
732
1
    case ECX_KEY_TYPE_X448:
733
1
        ossl_x448_public_from_private(pub, ecx->privkey);
734
1
        break;
735
3
    case ECX_KEY_TYPE_ED25519:
736
3
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
737
3
                                              ecx->propq))
738
0
            return 0;
739
3
        break;
740
5
    case ECX_KEY_TYPE_ED448:
741
5
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
742
5
                                            ecx->propq))
743
0
            return 0;
744
5
        break;
745
5
    default:
746
0
        return 0;
747
10
    }
748
10
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
749
10
}
750
751
static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
752
8.91k
{
753
8.91k
    const ECX_KEY *ecx = keydata;
754
8.91k
    int ok = keylen == ecx->keylen;
755
756
8.91k
    if (!ossl_prov_is_running())
757
0
        return 0;
758
759
8.91k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
760
14
        return 1; /* nothing to validate */
761
762
8.90k
    if (!ok) {
763
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
764
0
        return 0;
765
0
    }
766
767
8.90k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
768
8.88k
        ok = ok && ecx->haspubkey;
769
770
8.90k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
771
28
        ok = ok && ecx->privkey != NULL;
772
773
8.90k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
774
14
        ok = ok && ecx_key_pairwise_check(ecx, type);
775
776
8.90k
    return ok;
777
8.90k
}
778
779
static int x25519_validate(const void *keydata, int selection, int checktype)
780
16.2k
{
781
16.2k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
782
16.2k
}
783
784
static int x448_validate(const void *keydata, int selection, int checktype)
785
29
{
786
29
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
787
29
}
788
789
static int ed25519_validate(const void *keydata, int selection, int checktype)
790
24
{
791
24
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
792
24
}
793
794
static int ed448_validate(const void *keydata, int selection, int checktype)
795
32
{
796
32
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
797
32
}
798
799
#define MAKE_KEYMGMT_FUNCTIONS(alg) \
800
    const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
801
        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
802
        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
803
        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
804
        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
805
        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
806
        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
807
        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
808
        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
809
        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
810
        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
811
        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
812
        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
813
        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
814
        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
815
        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
816
        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
817
          (void (*)(void))ecx_gen_settable_params }, \
818
        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
819
        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
820
        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
821
        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
822
        { 0, NULL } \
823
    };
824
825
MAKE_KEYMGMT_FUNCTIONS(x25519)
826
MAKE_KEYMGMT_FUNCTIONS(x448)
827
MAKE_KEYMGMT_FUNCTIONS(ed25519)
828
MAKE_KEYMGMT_FUNCTIONS(ed448)
829
830
#ifdef S390X_EC_ASM
831
# include "s390x_arch.h"
832
833
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
834
{
835
    static const unsigned char generator[] = {
836
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
837
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
838
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
839
    };
840
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
841
                                    gctx->propq);
842
    unsigned char *privkey = NULL, *pubkey;
843
844
    if (key == NULL) {
845
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
846
        goto err;
847
    }
848
849
    /* If we're doing parameter generation then we just return a blank key */
850
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
851
        return key;
852
853
    pubkey = key->pubkey;
854
855
    privkey = ossl_ecx_key_allocate_privkey(key);
856
    if (privkey == NULL) {
857
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
858
        goto err;
859
    }
860
861
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
862
        goto err;
863
864
    privkey[0] &= 248;
865
    privkey[31] &= 127;
866
    privkey[31] |= 64;
867
868
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
869
        goto err;
870
    key->haspubkey = 1;
871
    return key;
872
 err:
873
    ossl_ecx_key_free(key);
874
    return NULL;
875
}
876
877
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
878
{
879
    static const unsigned char generator[] = {
880
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
883
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
884
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
885
    };
886
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
887
                                    gctx->propq);
888
    unsigned char *privkey = NULL, *pubkey;
889
890
    if (key == NULL) {
891
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
892
        goto err;
893
    }
894
895
    /* If we're doing parameter generation then we just return a blank key */
896
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
897
        return key;
898
899
    pubkey = key->pubkey;
900
901
    privkey = ossl_ecx_key_allocate_privkey(key);
902
    if (privkey == NULL) {
903
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
904
        goto err;
905
    }
906
907
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
908
        goto err;
909
910
    privkey[0] &= 252;
911
    privkey[55] |= 128;
912
913
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
914
        goto err;
915
    key->haspubkey = 1;
916
    return key;
917
 err:
918
    ossl_ecx_key_free(key);
919
    return NULL;
920
}
921
922
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
923
{
924
    static const unsigned char generator_x[] = {
925
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
926
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
927
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
928
    };
929
    static const unsigned char generator_y[] = {
930
        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
931
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
932
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
933
    };
934
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
935
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
936
                                    gctx->propq);
937
    unsigned char *privkey = NULL, *pubkey;
938
    unsigned int sz;
939
    EVP_MD *sha = NULL;
940
    int j;
941
942
    if (key == NULL) {
943
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
944
        goto err;
945
    }
946
947
    /* If we're doing parameter generation then we just return a blank key */
948
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
949
        return key;
950
951
    pubkey = key->pubkey;
952
953
    privkey = ossl_ecx_key_allocate_privkey(key);
954
    if (privkey == NULL) {
955
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
956
        goto err;
957
    }
958
959
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
960
        goto err;
961
962
    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
963
    if (sha == NULL)
964
        goto err;
965
    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
966
    EVP_MD_free(sha);
967
    if (!j)
968
        goto err;
969
970
    buff[0] &= 248;
971
    buff[31] &= 63;
972
    buff[31] |= 64;
973
974
    if (s390x_ed25519_mul(x_dst, pubkey,
975
                          generator_x, generator_y, buff) != 1)
976
        goto err;
977
978
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
979
    key->haspubkey = 1;
980
    return key;
981
 err:
982
    ossl_ecx_key_free(key);
983
    return NULL;
984
}
985
986
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
987
{
988
    static const unsigned char generator_x[] = {
989
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
990
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
991
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
992
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
993
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
994
    };
995
    static const unsigned char generator_y[] = {
996
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
997
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
998
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
999
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1000
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1001
    };
1002
    unsigned char x_dst[57], buff[114];
1003
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1004
                                    gctx->propq);
1005
    unsigned char *privkey = NULL, *pubkey;
1006
    EVP_MD_CTX *hashctx = NULL;
1007
    EVP_MD *shake = NULL;
1008
1009
    if (key == NULL) {
1010
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1011
        goto err;
1012
    }
1013
1014
    /* If we're doing parameter generation then we just return a blank key */
1015
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1016
        return key;
1017
1018
    pubkey = key->pubkey;
1019
1020
    privkey = ossl_ecx_key_allocate_privkey(key);
1021
    if (privkey == NULL) {
1022
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1023
        goto err;
1024
    }
1025
1026
    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1027
    if (shake == NULL)
1028
        goto err;
1029
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1030
        goto err;
1031
1032
    hashctx = EVP_MD_CTX_new();
1033
    if (hashctx == NULL)
1034
        goto err;
1035
    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1036
        goto err;
1037
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1038
        goto err;
1039
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1040
        goto err;
1041
1042
    buff[0] &= -4;
1043
    buff[55] |= 0x80;
1044
    buff[56] = 0;
1045
1046
    if (s390x_ed448_mul(x_dst, pubkey,
1047
                        generator_x, generator_y, buff) != 1)
1048
        goto err;
1049
1050
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1051
    EVP_MD_CTX_free(hashctx);
1052
    EVP_MD_free(shake);
1053
    key->haspubkey = 1;
1054
    return key;
1055
 err:
1056
    ossl_ecx_key_free(key);
1057
    EVP_MD_CTX_free(hashctx);
1058
    EVP_MD_free(shake);
1059
    return NULL;
1060
}
1061
#endif