Coverage Report

Created: 2025-12-04 06:33

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