Coverage Report

Created: 2023-06-08 06:41

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