Coverage Report

Created: 2026-10-16 07:07

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-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
0
#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
0
{
104
0
    return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448;
105
0
}
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
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_X25519, 0,
127
0
        NULL);
128
0
}
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
0
{
156
0
    const ECX_KEY *key = keydata;
157
0
    int ok = 0;
158
159
0
    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
0
        ok = 1;
165
166
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
167
0
            ok = ok && key->haspubkey;
168
169
0
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
170
0
            ok = ok && key->privkey != NULL;
171
0
    }
172
0
    return ok;
173
0
}
174
175
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
176
0
{
177
0
    const ECX_KEY *key1 = keydata1;
178
0
    const ECX_KEY *key2 = keydata2;
179
0
    int ok = 1;
180
181
0
    if (!ossl_prov_is_running())
182
0
        return 0;
183
184
0
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
185
0
        ok = ok && key1->type == key2->type;
186
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
187
0
        int key_checked = 0;
188
189
0
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
190
0
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
191
0
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
192
0
            size_t pal = key1->keylen;
193
0
            size_t pbl = key2->keylen;
194
195
0
            if (pa != NULL && pb != NULL) {
196
0
                ok = ok
197
0
                    && key1->type == key2->type
198
0
                    && pal == pbl
199
0
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
200
0
                key_checked = 1;
201
0
            }
202
0
        }
203
0
        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
0
        ok = ok && key_checked;
219
0
    }
220
0
    return ok;
221
0
}
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
0
{
242
0
    ECX_KEY *key = keydata;
243
0
    int ok = 1;
244
0
    int include_private;
245
0
    struct ecx_imexport_types_st p;
246
247
0
    if (!ossl_prov_is_running()
248
0
        || key == NULL
249
0
        || !ecx_imexport_types_decoder(params, &p))
250
0
        return 0;
251
252
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
253
0
        return 0;
254
255
0
    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
256
0
    ok = ok && ossl_ecx_key_fromdata(key, p.pub, p.priv, include_private);
257
258
0
    return ok;
259
0
}
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
0
{
264
0
    if (key == NULL)
265
0
        return 0;
266
267
0
    if (!ossl_param_build_set_octet_string(tmpl, pub,
268
0
            OSSL_PKEY_PARAM_PUB_KEY,
269
0
            key->pubkey, key->keylen))
270
0
        return 0;
271
272
0
    if (include_private
273
0
        && key->privkey != NULL
274
0
        && !ossl_param_build_set_octet_string(tmpl, priv,
275
0
            OSSL_PKEY_PARAM_PRIV_KEY,
276
0
            key->privkey, key->keylen))
277
0
        return 0;
278
279
0
    return 1;
280
0
}
281
282
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
283
    void *cbarg)
284
0
{
285
0
    ECX_KEY *key = keydata;
286
0
    OSSL_PARAM_BLD *tmpl;
287
0
    OSSL_PARAM *params = NULL;
288
0
    int ret = 0;
289
290
0
    if (!ossl_prov_is_running() || key == NULL)
291
0
        return 0;
292
293
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
294
0
        return 0;
295
296
0
    tmpl = OSSL_PARAM_BLD_new();
297
0
    if (tmpl == NULL)
298
0
        return 0;
299
300
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
301
0
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
302
303
0
        if (!key_to_params(key, tmpl, NULL, NULL, include_private))
304
0
            goto err;
305
0
    }
306
307
0
    params = OSSL_PARAM_BLD_to_param(tmpl);
308
0
    if (params == NULL)
309
0
        goto err;
310
311
0
    ret = param_cb(params, cbarg);
312
0
    OSSL_PARAM_clear_free(params);
313
0
err:
314
0
    OSSL_PARAM_BLD_free(tmpl);
315
0
    return ret;
316
0
}
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
0
{
330
0
    ECX_KEY *ecx = key;
331
332
0
    if (p->bits != NULL && !OSSL_PARAM_set_int(p->bits, bits))
333
0
        return 0;
334
0
    if (p->secbits != NULL && !OSSL_PARAM_set_int(p->secbits, secbits))
335
0
        return 0;
336
0
    if (p->size != NULL && !OSSL_PARAM_set_int(p->size, size))
337
0
        return 0;
338
0
    if (p->seccat != NULL && !OSSL_PARAM_set_int(p->seccat, 0))
339
0
        return 0;
340
0
    return key_to_params(ecx, NULL, p->pub, p->priv, 1);
341
0
}
342
343
/* X25519/X448 getter */
344
static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
345
    int size)
346
0
{
347
0
    ECX_KEY *ecx = key;
348
0
    struct ecx_ed_common_get_params_st p;
349
350
0
    if (key == NULL || !ecx_get_params_decoder(params, &p))
351
0
        return 0;
352
353
0
    if (p.encpub != NULL
354
0
        && !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
0
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
367
0
}
368
369
/* ED25519/ED448 getter */
370
static int ed_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
371
    int size)
