Coverage Report

Created: 2025-06-13 06:58

/src/openssl31/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_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
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
    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
10.1k
{
478
10.1k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
479
10.1k
    struct ecx_gen_ctx *gctx = NULL;
480
481
10.1k
    if (!ossl_prov_is_running())
482
0
        return NULL;
483
484
10.1k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
485
10.1k
        gctx->libctx = libctx;
486
10.1k
        gctx->type = type;
487
10.1k
        gctx->selection = selection;
488
10.1k
    }
489
10.1k
    if (!ecx_gen_set_params(gctx, params)) {
490
0
        ecx_gen_cleanup(gctx);
491
0
        gctx = NULL;
492
0
    }
493
10.1k
    return gctx;
494
10.1k
}
495
496
static void *x25519_gen_init(void *provctx, int selection,
497
                             const OSSL_PARAM params[])
498
80.3k
{
499
80.3k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
500
80.3k
}
501
502
static void *x448_gen_init(void *provctx, int selection,
503
                           const OSSL_PARAM params[])
504
78
{
505
78
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
506
78
}
507
508
static void *ed25519_gen_init(void *provctx, int selection,
509
                              const OSSL_PARAM params[])
510
0
{
511
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
512
0
}
513
514
static void *ed448_gen_init(void *provctx, int selection,
515
                            const OSSL_PARAM params[])
516
0
{
517
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
518
0
}
519
520
static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
521
37.1k
{
522
37.1k
    struct ecx_gen_ctx *gctx = genctx;
523
37.1k
    const OSSL_PARAM *p;
524
525
37.1k
    if (gctx == NULL)
526
0
        return 0;
527
528
37.1k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
529
37.1k
    if (p != NULL) {
530
17.8k
        const char *groupname = NULL;
531
532
        /*
533
         * We optionally allow setting a group name - but each algorithm only
534
         * support one such name, so all we do is verify that it is the one we
535
         * expected.
536
         */
537
17.8k
        switch (gctx->type) {
538
17.8k
            case ECX_KEY_TYPE_X25519:
539
17.8k
                groupname = "x25519";
540
17.8k
                break;
541
29
            case ECX_KEY_TYPE_X448:
542
29
                groupname = "x448";
543
29
                break;
544
0
            default:
545
                /* We only support this for key exchange at the moment */
546
0
                break;
547
17.8k
        }
548
17.8k
        if (p->data_type != OSSL_PARAM_UTF8_STRING
549
17.8k
                || groupname == NULL
550
17.8k
                || OPENSSL_strcasecmp(p->data, groupname) != 0) {
551
0
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
552
0
            return 0;
553
0
        }
554
17.8k
    }
555
37.1k
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
556
37.1k
    if (p != NULL) {
557
0
        if (p->data_type != OSSL_PARAM_UTF8_STRING)
558
0
            return 0;
559
0
        OPENSSL_free(gctx->propq);
560
0
        gctx->propq = OPENSSL_strdup(p->data);
561
0
        if (gctx->propq == NULL)
562
0
            return 0;
563
0
    }
564
565
37.1k
    return 1;
566
37.1k
}
567
568
static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
569
                                                 ossl_unused void *provctx)
570
0
{
571
0
    static OSSL_PARAM settable[] = {
572
0
        OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
573
0
        OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
574
0
        OSSL_PARAM_END
575
0
    };
576
0
    return settable;
577
0
}
578
579
static void *ecx_gen(struct ecx_gen_ctx *gctx)
580
19.2k
{
581
19.2k
    ECX_KEY *key;
582
19.2k
    unsigned char *privkey;
583
584
19.2k
    if (gctx == NULL)
585
0
        return NULL;
586
19.2k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
587
19.2k
                                gctx->propq)) == NULL) {
588
0
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
589
0
        return NULL;
590
0
    }
591
592
    /* If we're doing parameter generation then we just return a blank key */
593
19.2k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
594
3.07k
        return key;
595
596
16.1k
    if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
597
0
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
598
0
        goto err;
599
0
    }
600
16.1k
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
601
0
        goto err;
