Coverage Report

Created: 2026-05-20 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/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 <openssl/self_test.h>
20
#include "internal/fips.h"
21
#include "internal/param_build_set.h"
22
#include <openssl/param_build.h>
23
#include "crypto/ecx.h"
24
#include "prov/implementations.h"
25
#include "prov/providercommon.h"
26
#include "prov/provider_ctx.h"
27
#include "prov/ecx.h"
28
#include "prov/securitycheck.h"
29
#ifdef S390X_EC_ASM
30
#include "arch/s390x_arch.h"
31
#include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
32
#endif
33
34
static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
35
static OSSL_FUNC_keymgmt_new_fn x448_new_key;
36
static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
37
static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
38
static OSSL_FUNC_keymgmt_free_fn ecx_free_key;
39
static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
40
static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
41
static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
42
static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
43
static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
44
static OSSL_FUNC_keymgmt_gen_fn x448_gen;
45
static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
46
static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
47
static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
48
static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
49
static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
50
static OSSL_FUNC_keymgmt_load_fn ecx_load;
51
static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
52
static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
53
static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
54
static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
55
static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
56
static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
57
static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
58
static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
59
static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
60
static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
61
static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
62
static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
63
static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
64
static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
65
static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
66
static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
67
static OSSL_FUNC_keymgmt_has_fn ecx_has;
68
static OSSL_FUNC_keymgmt_match_fn ecx_match;
69
static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
70
static OSSL_FUNC_keymgmt_validate_fn x448_validate;
71
static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
72
static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
73
static OSSL_FUNC_keymgmt_import_fn ecx_import;
74
static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
75
static OSSL_FUNC_keymgmt_export_fn ecx_export;
76
static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
77
static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
78
79
0
#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
80
81
struct ecx_gen_ctx {
82
    OSSL_LIB_CTX *libctx;
83
    char *propq;
84
    ECX_KEY_TYPE type;
85
    int selection;
86
    unsigned char *dhkem_ikm;
87
    size_t dhkem_ikmlen;
88
};
89
90
#ifdef S390X_EC_ASM
91
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
92
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
93
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
94
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
95
#endif
96
97
#ifdef FIPS_MODULE
98
static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test);
99
#endif /* FIPS_MODULE */
100
101
static ossl_inline int ecx_key_type_is_ed(ECX_KEY_TYPE type)
102
0
{
103
0
    return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448;
104
0
}
105
106
static void *x25519_new_key(void *provctx)
107
0
{
108
0
    if (!ossl_prov_is_running())
109
0
        return 0;
110
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
111
0
        NULL);
112
0
}
113
114
static void *x448_new_key(void *provctx)
115
0
{
116
0
    if (!ossl_prov_is_running())
117
0
        return 0;
118
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
119
0
        NULL);
120
0
}
121
122
static void *ed25519_new_key(void *provctx)
123
0
{
124
0
    if (!ossl_prov_is_running())
125
0
        return 0;
126
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
127
0
        NULL);
128
0
}
129
130
static void *ed448_new_key(void *provctx)
131
0
{
132
0
    if (!ossl_prov_is_running())
133
0
        return 0;
134
0
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
135
0
        NULL);
136
0
}
137
138
static int ecx_has(const void *keydata, int selection)
139
0
{
140
0
    const ECX_KEY *key = keydata;
141
0
    int ok = 0;
142
143
0
    if (ossl_prov_is_running() && key != NULL) {
144
        /*
145
         * ECX keys always have all the parameters they need (i.e. none).
146
         * Therefore we always return with 1, if asked about parameters.
147
         */
148
0
        ok = 1;
149
150
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
151
0
            ok = ok && key->haspubkey;
152
153
0
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
154
0
            ok = ok && key->privkey != NULL;
155
0
    }
156
0
    return ok;
157
0
}
158
159
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
160
0
{
161
0
    const ECX_KEY *key1 = keydata1;
162
0
    const ECX_KEY *key2 = keydata2;
163
0
    int ok = 1;
164
165
0
    if (!ossl_prov_is_running())
166
0
        return 0;
167
168
0
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
169
0
        ok = ok && key1->type == key2->type;
170
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
171
0
        int key_checked = 0;
172
173
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
174
0
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
175
0
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
176
0
            size_t pal = key1->keylen;
177
0
            size_t pbl = key2->keylen;
178
179
0
            if (pa != NULL && pb != NULL) {
180
0
                ok = ok
181
0
                    && key1->type == key2->type
182
0
                    && pal == pbl
183
0
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
184
0
                key_checked = 1;
185
0
            }
186
0
        }