372
0
{
373
0
    struct ecx_ed_common_get_params_st p;
374
375
0
    if (key == NULL || !ed_get_params_decoder(params, &p))
376
0
        return 0;
377
0
    if (p.digest != NULL && !OSSL_PARAM_set_utf8_string(p.digest, ""))
378
0
        return 0;
379
0
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
380
0
}
381
382
static int x25519_get_params(void *key, OSSL_PARAM params[])
383
0
{
384
0
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
385
0
        X25519_KEYLEN);
386
0
}
387
388
static int x448_get_params(void *key, OSSL_PARAM params[])
389
0
{
390
0
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
391
0
        X448_KEYLEN);
392
0
}
393
394
static int ed25519_get_params(void *key, OSSL_PARAM params[])
395
0
{
396
0
    return ed_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
397
0
        ED25519_SIGSIZE);
398
0
}
399
static int ed448_get_params(void *key, OSSL_PARAM params[])
400
0
{
401
0
    return ed_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
402
0
        ED448_SIGSIZE);
403
0
}
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
0
{
439
0
    ECX_KEY *ecxkey = key;
440
0
    struct ecx_set_params_st p;
441
442
0
    if (key == NULL || !ecx_set_params_decoder(params, &p))
443
0
        return 0;
444
445
0
    if (p.pub != NULL) {
446
0
        void *buf = ecxkey->pubkey;
447
448
0
        if (p.pub->data_size != ecxkey->keylen
449
0
            || !OSSL_PARAM_get_octet_string(p.pub, &buf, sizeof(ecxkey->pubkey),
450
0
                NULL))
451
0
            return 0;
452
0
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
453
0
        ecxkey->privkey = NULL;
454
0
        ecxkey->haspubkey = 1;
455
0
    }
456
457
0
    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
0
    return 1;
464
0
}
465
466
static int x25519_set_params(void *key, const OSSL_PARAM params[])
467
0
{
468
0
    return ecx_set_params(key, params);
469
0
}
470
471
static int x448_set_params(void *key, const OSSL_PARAM params[])
472
0
{
473
0
    return ecx_set_params(key, params);
474
0
}
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
0
{
514
0
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
515
0
    struct ecx_gen_ctx *gctx = NULL;
516
517
0
    if (!ossl_prov_is_running())
518
0
        return NULL;
519
520
0
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
521
0
        gctx->libctx = libctx;
522
0
        gctx->type = type;
523
0
        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
0
    } else {
533
0
        return NULL;
534
0
    }
535
0
    if (!ecx_gen_set_params(gctx, params)) {
536
0
        ecx_gen_cleanup(gctx);
537
0
        gctx = NULL;
538
0
    }
539
0
    return gctx;
540
0
}
541
542
static void *x25519_gen_init(void *provctx, int selection,
543
    const OSSL_PARAM params[])
544
0
{
545
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
546
0
}
547
548
static void *x448_gen_init(void *provctx, int selection,
549
    const OSSL_PARAM params[])
550
0
{
551
0
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
552
0
}
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
0
{
568
0
    struct ecx_gen_ctx *gctx = genctx;
569
0
    struct ecx_gen_set_params_st p;
570
571
0
    if (gctx == NULL || !ecx_gen_set_params_decoder(params, &p))
572
0
        return 0;
573
574
0
    if (p.group != NULL) {
575
0
        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
0
        switch (gctx->type) {
583
0
        case ECX_KEY_TYPE_X25519:
584
0
            groupname = "x25519";
585
0
            break;
586
0
        case ECX_KEY_TYPE_X448:
587
0
            groupname = "x448";
588
0
            break;
589
0
        default:
590
            /* We only support this for key exchange at the moment */
591
0
            break;
592
0
        }
593
0
        if (p.group->data_type != OSSL_PARAM_UTF8_STRING
594
0
            || groupname == NULL
595
0
            || 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
0
    }
600
601
0
    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
0
    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
0
    return 1;
621
0
}
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
0
{
699
0
    ECX_KEY *key;
700
0
    unsigned char *privkey;
701
702
0
    if (gctx == NULL)
703
0
        return NULL;
704
0
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
705
0
             gctx->propq))
706
0
        == 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
0
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
713
0
        return key;
714
715
0
    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
0
#ifndef FIPS_MODULE
720
0
    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
0
#endif
728
0
    {
729
0
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
730
0
            goto err;
731
0
    }