602
16.1k
    switch (gctx->type) {
603
16.1k
    case ECX_KEY_TYPE_X25519:
604
16.1k
        privkey[0] &= 248;
605
16.1k
        privkey[X25519_KEYLEN - 1] &= 127;
606
16.1k
        privkey[X25519_KEYLEN - 1] |= 64;
607
16.1k
        ossl_x25519_public_from_private(key->pubkey, privkey);
608
16.1k
        break;
609
23
    case ECX_KEY_TYPE_X448:
610
23
        privkey[0] &= 252;
611
23
        privkey[X448_KEYLEN - 1] |= 128;
612
23
        ossl_x448_public_from_private(key->pubkey, privkey);
613
23
        break;
614
0
    case ECX_KEY_TYPE_ED25519:
615
0
        if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
616
0
                                              gctx->propq))
617
0
            goto err;
618
0
        break;
619
0
    case ECX_KEY_TYPE_ED448:
620
0
        if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
621
0
                                            gctx->propq))
622
0
            goto err;
623
0
        break;
624
16.1k
    }
625
16.1k
    key->haspubkey = 1;
626
16.1k
    return key;
627
0
err:
628
0
    ossl_ecx_key_free(key);
629
0
    return NULL;
630
16.1k
}
631
632
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
633
80.3k
{
634
80.3k
    struct ecx_gen_ctx *gctx = genctx;
635
636
80.3k
    if (!ossl_prov_is_running())
637
0
        return 0;
638
639
#ifdef S390X_EC_ASM
640
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
641
        return s390x_ecx_keygen25519(gctx);
642
#endif
643
80.3k
    return ecx_gen(gctx);
644
80.3k
}
645
646
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
647
78
{
648
78
    struct ecx_gen_ctx *gctx = genctx;
649
650
78
    if (!ossl_prov_is_running())
651
0
        return 0;
652
653
#ifdef S390X_EC_ASM
654
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
655
        return s390x_ecx_keygen448(gctx);
656
#endif
657
78
    return ecx_gen(gctx);
658
78
}
659
660
static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
661
0
{
662
0
    struct ecx_gen_ctx *gctx = genctx;
663
664
0
    if (!ossl_prov_is_running())
665
0
        return 0;
666
667
#ifdef S390X_EC_ASM
668
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
669
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
670
        && OPENSSL_s390xcap_P.kdsa[0]
671
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
672
        return s390x_ecd_keygen25519(gctx);
673
#endif
674
0
    return ecx_gen(gctx);
675
0
}
676
677
static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
678
0
{
679
0
    struct ecx_gen_ctx *gctx = genctx;
680
681
0
    if (!ossl_prov_is_running())
682
0
        return 0;
683
684
#ifdef S390X_EC_ASM
685
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
686
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
687
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
688
        return s390x_ecd_keygen448(gctx);
689
#endif
690
0
    return ecx_gen(gctx);
691
0
}
692
693
static void ecx_gen_cleanup(void *genctx)
694
40.6k
{
695
40.6k
    struct ecx_gen_ctx *gctx = genctx;
696
697
40.6k
    OPENSSL_free(gctx->propq);
698
40.6k
    OPENSSL_free(gctx);
699
40.6k
}
700
701
void *ecx_load(const void *reference, size_t reference_sz)
702
3.74k
{
703
3.74k
    ECX_KEY *key = NULL;
704
705
3.74k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
706
        /* The contents of the reference is the address to our object */
707
3.74k
        key = *(ECX_KEY **)reference;
708
        /* We grabbed, so we detach it */
709
3.74k
        *(ECX_KEY **)reference = NULL;
710
3.74k
        return key;
711
3.74k
    }
712
0
    return NULL;