187
0
        if (!key_checked
188
0
            && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
189
0
            const unsigned char *pa = key1->privkey;
190
0
            const unsigned char *pb = key2->privkey;
191
0
            size_t pal = key1->keylen;
192
0
            size_t pbl = key2->keylen;
193
194
0
            if (pa != NULL && pb != NULL) {
195
0
                ok = ok
196
0
                    && key1->type == key2->type
197
0
                    && pal == pbl
198
0
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
199
0
                key_checked = 1;
200
0
            }
201
0
        }
202
0
        ok = ok && key_checked;
203
0
    }
204
0
    return ok;
205
0
}
206
207
struct ecx_ed_common_get_params_st {
208
    OSSL_PARAM *bits;
209
    OSSL_PARAM *secbits;
210
    OSSL_PARAM *size;
211
    OSSL_PARAM *seccat;
212
    OSSL_PARAM *pub;
213
    OSSL_PARAM *priv;
214
    OSSL_PARAM *encpub; /* ECX only */
215
    OSSL_PARAM *ind; /* ECX only */
216
    OSSL_PARAM *digest; /* Ed only */
217
};
218
219
#define ecx_get_params_st ecx_ed_common_get_params_st
220
#define ed_get_params_st ecx_ed_common_get_params_st
221
222
#include "providers/implementations/keymgmt/ecx_kmgmt.inc"
223
224
static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
225
0
{
226
0
    ECX_KEY *key = keydata;
227
0
    int ok = 1;
228
0
    int include_private;
229
0
    struct ecx_imexport_types_st p;
230
231
0
    if (!ossl_prov_is_running()
232
0
        || key == NULL
233
0
        || !ecx_imexport_types_decoder(params, &p))
234
0
        return 0;
235
236
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
237
0
        return 0;
238
239
0
    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
240
0
    ok = ok && ossl_ecx_key_fromdata(key, p.pub, p.priv, include_private);
241
242
0
    return ok;
243
0
}
244
245
static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
246
    OSSL_PARAM *pub, OSSL_PARAM *priv, int include_private)
247
0
{
248
0
    if (key == NULL)
249
0
        return 0;
250
251
0
    if (!ossl_param_build_set_octet_string(tmpl, pub,
252
0
            OSSL_PKEY_PARAM_PUB_KEY,
253
0
            key->pubkey, key->keylen))
254
0
        return 0;
255
256
0
    if (include_private
257
0
        && key->privkey != NULL
258
0
        && !ossl_param_build_set_octet_string(tmpl, priv,
259
0
            OSSL_PKEY_PARAM_PRIV_KEY,
260
0
            key->privkey, key->keylen))
261
0
        return 0;
262
263
0
    return 1;
264
0
}
265
266
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
267
    void *cbarg)
268
0
{
269
0
    ECX_KEY *key = keydata;
270
0
    OSSL_PARAM_BLD *tmpl;
271
0
    OSSL_PARAM *params = NULL;
272
0
    int ret = 0;
273
274
0
    if (!ossl_prov_is_running() || key == NULL)
275
0
        return 0;
276
277
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
278
0
        return 0;
279
280
0
    tmpl = OSSL_PARAM_BLD_new();
281
0
    if (tmpl == NULL)
282
0
        return 0;
283
284
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
285
0
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
286
287
0
        if (!key_to_params(key, tmpl, NULL, NULL, include_private))
288
0
            goto err;
289
0
    }
290
291
0
    params = OSSL_PARAM_BLD_to_param(tmpl);
292
0
    if (params == NULL)
293
0
        goto err;
294
295
0
    ret = param_cb(params, cbarg);
296
0
    OSSL_PARAM_clear_free(params);
297
0
err:
298
0
    OSSL_PARAM_BLD_free(tmpl);
299
0
    return ret;
300
0
}
301
302
static const OSSL_PARAM *ecx_imexport_types(int selection)
303
0
{
304
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
305
0
        return ecx_imexport_types_list;
306
0
    return NULL;
307
0
}
308
309
/* This getter is shared by ED25519, ED448, X25519 and X448 */
310
static int ecx_ed_common_get_params(void *key,
311
    const struct ecx_ed_common_get_params_st *p,
312
    int bits, int secbits, int size)
313
0
{
314
0
    ECX_KEY *ecx = key;
315
316
0
    if (p->bits != NULL && !OSSL_PARAM_set_int(p->bits, bits))
317
0
        return 0;
318
0
    if (p->secbits != NULL && !OSSL_PARAM_set_int(p->secbits, secbits))
319
0
        return 0;
320
0
    if (p->size != NULL && !OSSL_PARAM_set_int(p->size, size))
321
0
        return 0;
322
0
    if (p->seccat != NULL && !OSSL_PARAM_set_int(p->seccat, 0))
323
0
        return 0;
324
0
    return key_to_params(ecx, NULL, p->pub, p->priv, 1);
325
0
}
326
327
/* X25519/X448 getter */
328
static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
329
    int size)
