Coverage Report

Created: 2023-06-08 06:40

/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
0
#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
0
{
127
0
    const ECX_KEY *key = keydata;
128
0
    int ok = 0;
129
130
0
    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
0
        ok = 1;
136
137
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
138
0
            ok = ok && key->haspubkey;
139
140
0
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
141
0
            ok = ok && key->privkey != NULL;
142
0
    }
143
0
    return ok;
144
0
}
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
0
{
215
0
    if (key == NULL)
216
0
        return 0;
217
218
0
    if (!ossl_param_build_set_octet_string(tmpl, params,
219
0
                                           OSSL_PKEY_PARAM_PUB_KEY,
220
0
                                           key->pubkey, key->keylen))
221
0
        return 0;
222
223
0
    if (include_private
224
0
        && key->privkey != NULL
225
0
        && !ossl_param_build_set_octet_string(tmpl, params,
226
0
                                              OSSL_PKEY_PARAM_PRIV_KEY,
227
0
                                              key->privkey, key->keylen))
228
0
        return 0;
229
230
0
    return 1;
231
0
}
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
0
{
284
0
    ECX_KEY *ecx = key;
285
0
    OSSL_PARAM *p;
286
287
0
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
288
0
        && !OSSL_PARAM_set_int(p, bits))
289
0
        return 0;
290
0
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
291
0
        && !OSSL_PARAM_set_int(p, secbits))
292
0
        return 0;
293
0
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
294
0
        && !OSSL_PARAM_set_int(p, size))
295
0
        return 0;
296
0
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
297
0
            && (ecx->type == ECX_KEY_TYPE_X25519
298
0
                || ecx->type == ECX_KEY_TYPE_X448)) {
299
0
        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
300
0
            return 0;
301
0
    }
302
303
0
    return key_to_params(ecx, NULL, params, 1);
304
0
}
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
0
{
319
0
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
320
0
                          X25519_KEYLEN);
321
0
}
322
323
static int x448_get_params(void *key, OSSL_PARAM params[])
324
0
{
325
0
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
326
0
                          X448_KEYLEN);
327
0
}
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
0
{
395
0
    ECX_KEY *ecxkey = key;
396
0
    const OSSL_PARAM *p;
397
398
0
    if (params == NULL)
399
0
        return 1;
400
401
0
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
402
0
    if (p != NULL) {
403
0
        void *buf = ecxkey->pubkey;
404
405
0
        if (p->data_size != ecxkey->keylen
406
0
                || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
407
0
                                                NULL))
408
0
            return 0;
409
0
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
410
0
        ecxkey->privkey = NULL;
411
0
        ecxkey->haspubkey = 1;
412
0
    }
413
0
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
414
0
    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
0
    return 1;
421
0
}
422
423
static int x25519_set_params(void *key, const OSSL_PARAM params[])
424
0
{
425
0
    return ecx_set_params(key, params);
426
0
}
427
428
static int x448_set_params(void *key, const OSSL_PARAM params[])
429
0
{
430
0
    return ecx_set_params(key, params);
431
0
}
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
0
{
476
0
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
477
0
    struct ecx_gen_ctx *gctx = NULL;
478
479
0
    if (!ossl_prov_is_running())
480
0
        return NULL;
481
482
0
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
483
0
        gctx->libctx = libctx;
484
0
        gctx->type = type;
485
0
        gctx->selection = selection;
486
0
    }
487
0
    if (!ecx_gen_set_params(gctx, params)) {
488
0
        OPENSSL_free(gctx);
489
0
        gctx = NULL;
490
0
    }
491
0
    return gctx;
492
0
}
493
494
static void *x25519_gen_init(void *provctx, int selection,
495
                             const OSSL_PARAM params[])
496
0
{
497
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
498
0
}
499
500
static void *x448_gen_init(void *provctx, int selection,
501
                           const OSSL_PARAM params[])
502
0
{
503
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
504
0
}
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
0
{
520
0
    struct ecx_gen_ctx *gctx = genctx;
521
0
    const OSSL_PARAM *p;
522
523
0
    if (gctx == NULL)
524
0
        return 0;
525
526
0
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
527
0
    if (p != NULL) {
528
0
        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
0
        switch (gctx->type) {
536
0
            case ECX_KEY_TYPE_X25519:
537
0
                groupname = "x25519";
538
0
                break;
539
0
            case ECX_KEY_TYPE_X448:
540
0
                groupname = "x448";
541
0
                break;
542
0
            default:
543
                /* We only support this for key exchange at the moment */
544
0
                break;
545
0
        }
546
0
        if (p->data_type != OSSL_PARAM_UTF8_STRING
547
0
                || groupname == NULL
548
0
                || 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
0
    }
553
0
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
554
0
    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
0
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
563
0
    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
0
    return 1;
574
0
}
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
0
{
590
0
    ECX_KEY *key;
591
0
    unsigned char *privkey;
592
593
0
    if (gctx == NULL)
594
0
        return NULL;
595
0
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
596
0
                                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
0
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
603
0
        return key;
604
605
0
    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
0
#ifndef FIPS_MODULE
610
0
    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
0
#endif
619
0
    {
620
0
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
621
0
            goto err;
622
0
    }
623
624
0
    switch (gctx->type) {
625
0
    case ECX_KEY_TYPE_X25519:
626
0
        privkey[0] &= 248;
627
0
        privkey[X25519_KEYLEN - 1] &= 127;
628
0
        privkey[X25519_KEYLEN - 1] |= 64;
629
0
        ossl_x25519_public_from_private(key->pubkey, privkey);
630
0
        break;
631
0
    case ECX_KEY_TYPE_X448:
632
0
        privkey[0] &= 252;
633
0
        privkey[X448_KEYLEN - 1] |= 128;
634
0
        ossl_x448_public_from_private(key->pubkey, privkey);
635
0
        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
0
    }
647
0
    key->haspubkey = 1;
648
0
    return key;
649
0
err:
650
0
    ossl_ecx_key_free(key);
651
0
    return NULL;
652
0
}
653
654
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
655
0
{
656
0
    struct ecx_gen_ctx *gctx = genctx;
657
658
0
    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
0
    return ecx_gen(gctx);
666
0
}
667
668
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
669
0
{
670
0
    struct ecx_gen_ctx *gctx = genctx;
671
672
0
    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
0
    return ecx_gen(gctx);
680
0
}
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
0
{
717
0
    struct ecx_gen_ctx *gctx = genctx;
718
719
0
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
720
0
    OPENSSL_free(gctx->propq);
721
0
    OPENSSL_free(gctx);
722
0
}
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
0
{
740
0
    if (ossl_prov_is_running())
741
0
        return ossl_ecx_key_dup(keydata_from, selection);
742
0
    return NULL;
743
0
}
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
0
{
774
0
    const ECX_KEY *ecx = keydata;
775
0
    int ok = keylen == ecx->keylen;
776
777
0
    if (!ossl_prov_is_running())
778
0
        return 0;
779
780
0
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
781
0
        return 1; /* nothing to validate */
782
783
0
    if (!ok) {
784
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
785
0
        return 0;
786
0
    }
787
788
0
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
789
0
        ok = ok && ecx->haspubkey;
790
791
0
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
792
0
        ok = ok && ecx->privkey != NULL;
793
794
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
795
0
        ok = ok && ecx_key_pairwise_check(ecx, type);
796
797
0
    return ok;
798
0
}
799
800
static int x25519_validate(const void *keydata, int selection, int checktype)
801
0
{
802
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
803
0
}
804
805
static int x448_validate(const void *keydata, int selection, int checktype)
806
0
{
807
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
808
0
}
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