713
3.74k
}
714
715
static void *ecx_dup(const void *keydata_from, int selection)
716
12.8k
{
717
12.8k
    if (ossl_prov_is_running())
718
12.8k
        return ossl_ecx_key_dup(keydata_from, selection);
719
0
    return NULL;
720
12.8k
}
721
722
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
723
10
{
724
10
    uint8_t pub[64];
725
726
10
    switch (type) {
727
1
    case ECX_KEY_TYPE_X25519:
728
1
        ossl_x25519_public_from_private(pub, ecx->privkey);
729
1
        break;
730
1
    case ECX_KEY_TYPE_X448:
731
1
        ossl_x448_public_from_private(pub, ecx->privkey);
732
1
        break;
733
3
    case ECX_KEY_TYPE_ED25519:
734
3
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
735
3
                                              ecx->propq))
736
0
            return 0;
737
3
        break;
738
5
    case ECX_KEY_TYPE_ED448:
739
5
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
740
5
                                            ecx->propq))
741
0
            return 0;
742
5
        break;
743
5
    default:
744
0
        return 0;
745
10
    }
746
10
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
747
10
}
748
749
static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
750
8.91k
{
751
8.91k
    const ECX_KEY *ecx = keydata;
752
8.91k
    int ok = keylen == ecx->keylen;
753
754
8.91k
    if (!ossl_prov_is_running())
755
0
        return 0;
756
757
8.91k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
758
14
        return 1; /* nothing to validate */
759
760
8.90k
    if (!ok) {
761
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
762
0
        return 0;
763
0
    }
764
765
8.90k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
766
8.88k
        ok = ok && ecx->haspubkey;
767
768
8.90k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
769
28
        ok = ok && ecx->privkey != NULL;
770
771
8.90k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
772
14
        ok = ok && ecx_key_pairwise_check(ecx, type);
773
774
8.90k
    return ok;
775
8.90k
}
776
777
static int x25519_validate(const void *keydata, int selection, int checktype)
778
16.2k
{
779
16.2k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
780
16.2k
}
781
782
static int x448_validate(const void *keydata, int selection, int checktype)
783
29
{
784
29
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
785
29
}
786
787
static int ed25519_validate(const void *keydata, int selection, int checktype)
788
24
{
789
24
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
790
24
}
791
792
static int ed448_validate(const void *keydata, int selection, int checktype)
793
32
{
794
32
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
795
32
}
796
797
#define MAKE_KEYMGMT_FUNCTIONS(alg) \
798
    const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
799
        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
800
        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
801
        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
802
        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
803
        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
804
        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
805
        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
806
        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
807
        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
808
        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
809
        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
810
        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
811
        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
812
        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
813
        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
814
        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
815
          (void (*)(void))ecx_gen_settable_params }, \
816
        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
817
        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
818
        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
819
        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
820
        { 0, NULL } \
821
    };
822
823
MAKE_KEYMGMT_FUNCTIONS(x25519)
824
MAKE_KEYMGMT_FUNCTIONS(x448)
825
MAKE_KEYMGMT_FUNCTIONS(ed25519)
826
MAKE_KEYMGMT_FUNCTIONS(ed448)
827
828
#ifdef S390X_EC_ASM
829
# include "s390x_arch.h"
830
831
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
832
{
833
    static const unsigned char generator[] = {
834
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
837
    };
838
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
839
                                    gctx->propq);
840
    unsigned char *privkey = NULL, *pubkey;
841
842
    if (key == NULL) {
843
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
844
        goto err;
845
    }
846
847
    /* If we're doing parameter generation then we just return a blank key */
848
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
849
        return key;
850
851
    pubkey = key->pubkey;
852
853
    privkey = ossl_ecx_key_allocate_privkey(key);
854
    if (privkey == NULL) {
855
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
856
        goto err;
857
    }
858
859
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
860
        goto err;
861
862
    privkey[0] &= 248;
863
    privkey[31] &= 127;
864
    privkey[31] |= 64;
865
866
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
867
        goto err;
868
    key->haspubkey = 1;
869
    return key;
870
 err:
871
    ossl_ecx_key_free(key);
872
    return NULL;
873
}
874
875
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
876
{
877
    static const unsigned char generator[] = {
878
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880
        0x00, 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
883
    };
884
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
885
                                    gctx->propq);
886
    unsigned char *privkey = NULL, *pubkey;