330
0
{
331
0
    ECX_KEY *ecx = key;
332
0
    struct ecx_ed_common_get_params_st p;
333
334
0
    if (key == NULL || !ecx_get_params_decoder(params, &p))
335
0
        return 0;
336
337
0
    if (p.encpub != NULL
338
0
        && !OSSL_PARAM_set_octet_string(p.encpub, ecx->pubkey, ecx->keylen))
339
0
        return 0;
340
#ifdef FIPS_MODULE
341
    {
342
        /* Currently X25519 and X448 are not approved */
343
        int approved = 0;
344
345
        if (p.ind != NULL && !OSSL_PARAM_set_int(p.ind, approved))
346
            return 0;
347
    }
348
#endif
349
350
0
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
351
0
}
352
353
/* ED25519/ED448 getter */
354
static int ed_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
355
    int size)
356
0
{
357
0
    struct ecx_ed_common_get_params_st p;
358
359
0
    if (key == NULL || !ed_get_params_decoder(params, &p))
360
0
        return 0;
361
0
    if (p.digest != NULL && !OSSL_PARAM_set_utf8_string(p.digest, ""))
362
0
        return 0;
363
0
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
364
0
}
365
366
static int x25519_get_params(void *key, OSSL_PARAM params[])
367
0
{
368
0
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
369
0
        X25519_KEYLEN);
370
0
}
371
372
static int x448_get_params(void *key, OSSL_PARAM params[])
373
0
{
374
0
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
375
0
        X448_KEYLEN);
376
0
}
377
378
static int ed25519_get_params(void *key, OSSL_PARAM params[])
379
0
{
380
0
    return ed_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
381
0
        ED25519_SIGSIZE);
382
0
}
383
static int ed448_get_params(void *key, OSSL_PARAM params[])
384
0
{
385
0
    return ed_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
386
0
        ED448_SIGSIZE);
387
0
}
388
389
static const OSSL_PARAM *x25519_gettable_params(void *provctx)
390
0
{
391
0
    return ecx_get_params_list;
392
0
}
393
394
static const OSSL_PARAM *x448_gettable_params(void *provctx)
395
0
{
396
0
    return ecx_get_params_list;
397
0
}
398
399
static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
400
0
{
401
0
    return ed_get_params_list;
402
0
}
403
404
static const OSSL_PARAM *ed448_gettable_params(void *provctx)
405
0
{
406
0
    return ed_get_params_list;
407
0
}
408
409
static int set_property_query(ECX_KEY *ecxkey, const char *propq)
410
0
{
411
0
    OPENSSL_free(ecxkey->propq);
412
0
    ecxkey->propq = NULL;
413
0
    if (propq != NULL) {
414
0
        ecxkey->propq = OPENSSL_strdup(propq);
415
0
        if (ecxkey->propq == NULL)
416
0
            return 0;
417
0
    }
418
0
    return 1;
419
0
}
420
421
static int ecx_set_params(void *key, const OSSL_PARAM params[])
422
0
{
423
0
    ECX_KEY *ecxkey = key;
424
0
    struct ecx_set_params_st p;
425
426
0
    if (key == NULL || !ecx_set_params_decoder(params, &p))
427
0
        return 0;
428
429
0
    if (p.pub != NULL) {
430
0
        void *buf = ecxkey->pubkey;
431
432
0
        if (p.pub->data_size != ecxkey->keylen
433
0
            || !OSSL_PARAM_get_octet_string(p.pub, &buf, sizeof(ecxkey->pubkey),
434
0
                NULL))
435
0
            return 0;
436
0
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
437
0
        ecxkey->privkey = NULL;
438
0
        ecxkey->haspubkey = 1;
439
0
    }
440
441
0
    if (p.propq != NULL) {
442
0
        if (p.propq->data_type != OSSL_PARAM_UTF8_STRING
443
0
            || !set_property_query(ecxkey, p.propq->data))
444
0
            return 0;
445
0
    }
446
447
0
    return 1;
448
0
}
449
450
static int x25519_set_params(void *key, const OSSL_PARAM params[])
451
0
{
452
0
    return ecx_set_params(key, params);
453
0
}
454
455
static int x448_set_params(void *key, const OSSL_PARAM params[])
456
0
{
457
0
    return ecx_set_params(key, params);
458
0
}
459
460
static int ed25519_set_params(void *key, const OSSL_PARAM params[])
461
0
{
462
0
    return 1;
463
0
}
464
465
static int ed448_set_params(void *key, const OSSL_PARAM params[])
466
0
{
467
0
    return 1;
468
0
}
469
470
static const OSSL_PARAM ed_settable_params[] = {
471
    OSSL_PARAM_END
472
};
473
474
static const OSSL_PARAM *x25519_settable_params(void *provctx)
475
0
{
476
0
    return ecx_set_params_list;
477
0
}
478
479
static const OSSL_PARAM *x448_settable_params(void *provctx)
480
0
{
481
0
    return ecx_set_params_list;
482
0
}
483
484
static const OSSL_PARAM *ed25519_settable_params(void *provctx)
485
0
{
486
0
    return ed_settable_params;
487
0
}
488
489
static const OSSL_PARAM *ed448_settable_params(void *provctx)
490
0
{
491
0
    return ed_settable_params;
492
0
}
493
494
static void *ecx_gen_init(void *provctx, int selection,
495
    const OSSL_PARAM params[], ECX_KEY_TYPE type,
496
    const char *algdesc)
