Coverage Report

Created: 2026-04-09 06:50

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