887
888
    if (key == NULL) {
889
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
890
        goto err;
891
    }
892
893
    /* If we're doing parameter generation then we just return a blank key */
894
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
895
        return key;
896
897
    pubkey = key->pubkey;
898
899
    privkey = ossl_ecx_key_allocate_privkey(key);
900
    if (privkey == NULL) {
901
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
902
        goto err;
903
    }
904
905
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
906
        goto err;
907
908
    privkey[0] &= 252;
909
    privkey[55] |= 128;
910
911
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
912
        goto err;
913
    key->haspubkey = 1;
914
    return key;
915
 err:
916
    ossl_ecx_key_free(key);
917
    return NULL;
918
}
919
920
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
921
{
922
    static const unsigned char generator_x[] = {
923
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
924
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
925
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
926
    };
927
    static const unsigned char generator_y[] = {
928
        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
929
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
930
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
931
    };
932
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
933
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
934
                                    gctx->propq);
935
    unsigned char *privkey = NULL, *pubkey;
936
    unsigned int sz;
937
    EVP_MD *sha = NULL;
938
    int j;
939
940
    if (key == NULL) {
941
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
942
        goto err;
943
    }
944
945
    /* If we're doing parameter generation then we just return a blank key */
946
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
947
        return key;
948
949
    pubkey = key->pubkey;
950
951
    privkey = ossl_ecx_key_allocate_privkey(key);
952
    if (privkey == NULL) {
953
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
954
        goto err;
955
    }
956
957
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
958
        goto err;
959
960
    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
961
    if (sha == NULL)
962
        goto err;
963
    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
964
    EVP_MD_free(sha);
965
    if (!j)
966
        goto err;
967
968
    buff[0] &= 248;
969
    buff[31] &= 63;
970
    buff[31] |= 64;
971
972
    if (s390x_ed25519_mul(x_dst, pubkey,
973
                          generator_x, generator_y, buff) != 1)
974
        goto err;
975
976
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
977
    key->haspubkey = 1;
978
    return key;
979
 err:
980
    ossl_ecx_key_free(key);
981
    return NULL;
982
}
983
984
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
985
{
986
    static const unsigned char generator_x[] = {
987
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
988
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
989
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
990
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
991
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
992
    };
993
    static const unsigned char generator_y[] = {
994
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
995
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
996
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
997
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
998
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
999
    };
1000
    unsigned char x_dst[57], buff[114];
1001
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1002
                                    gctx->propq);
1003
    unsigned char *privkey = NULL, *pubkey;
1004
    EVP_MD_CTX *hashctx = NULL;
1005
    EVP_MD *shake = NULL;
1006
1007
    if (key == NULL) {
1008
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1009
        goto err;
1010
    }
1011
1012
    /* If we're doing parameter generation then we just return a blank key */
1013
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1014
        return key;
1015
1016
    pubkey = key->pubkey;
1017
1018
    privkey = ossl_ecx_key_allocate_privkey(key);
1019
    if (privkey == NULL) {
1020
        ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1021
        goto err;
1022
    }
1023
1024
    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1025
    if (shake == NULL)
1026
        goto err;
1027
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1028
        goto err;
1029
1030
    hashctx = EVP_MD_CTX_new();
1031
    if (hashctx == NULL)
1032
        goto err;
1033
    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1034
        goto err;
1035
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1036
        goto err;
1037
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1038
        goto err;
1039
1040
    buff[0] &= -4;
1041
    buff[55] |= 0x80;
1042
    buff[56] = 0;
1043
1044
    if (s390x_ed448_mul(x_dst, pubkey,
1045
                        generator_x, generator_y, buff) != 1)
1046
        goto err;
1047
1048
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1049
    EVP_MD_CTX_free(hashctx);
1050
    EVP_MD_free(shake);
1051
    key->haspubkey = 1;
1052
    return key;
1053
 err:
1054
    ossl_ecx_key_free(key);
1055
    EVP_MD_CTX_free(hashctx);
1056
    EVP_MD_free(shake);
1057
    return NULL;
1058
}
1059
#endif