497
0
{
498
0
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
499
0
    struct ecx_gen_ctx *gctx = NULL;
500
501
0
    if (!ossl_prov_is_running())
502
0
        return NULL;
503
504
0
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
505
0
        gctx->libctx = libctx;
506
0
        gctx->type = type;
507
0
        gctx->selection = selection;
508
#ifdef FIPS_MODULE
509
        /* X25519/X448 are not FIPS approved, (ED25519/ED448 are approved) */
510
        if (algdesc != NULL
511
            && !ossl_FIPS_IND_callback(libctx, algdesc, "KeyGen Init")) {
512
            OPENSSL_free(gctx);
513
            return NULL;
514
        }
515
#endif
516
0
    } else {
517
0
        return NULL;
518
0
    }
519
0
    if (!ecx_gen_set_params(gctx, params)) {
520
0
        ecx_gen_cleanup(gctx);
521
0
        gctx = NULL;
522
0
    }
523
0
    return gctx;
524
0
}
525
526
static void *x25519_gen_init(void *provctx, int selection,
527
    const OSSL_PARAM params[])
528
0
{
529
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
530
0
}
531
532
static void *x448_gen_init(void *provctx, int selection,
533
    const OSSL_PARAM params[])
534
0
{
535
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
536
0
}
537
538
static void *ed25519_gen_init(void *provctx, int selection,
539
    const OSSL_PARAM params[])
540
0
{
541
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519, NULL);
542
0
}
543
544
static void *ed448_gen_init(void *provctx, int selection,
545
    const OSSL_PARAM params[])
546
0
{
547
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448, NULL);
548
0
}
549
550
static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
551
0
{
552
0
    struct ecx_gen_ctx *gctx = genctx;
553
0
    struct ecx_gen_set_params_st p;
554
555
0
    if (gctx == NULL || !ecx_gen_set_params_decoder(params, &p))
556
0
        return 0;
557
558
0
    if (p.group != NULL) {
559
0
        const char *groupname = NULL;
560
561
        /*
562
         * We optionally allow setting a group name - but each algorithm only
563
         * support one such name, so all we do is verify that it is the one we
564
         * expected.
565
         */
566
0
        switch (gctx->type) {
567
0
        case ECX_KEY_TYPE_X25519:
568
0
            groupname = "x25519";
569
0
            break;
570
0
        case ECX_KEY_TYPE_X448:
571
0
            groupname = "x448";
572
0
            break;
573
0
        default:
574
            /* We only support this for key exchange at the moment */
575
0
            break;
576
0
        }
577
0
        if (p.group->data_type != OSSL_PARAM_UTF8_STRING
578
0
            || groupname == NULL
579
0
            || OPENSSL_strcasecmp(p.group->data, groupname) != 0) {
580
0
            ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
581
0
            return 0;
582
0
        }
583
0
    }
584
585
0
    if (p.kdfpropq != NULL) {
586
0
        if (p.kdfpropq->data_type != OSSL_PARAM_UTF8_STRING)
587
0
            return 0;
588
0
        OPENSSL_free(gctx->propq);
589
0
        gctx->propq = OPENSSL_strdup(p.kdfpropq->data);
590
0
        if (gctx->propq == NULL)
591
0
            return 0;
592
0
    }
593
594
0
    if (p.ikm != NULL) {
595
0
        if (p.ikm->data_size != 0 && p.ikm->data != NULL) {
596
0
            OPENSSL_free(gctx->dhkem_ikm);
597
0
            gctx->dhkem_ikm = NULL;
598
0
            if (!OSSL_PARAM_get_octet_string(p.ikm, (void **)&gctx->dhkem_ikm, 0,
599
0
                    &gctx->dhkem_ikmlen))
600
0
                return 0;
601
0
        }
602
0
    }
603
604
0
    return 1;
605
0
}
606
607
static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
608
    ossl_unused void *provctx)
609
0
{
610
0
    return ecx_gen_set_params_list;
611
0
}
612
613
#ifdef FIPS_MODULE
614
/*
615
 * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1
616
 * Perform a pairwise test for EDDSA by signing and verifying signature.
617
 *
618
 * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST
619
 * instance.
620
 */