732
733
0
    switch (gctx->type) {
734
0
    case ECX_KEY_TYPE_X25519:
735
0
        privkey[0] &= 248;
736
0
        privkey[X25519_KEYLEN - 1] &= 127;
737
0
        privkey[X25519_KEYLEN - 1] |= 64;
738
0
        ossl_x25519_public_from_private(key->pubkey, privkey);
739
0
        break;
740
0
    case ECX_KEY_TYPE_X448:
741
0
        privkey[0] &= 252;
742
0
        privkey[X448_KEYLEN - 1] |= 128;
743
0
        ossl_x448_public_from_private(key->pubkey, privkey);
744
0
        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
0
    }
756
0
    key->haspubkey = 1;
757
0
    return key;
758
0
err:
759
0
    ossl_ecx_key_free(key);
760
0
    return NULL;
761
0
}
762
763
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
764
0
{
765
0
    struct ecx_gen_ctx *gctx = genctx;
766
767
0
    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
0
    return ecx_gen(gctx);
775
0
}
776
777
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
778
0
{
779
0
    struct ecx_gen_ctx *gctx = genctx;
780
781
0
    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
0
    return ecx_gen(gctx);
789
0
}
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
0
{
858
0
    struct ecx_gen_ctx *gctx = genctx;
859
860
0
    if (gctx == NULL)
861
0
        return;
862
863
0
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
864
0
    OPENSSL_free(gctx->propq);
865
0
    OPENSSL_free(gctx);
866
0
}
867
868
void *ecx_load(const void *reference, size_t reference_sz)
869
0
{
870
0
    ECX_KEY *key = NULL;
871
872
0
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
873
        /* The contents of the reference is the address to our object */
874
0
        key = *(ECX_KEY **)reference;
875
        /* We grabbed, so we detach it */
876
0
        *(ECX_KEY **)reference = NULL;
877
0
        return key;
878
0
    }
879
0
    return NULL;
880
0
}
881
882
static void *ecx_dup(const void *keydata_from, int selection)
883
0
{
884
0
    if (ossl_prov_is_running())
885
0
        return ossl_ecx_key_dup(keydata_from, selection);
886
0
    return NULL;
887
0
}
888
889
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
890
0
{
891
0
    uint8_t pub[64];
892
893
0
    switch (type) {
894
0
    case ECX_KEY_TYPE_X25519:
895
0
        ossl_x25519_public_from_private(pub, ecx->privkey);
896
0
        break;
897
0
    case ECX_KEY_TYPE_X448:
898
0
        ossl_x448_public_from_private(pub, ecx->privkey);
899
0
        break;
900
0
    default:
901
0
        return 0;
902
0
    }
903
0
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
904
0
}
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
0
{
933
0
    uint8_t pub[64];
934
935
0
    switch (type) {
936
0
    case ECX_KEY_TYPE_ED25519:
937
0
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
938
0
                ecx->propq))
939
0
            return 0;
940
0
        break;
941
0
    case ECX_KEY_TYPE_ED448:
942
0
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
943
0
                ecx->propq))
944
0
            return 0;
945
0
        break;
946
0
    default:
947
0
        return 0;
948
0
    }
949
0
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
950
0
}
951
#endif
952
953
static int ecx_validate(const void *keydata, int selection, int type,
954
    size_t keylen)
955
0
{
956
0
    const ECX_KEY *ecx = keydata;
957
0
    int ok = keylen == ecx->keylen;
958
959
0
    if (!ossl_prov_is_running())
960
0
        return 0;
961
962
0
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
963
0
        return 1; /* nothing to validate */
964
965
0
    if (!ok) {
966
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
967
0
        return 0;
968
0
    }
969
970
0
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
971
0
        ok = ok && ecx->haspubkey;
972
#ifdef FIPS_MODULE
973
        ok = ok && ecd_key_pub_check(ecx, type);
974
#endif
975
0
    }
976
977
0
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
978
0
        ok = ok && ecx->privkey != NULL;
979
980
0
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
981
0
        return ok;
982
983
0
    if (ecx_key_type_is_ed(type))
984
0
        ok = ok && ecd_key_pairwise_check(ecx, type);
985
0
    else
986
0
        ok = ok && ecx_key_pairwise_check(ecx, type);
987
988
0
    return ok;
989
0
}
990
991
static int x25519_validate(const void *keydata, int selection, int checktype)
992
0
{
993
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
994
0
}
995
996
static int x448_validate(const void *keydata, int selection, int checktype)
997
0
{
998
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
999
0
}
1000
1001
static int ed25519_validate(const void *keydata, int selection, int checktype)
1002
0
{
1003
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
1004
0
}
1005
1006
static int ed448_validate(const void *keydata, int selection, int checktype)
1007
0
{
1008
0
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
1009
0
}
1010
1011
static void ecx_free_key(void *keydata)
1012
0
{
1013
0
    ossl_ecx_key_free((ECX_KEY *)keydata);
1014
0
}
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