Coverage Report

Created: 2026-10-28 06:28

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