621
static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test)
622
{
623
    int ret = 0;
624
    OSSL_SELF_TEST *st = NULL;
625
    OSSL_CALLBACK *cb = NULL;
626
    void *cbarg = NULL;
627
628
    unsigned char msg[16] = { 0 };
629
    size_t msg_len = sizeof(msg);
630
    unsigned char sig[ED448_SIGSIZE] = { 0 };
631
632
    int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0;
633
    int operation_result = 0;
634
635
    /*
636
     * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
637
     * is NULL.
638
     */
639
    if (self_test) {
640
        OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg);
641
642
        st = OSSL_SELF_TEST_new(cb, cbarg);
643
        if (st == NULL)
644
            return 0;
645
    }
646
647
    OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
648
        OSSL_SELF_TEST_DESC_PCT_EDDSA);
649
650
    if (is_ed25519)
651
        operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey,
652
            ecx->privkey, 0, 0, 0, NULL, 0,
653
            ecx->libctx, ecx->propq);
654
    else
655
        operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len,
656
            ecx->pubkey, ecx->privkey, NULL, 0,
657
            0, ecx->propq);
658
    if (operation_result != 1)
659
        goto err;
660
661
    OSSL_SELF_TEST_oncorrupt_byte(st, sig);
662
663
    if (is_ed25519)
664
        operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey,
665
            0, 0, 0, NULL, 0, ecx->libctx,
666
            ecx->propq);
667
    else
668
        operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig,
669
            ecx->pubkey, NULL, 0, 0, ecx->propq);
670
    if (operation_result != 1)
671
        goto err;
672
673
    ret = 1;
674
err:
675
    OSSL_SELF_TEST_onend(st, ret);
676
    OSSL_SELF_TEST_free(st);
677
    return ret;
678
}
679
#endif
680
681
static void *ecx_gen(struct ecx_gen_ctx *gctx)
682
0
{
683
0
    ECX_KEY *key;
684
0
    unsigned char *privkey;
685
686
0
    if (gctx == NULL)
687
0
        return NULL;
688
0
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
689
0
             gctx->propq))
690
0
        == NULL) {
691
0
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
692
0
        return NULL;
693
0
    }
694
695
    /* If we're doing parameter generation then we just return a blank key */
696
0
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
697
0
        return key;
698
699
0
    if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
700
0
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
701
0
        goto err;
702
0
    }
703
0
#ifndef FIPS_MODULE
704
0
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
705
0
        if (ecx_key_type_is_ed(gctx->type))
706
0
            goto err;
707
0
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
708
0
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
709
0
            goto err;
710
0
    } else
711
0
#endif
712
0
    {
713
0
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
714
0
            goto err;
715
0
    }
716
717
0
    switch (gctx->type) {
718
0
    case ECX_KEY_TYPE_X25519:
719
0
        privkey[0] &= 248;
720
0
        privkey[X25519_KEYLEN - 1] &= 127;
721
0
        privkey[X25519_KEYLEN - 1] |= 64;
722
0
        ossl_x25519_public_from_private(key->pubkey, privkey);
723
0
        break;
724
0
    case ECX_KEY_TYPE_X448:
725
0
        privkey[0] &= 252;
726
0
        privkey[X448_KEYLEN - 1] |= 128;
727
0
        ossl_x448_public_from_private(key->pubkey, privkey);
728
0
        break;
729
0
    case ECX_KEY_TYPE_ED25519:
730
0
        if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
731
0
                gctx->propq))
732
0
            goto err;
733
0
        break;
734
0
    case ECX_KEY_TYPE_ED448:
735
0
        if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
736
0
                gctx->propq))
737
0
            goto err;
738
0
        break;
739
0
    }
740
0
    key->haspubkey = 1;
741
0
    return key;
742
0
err:
743
0
    ossl_ecx_key_free(key);
744
0
    return NULL;
745
0
}
746
747
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
748
0
{
749
0
    struct ecx_gen_ctx *gctx = genctx;
750
751
0
    if (!ossl_prov_is_running())
752
0
        return 0;
753
754
#ifdef S390X_EC_ASM
755
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
756
        return s390x_ecx_keygen25519(gctx);
757
#endif
758
0
    return ecx_gen(gctx);
759
0
}
760
761
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
762
0
{
763
0
    struct ecx_gen_ctx *gctx = genctx;
764
765
0
    if (!ossl_prov_is_running())
766
0
        return 0;
767
768
#ifdef S390X_EC_ASM
769
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
770
        return s390x_ecx_keygen448(gctx);
771
#endif
772
0
    return ecx_gen(gctx);
773
0
}
774
775
static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
776
0
{
777
0
    ECX_KEY *key = NULL;
778
0
    struct ecx_gen_ctx *gctx = genctx;
779
780
0
    if (!ossl_prov_is_running())
781
0
        return 0;
782
783
#ifdef S390X_EC_ASM
784
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
785
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
786
        && OPENSSL_s390xcap_P.kdsa[0]
787
            & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) {
788
        key = s390x_ecd_keygen25519(gctx);
789
    } else
790
#endif
791
0
    {
792
0
        key = ecx_gen(gctx);
793
0
    }
794
795
#ifdef FIPS_MODULE
796
    /* Exit if keygen failed OR we are doing parameter generation (blank key) */
797
    if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
798
        return key;
799
    if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) {
800
        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
801
        ossl_ecx_key_free(key);
802
        return NULL;
803
    }
804
#endif
805
806
0
    return key;
807
0
}
808
809
static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
810
0
{
811
0
    ECX_KEY *key = NULL;
812
0
    struct ecx_gen_ctx *gctx = genctx;
813
814
0
    if (!ossl_prov_is_running())
815
0
        return 0;
816
817
#ifdef S390X_EC_ASM
818
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
819
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
820
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) {
821
        key = s390x_ecd_keygen448(gctx);
822
    } else
823
#endif
824
0
    {
825
0
        key = ecx_gen(gctx);
826
0
    }
827
828
#ifdef FIPS_MODULE
829
    /* Exit if keygen failed OR we are doing parameter generation (blank key) */
830
    if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
831
        return key;
832
    if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
833
        ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
834
        ossl_ecx_key_free(key);
835
        return NULL;
836
    }
837
#endif
838
839
0
    return key;
840
0
}
841
842
static void ecx_gen_cleanup(void *genctx)
843
0
{
844
0
    struct ecx_gen_ctx *gctx = genctx;
845
846
0
    if (gctx == NULL)
847
0
        return;
848
849
0
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
850
0
    OPENSSL_free(gctx->propq);
851
0
    OPENSSL_free(gctx);
852
0
}
853
854
void *ecx_load(const void *reference, size_t reference_sz)
855
0
{
856
0
    ECX_KEY *key = NULL;
857
858
0
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
859
        /* The contents of the reference is the address to our object */
860
0
        key = *(ECX_KEY **)reference;
861
        /* We grabbed, so we detach it */
862
0
        *(ECX_KEY **)reference = NULL;
863
0
        return key;
864
0
    }
865
0
    return NULL;
866
0
}
867
868
static void *ecx_dup(const void *keydata_from, int selection)
869
0
{
870
0
    if (ossl_prov_is_running())
871
0
        return ossl_ecx_key_dup(keydata_from, selection);
872
0
    return NULL;
873
0
}
874
875
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
876
0
{
877
0
    uint8_t pub[64];
878
879
0
    switch (type) {
880
0
    case ECX_KEY_TYPE_X25519:
881
0
        ossl_x25519_public_from_private(pub, ecx->privkey);
882
0
        break;
883
0
    case ECX_KEY_TYPE_X448:
884
0
        ossl_x448_public_from_private(pub, ecx->privkey);
885
0
        break;
886
0
    default:
887
0
        return 0;
888
0
    }
889
0
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
890
0
}
891
892
#ifdef FIPS_MODULE
893
/*
894
 * FIPS ACVP testing requires the ability to check if the public key is valid
895
 * This is not required normally since the ED signature verify does the test
896
 * internally.
897
 */
898
static int ecd_key_pub_check(const ECX_KEY *ecx, int type)
899
{
900
    switch (type) {
901
    case ECX_KEY_TYPE_ED25519:
902
        return ossl_ed25519_pubkey_verify(ecx->pubkey, ecx->keylen);
903
    case ECX_KEY_TYPE_ED448:
904
        return ossl_ed448_pubkey_verify(ecx->pubkey, ecx->keylen);
905
    default:
906
        return 1;
907
    }
908
}
909
#endif
910
911
#ifdef FIPS_MODULE
912
static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
913
{
914
    return ecd_fips140_pairwise_test(ecx, type, 0);
915
}
916
#else
917
static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
918
0
{
919
0
    uint8_t pub[64];
920
921
0
    switch (type) {
922
0
    case ECX_KEY_TYPE_ED25519:
923
0
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
924
0
                ecx->propq))
925
0
            return 0;
926
0
        break;
927
0
    case ECX_KEY_TYPE_ED448:
928
0
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
929
0
                ecx->propq))
930
0
            return 0;
931
0
        break;
932
0
    default:
933
0
        return 0;
934
0
    }
935
0
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
936
0
}
937
#endif
938
939
static int ecx_validate(const void *keydata, int selection, int type,
940
    size_t keylen)
941
0
{
942
0
    const ECX_KEY *ecx = keydata;
943
0
    int ok = keylen == ecx->keylen;
944
945
0
    if (!ossl_prov_is_running())
946
0
        return 0;
947
948
0
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
949
0
        return 1; /* nothing to validate */
950
951
0
    if (!ok) {
952
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
953
0
        return 0;
954
0
    }
955
956
0
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
957
0
        ok = ok && ecx->haspubkey;
958
#ifdef FIPS_MODULE
959
        ok = ok && ecd_key_pub_check(ecx, type);
960
#endif
961
0
    }
962
963
0
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
964
0
        ok = ok && ecx->privkey != NULL;
965
966
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
967
0
        return ok;
968
969
0
    if (ecx_key_type_is_ed(type))
970
0
        ok = ok && ecd_key_pairwise_check(ecx, type);
971
0
    else
972
0
        ok = ok && ecx_key_pairwise_check(ecx, type);
973
974
0
    return ok;
975
0
}
976
977
static int x25519_validate(const void *keydata, int selection, int checktype)
978
0
{
979
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
980
0
}
981
982
static int x448_validate(const void *keydata, int selection, int checktype)
983
0
{
984
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
985
0
}
986
987
static int ed25519_validate(const void *keydata, int selection, int checktype)
988
0
{
989
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
990
0
}
991
992
static int ed448_validate(const void *keydata, int selection, int checktype)
993
0
{
994
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
995
0
}
996
997
static void ecx_free_key(void *keydata)
998
0
{
999
0
    ossl_ecx_key_free((ECX_KEY *)keydata);
1000
0
}
1001
1002
#define MAKE_KEYMGMT_FUNCTIONS(alg)                                                   \
1003
    const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = {                          \
1004
        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key },                     \
1005
        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_free_key },                     \
1006
        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))alg##_get_params },           \
1007
        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))alg##_gettable_params }, \
1008
        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))alg##_set_params },           \
1009
        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))alg##_settable_params }, \
1010
        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has },                           \
1011
        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match },                       \
1012
        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate },               \
1013
        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import },                     \
1014
        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types },       \
1015
        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export },                     \
1016
        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types },       \
1017
        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init },               \
1018
        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params },     \
1019
        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,                                      \
1020
            (void (*)(void))ecx_gen_settable_params },                                \
1021
        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen },                         \
1022
        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup },           \
1023
        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load },                         \
1024
        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup },                           \
1025
        OSSL_DISPATCH_END                                                             \
1026
    };
1027
1028
MAKE_KEYMGMT_FUNCTIONS(x25519)
1029
MAKE_KEYMGMT_FUNCTIONS(x448)
1030
MAKE_KEYMGMT_FUNCTIONS(ed25519)
1031
MAKE_KEYMGMT_FUNCTIONS(ed448)
1032
1033
#ifdef S390X_EC_ASM
1034
#include "arch/s390x_arch.h"
1035
1036
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
1037
{
1038
    static const unsigned char generator[] = {
1039
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1040
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1041
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1042
    };
1043
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
1044
        gctx->propq);
1045
    unsigned char *privkey = NULL, *pubkey;
1046
1047
    if (key == NULL) {
1048
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1049
        goto err;
1050
    }
1051
1052
    /* If we're doing parameter generation then we just return a blank key */
1053
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1054
        return key;
1055
1056
    pubkey = key->pubkey;
1057
1058
    privkey = ossl_ecx_key_allocate_privkey(key);
1059
    if (privkey == NULL) {
1060
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1061
        goto err;
1062
    }
1063
1064
#ifndef FIPS_MODULE
1065
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1066
        if (gctx->type != ECX_KEY_TYPE_X25519)
1067
            goto err;
1068
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
1069
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1070
            goto err;
1071
    } else
1072
#endif
1073
    {
1074
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
1075
            goto err;
1076
    }
1077
1078
    privkey[0] &= 248;
1079
    privkey[31] &= 127;
1080
    privkey[31] |= 64;
1081
1082
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1083
        goto err;
1084
    key->haspubkey = 1;
1085
    return key;
1086
err:
1087
    ossl_ecx_key_free(key);
1088
    return NULL;
1089
}
1090
1091
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
1092
{
1093
    static const unsigned char generator[] = {
1094
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1095
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1096
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1097
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1098
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1099
    };
1100
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
1101
        gctx->propq);
1102
    unsigned char *privkey = NULL, *pubkey;
1103
1104
    if (key == NULL) {
1105
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1106
        goto err;
1107
    }
1108
1109
    /* If we're doing parameter generation then we just return a blank key */
1110
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1111
        return key;
1112
1113
    pubkey = key->pubkey;
1114
1115
    privkey = ossl_ecx_key_allocate_privkey(key);
1116
    if (privkey == NULL) {
1117
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1118
        goto err;
1119
    }
1120
1121
#ifndef FIPS_MODULE
1122
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1123
        if (gctx->type != ECX_KEY_TYPE_X448)
1124
            goto err;
1125
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
1126
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1127
            goto err;
1128
    } else
1129
#endif
1130
    {
1131
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1132
            goto err;
1133
    }
1134
1135
    privkey[0] &= 252;
1136
    privkey[55] |= 128;
1137
1138
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1139
        goto err;
1140
    key->haspubkey = 1;
1141
    return key;
1142
err:
1143
    ossl_ecx_key_free(key);
1144
    return NULL;
1145
}
1146
1147
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
1148
{
1149
    static const unsigned char generator_x[] = {
1150
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1151
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1152
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1153
    };
1154
    static const unsigned char generator_y[] = {
1155
        0x58,
1156
        0x66,
1157
        0x66,
1158
        0x66,
1159
        0x66,
1160
        0x66,
1161
        0x66,
1162
        0x66,
1163
        0x66,
1164
        0x66,
1165
        0x66,
1166
        0x66,
1167
        0x66,
1168
        0x66,
1169
        0x66,
1170
        0x66,
1171
        0x66,
1172
        0x66,
1173
        0x66,
1174
        0x66,
1175
        0x66,
1176
        0x66,
1177
        0x66,
1178
        0x66,
1179
        0x66,
1180
        0x66,
1181
        0x66,
1182
        0x66,
1183
        0x66,
1184
        0x66,
1185
        0x66,
1186
        0x66,
1187
    };
1188
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1189
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1190
        gctx->propq);
1191
    unsigned char *privkey = NULL, *pubkey;
1192
    unsigned int sz;
1193
    EVP_MD *sha = NULL;
1194
    int j;
1195
1196
    if (key == NULL) {
1197
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1198
        goto err;
1199
    }
1200
1201
    /* If we're doing parameter generation then we just return a blank key */
1202
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1203
        return key;
1204
1205
    pubkey = key->pubkey;
1206
1207
    privkey = ossl_ecx_key_allocate_privkey(key);
1208
    if (privkey == NULL) {
1209
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1210
        goto err;
1211
    }
1212
1213
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1214
        goto err;
1215
1216
    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1217
    if (sha == NULL)
1218
        goto err;
1219
    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1220
    EVP_MD_free(sha);
1221
    if (!j)
1222
        goto err;
1223
1224
    buff[0] &= 248;
1225
    buff[31] &= 63;
1226
    buff[31] |= 64;
1227
1228
    if (s390x_ed25519_mul(x_dst, pubkey,
1229
            generator_x, generator_y, buff)
1230
        != 1)
1231
        goto err;
1232
1233
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1234
    key->haspubkey = 1;
1235
    return key;
1236
err:
1237
    ossl_ecx_key_free(key);
1238
    return NULL;
1239
}
1240
1241
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1242
{
1243
    static const unsigned char generator_x[] = {
1244
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1245
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1246
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1247
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1248
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1249
    };
1250
    static const unsigned char generator_y[] = {
1251
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1252
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1253
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1254
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1255
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1256
    };
1257
    unsigned char x_dst[57], buff[114];
1258
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1259
        gctx->propq);
1260
    unsigned char *privkey = NULL, *pubkey;
1261
    EVP_MD_CTX *hashctx = NULL;
1262
    EVP_MD *shake = NULL;
1263
1264
    if (key == NULL) {
1265
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1266
        goto err;
1267
    }
1268
1269
    /* If we're doing parameter generation then we just return a blank key */
1270
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1271
        return key;
1272
1273
    pubkey = key->pubkey;
1274
1275
    privkey = ossl_ecx_key_allocate_privkey(key);
1276
    if (privkey == NULL) {
1277
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1278
        goto err;
1279
    }
1280
1281
    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1282
    if (shake == NULL)
1283
        goto err;
1284
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1285
        goto err;
1286
1287
    hashctx = EVP_MD_CTX_new();
1288
    if (hashctx == NULL)
1289
        goto err;
1290
    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1291
        goto err;
1292
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1293
        goto err;
1294
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1295
        goto err;
1296
1297
    buff[0] &= -4;
1298
    buff[55] |= 0x80;
1299
    buff[56] = 0;
1300
1301
    if (s390x_ed448_mul(x_dst, pubkey,
1302
            generator_x, generator_y, buff)
1303
        != 1)
1304
        goto err;
1305
1306
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1307
    EVP_MD_CTX_free(hashctx);
1308
    EVP_MD_free(shake);
1309
    key->haspubkey = 1;
1310
    return key;
1311
err:
1312
    ossl_ecx_key_free(key);
1313
    EVP_MD_CTX_free(hashctx);
1314
    EVP_MD_free(shake);
1315
    return NULL;
1316
}
1317
#endif