Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl40/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
#ifdef S390X_EC_ASM
30
#include "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
21.4k
#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
24
{
103
24
    return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448;
104
24
}
105
106
static void *x25519_new_key(void *provctx)
107
25
{
108
25
    if (!ossl_prov_is_running())
109
0
        return 0;
110
25
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
111
25
        NULL);
112
25
}
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
47.8k
{
140
47.8k
    const ECX_KEY *key = keydata;
141
47.8k
    int ok = 0;
142
143
47.8k
    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
24.0k
        ok = 1;
149
150
24.0k
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
151
86
            ok = ok && key->haspubkey;
152
153
24.0k
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
154
18
            ok = ok && key->privkey != NULL;
155
24.0k
    }
156
47.8k
    return ok;
157
47.8k
}
158
159
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
160
43
{
161
43
    const ECX_KEY *key1 = keydata1;
162
43
    const ECX_KEY *key2 = keydata2;
163
43
    int ok = 1;
164
165
43
    if (!ossl_prov_is_running())
166
0
        return 0;
167
168
43
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
169
43
        ok = ok && key1->type == key2->type;
170
43
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
171
43
        int key_checked = 0;
172
173
43
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
174
43
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
175
43
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
176
43
            size_t pal = key1->keylen;
177
43
            size_t pbl = key2->keylen;
178
179
43
            if (pa != NULL && pb != NULL) {
180
43
                ok = ok
181
43
                    && key1->type == key2->type
182
43
                    && pal == pbl
183
43
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
184
43
                key_checked = 1;
185
43
            }
186
43
        }
187
43
        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
43
        ok = ok && key_checked;
203
43
    }
204
43
    return ok;
205
43
}
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
25
{
226
25
    ECX_KEY *key = keydata;
227
25
    int ok = 1;
228
25
    int include_private;
229
25
    struct ecx_imexport_types_st p;
230
231
25
    if (!ossl_prov_is_running()
232
25
        || key == NULL
233
25
        || !ecx_imexport_types_decoder(params, &p))
234
0
        return 0;
235
236
25
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
237
0
        return 0;
238
239
25
    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
240
25
    ok = ok && ossl_ecx_key_fromdata(key, p.pub, p.priv, include_private);
241
242
25
    return ok;
243
25
}
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
413k
{
248
413k
    if (key == NULL)
249
0
        return 0;
250
251
413k
    if (!ossl_param_build_set_octet_string(tmpl, pub,
252
413k
            OSSL_PKEY_PARAM_PUB_KEY,
253
413k
            key->pubkey, key->keylen))
254
0
        return 0;
255
256
413k
    if (include_private
257
350k
        && key->privkey != NULL
258
317k
        && !ossl_param_build_set_octet_string(tmpl, priv,
259
317k
            OSSL_PKEY_PARAM_PRIV_KEY,
260
317k
            key->privkey, key->keylen))
261
0
        return 0;
262
263
413k
    return 1;
264
413k
}
265
266
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
267
    void *cbarg)
268
63.4k
{
269
63.4k
    ECX_KEY *key = keydata;
270
63.4k
    OSSL_PARAM_BLD *tmpl;
271
63.4k
    OSSL_PARAM *params = NULL;
272
63.4k
    int ret = 0;
273
274
63.4k
    if (!ossl_prov_is_running() || key == NULL)
275
0
        return 0;
276
277
63.4k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
278
0
        return 0;
279
280
63.4k
    tmpl = OSSL_PARAM_BLD_new();
281
63.4k
    if (tmpl == NULL)
282
0
        return 0;
283
284
63.4k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
285
63.4k
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
286
287
63.4k
        if (!key_to_params(key, tmpl, NULL, NULL, include_private))
288
0
            goto err;
289
63.4k
    }
290
291
63.4k
    params = OSSL_PARAM_BLD_to_param(tmpl);
292
63.4k
    if (params == NULL)
293
0
        goto err;
294
295
63.4k
    ret = param_cb(params, cbarg);
296
63.4k
    OSSL_PARAM_clear_free(params);
297
63.4k
err:
298
63.4k
    OSSL_PARAM_BLD_free(tmpl);
299
63.4k
    return ret;
300
63.4k
}
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
227k
{
314
227k
    ECX_KEY *ecx = key;
315
316
227k
    if (p->bits != NULL && !OSSL_PARAM_set_int(p->bits, bits))
317
0
        return 0;
318
227k
    if (p->secbits != NULL && !OSSL_PARAM_set_int(p->secbits, secbits))
319
0
        return 0;
320
227k
    if (p->size != NULL && !OSSL_PARAM_set_int(p->size, size))
321
0
        return 0;
322
227k
    if (p->seccat != NULL && !OSSL_PARAM_set_int(p->seccat, 0))
323
0
        return 0;
324
227k
    return key_to_params(ecx, NULL, p->pub, p->priv, 1);
325
227k
}
326
327
/* X25519/X448 getter */
328
static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
329
    int size)
330
225k
{
331
225k
    ECX_KEY *ecx = key;
332
225k
    struct ecx_ed_common_get_params_st p;
333
334
225k
    if (key == NULL || !ecx_get_params_decoder(params, &p))
335
0
        return 0;
336
337
225k
    if (p.encpub != NULL
338
106k
        && !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
225k
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
351
225k
}
352
353
/* ED25519/ED448 getter */
354
static int ed_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
355
    int size)
356
1.65k
{
357
1.65k
    struct ecx_ed_common_get_params_st p;
358
359
1.65k
    if (key == NULL || !ed_get_params_decoder(params, &p))
360
0
        return 0;
361
1.65k
    if (p.digest != NULL && !OSSL_PARAM_set_utf8_string(p.digest, ""))
362
0
        return 0;
363
1.65k
    return ecx_ed_common_get_params(key, &p, bits, secbits, size);
364
1.65k
}
365
366
static int x25519_get_params(void *key, OSSL_PARAM params[])
367
347k
{
368
347k
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
369
347k
        X25519_KEYLEN);
370
347k
}
371
372
static int x448_get_params(void *key, OSSL_PARAM params[])
373
1.02k
{
374
1.02k
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
375
1.02k
        X448_KEYLEN);
376
1.02k
}
377
378
static int ed25519_get_params(void *key, OSSL_PARAM params[])
379
347
{
380
347
    return ed_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
381
347
        ED25519_SIGSIZE);
382
347
}
383
static int ed448_get_params(void *key, OSSL_PARAM params[])
384
1.30k
{
385
1.30k
    return ed_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
386
1.30k
        ED448_SIGSIZE);
387
1.30k
}
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
17.0k
{
423
17.0k
    ECX_KEY *ecxkey = key;
424
17.0k
    struct ecx_set_params_st p;
425
426
17.0k
    if (key == NULL || !ecx_set_params_decoder(params, &p))
427
0
        return 0;
428
429
17.0k
    if (p.pub != NULL) {
430
17.0k
        void *buf = ecxkey->pubkey;
431
432
17.0k
        if (p.pub->data_size != ecxkey->keylen
433
17.0k
            || !OSSL_PARAM_get_octet_string(p.pub, &buf, sizeof(ecxkey->pubkey),
434
17.0k
                NULL))
435
27
            return 0;
436
17.0k
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
437
17.0k
        ecxkey->privkey = NULL;
438
17.0k
        ecxkey->haspubkey = 1;
439
17.0k
    }
440
441
17.0k
    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
17.0k
    return 1;
448
17.0k
}
449
450
static int x25519_set_params(void *key, const OSSL_PARAM params[])
451
28.2k
{
452
28.2k
    return ecx_set_params(key, params);
453
28.2k
}
454
455
static int x448_set_params(void *key, const OSSL_PARAM params[])
456
53
{
457
53
    return ecx_set_params(key, params);
458
53
}
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
151k
{
498
151k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
499
151k
    struct ecx_gen_ctx *gctx = NULL;
500
501
151k
    if (!ossl_prov_is_running())
502
0
        return NULL;
503
504
151k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
505
151k
        gctx->libctx = libctx;
506
151k
        gctx->type = type;
507
151k
        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
151k
    } else {
517
0
        return NULL;
518
0
    }
519
151k
    if (!ecx_gen_set_params(gctx, params)) {
520
0
        ecx_gen_cleanup(gctx);
521
0
        gctx = NULL;
522
0
    }
523
151k
    return gctx;
524
151k
}
525
526
static void *x25519_gen_init(void *provctx, int selection,
527
    const OSSL_PARAM params[])
528
151k
{
529
151k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
530
151k
}
531
532
static void *x448_gen_init(void *provctx, int selection,
533
    const OSSL_PARAM params[])
534
296
{
535
296
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
536
296
}
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
204k
{
552
204k
    struct ecx_gen_ctx *gctx = genctx;
553
204k
    struct ecx_gen_set_params_st p;
554
555
204k
    if (gctx == NULL || !ecx_gen_set_params_decoder(params, &p))
556
0
        return 0;
557
558
204k
    if (p.group != NULL) {
559
53.4k
        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
53.4k
        switch (gctx->type) {
567
53.2k
        case ECX_KEY_TYPE_X25519:
568
53.2k
            groupname = "x25519";
569
53.2k
            break;
570
219
        case ECX_KEY_TYPE_X448:
571
219
            groupname = "x448";
572
219
            break;
573
0
        default:
574
            /* We only support this for key exchange at the moment */
575
0
            break;
576
53.4k
        }
577
53.4k
        if (p.group->data_type != OSSL_PARAM_UTF8_STRING
578
53.4k
            || groupname == NULL
579
53.4k
            || 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
53.4k
    }
584
585
204k
    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
204k
    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
204k
    return 1;
605
204k
}
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
135k
{
683
135k
    ECX_KEY *key;
684
135k
    unsigned char *privkey;
685
686
135k
    if (gctx == NULL)
687
0
        return NULL;
688
135k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
689
135k
             gctx->propq))
690
135k
        == 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
135k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
697
3.68k
        return key;
698
699
131k
    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
131k
#ifndef FIPS_MODULE
704
131k
    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
131k
#endif
712
131k
    {
713
131k
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
714
0
            goto err;
715
131k
    }
716
717
131k
    switch (gctx->type) {
718
131k
    case ECX_KEY_TYPE_X25519:
719
131k
        privkey[0] &= 248;
720
131k
        privkey[X25519_KEYLEN - 1] &= 127;
721
131k
        privkey[X25519_KEYLEN - 1] |= 64;
722
131k
        ossl_x25519_public_from_private(key->pubkey, privkey);
723
131k
        break;
724
230
    case ECX_KEY_TYPE_X448:
725
230
        privkey[0] &= 252;
726
230
        privkey[X448_KEYLEN - 1] |= 128;
727
230
        ossl_x448_public_from_private(key->pubkey, privkey);
728
230
        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
131k
    }
740
131k
    key->haspubkey = 1;
741
131k
    return key;
742
0
err:
743
0
    ossl_ecx_key_free(key);
744
0
    return NULL;
745
131k
}
746
747
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
748
151k
{
749
151k
    struct ecx_gen_ctx *gctx = genctx;
750
751
151k
    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
151k
    return ecx_gen(gctx);
759
151k
}
760
761
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
762
296
{
763
296
    struct ecx_gen_ctx *gctx = genctx;
764
765
296
    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
296
    return ecx_gen(gctx);
773
296
}
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_ecx_key_free(key);
801
        return NULL;
802
    }
803
#endif
804
805
0
    return key;
806
0
}
807
808
static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
809
0
{
810
0
    ECX_KEY *key = NULL;
811
0
    struct ecx_gen_ctx *gctx = genctx;
812
813
0
    if (!ossl_prov_is_running())
814
0
        return 0;
815
816
#ifdef S390X_EC_ASM
817
    if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
818
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
819
        && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) {
820
        key = s390x_ecd_keygen448(gctx);
821
    } else
822
#endif
823
0
    {
824
0
        key = ecx_gen(gctx);
825
0
    }
826
827
#ifdef FIPS_MODULE
828
    /* Exit if keygen failed OR we are doing parameter generation (blank key) */
829
    if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
830
        return key;
831
    if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
832
        ossl_ecx_key_free(key);
833
        return NULL;
834
    }
835
#endif
836
837
0
    return key;
838
0
}
839
840
static void ecx_gen_cleanup(void *genctx)
841
151k
{
842
151k
    struct ecx_gen_ctx *gctx = genctx;
843
844
151k
    if (gctx == NULL)
845
0
        return;
846
847
151k
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
848
151k
    OPENSSL_free(gctx->propq);
849
151k
    OPENSSL_free(gctx);
850
151k
}
851
852
void *ecx_load(const void *reference, size_t reference_sz)
853
4.19k
{
854
4.19k
    ECX_KEY *key = NULL;
855
856
4.19k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
857
        /* The contents of the reference is the address to our object */
858
4.19k
        key = *(ECX_KEY **)reference;
859
        /* We grabbed, so we detach it */
860
4.19k
        *(ECX_KEY **)reference = NULL;
861
4.19k
        return key;
862
4.19k
    }
863
0
    return NULL;
864
4.19k
}
865
866
static void *ecx_dup(const void *keydata_from, int selection)
867
23.8k
{
868
23.8k
    if (ossl_prov_is_running())
869
23.8k
        return ossl_ecx_key_dup(keydata_from, selection);
870
0
    return NULL;
871
23.8k
}
872
873
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
874
9
{
875
9
    uint8_t pub[64];
876
877
9
    switch (type) {
878
4
    case ECX_KEY_TYPE_X25519:
879
4
        ossl_x25519_public_from_private(pub, ecx->privkey);
880
4
        break;
881
5
    case ECX_KEY_TYPE_X448:
882
5
        ossl_x448_public_from_private(pub, ecx->privkey);
883
5
        break;
884
0
    default:
885
0
        return 0;
886
9
    }
887
9
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
888
9
}
889
890
#ifdef FIPS_MODULE
891
/*
892
 * FIPS ACVP testing requires the ability to check if the public key is valid
893
 * This is not required normally since the ED signature verify does the test
894
 * internally.
895
 */
896
static int ecd_key_pub_check(const ECX_KEY *ecx, int type)
897
{
898
    switch (type) {
899
    case ECX_KEY_TYPE_ED25519:
900
        return ossl_ed25519_pubkey_verify(ecx->pubkey, ecx->keylen);
901
    case ECX_KEY_TYPE_ED448:
902
        return ossl_ed448_pubkey_verify(ecx->pubkey, ecx->keylen);
903
    default:
904
        return 1;
905
    }
906
}
907
#endif
908
909
#ifdef FIPS_MODULE
910
static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
911
{
912
    return ecd_fips140_pairwise_test(ecx, type, 0);
913
}
914
#else
915
static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
916
17
{
917
17
    uint8_t pub[64];
918
919
17
    switch (type) {
920
5
    case ECX_KEY_TYPE_ED25519:
921
5
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
922
5
                ecx->propq))
923
0
            return 0;
924
5
        break;
925
12
    case ECX_KEY_TYPE_ED448:
926
12
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
927
12
                ecx->propq))
928
0
            return 0;
929
12
        break;
930
12
    default:
931
0
        return 0;
932
17
    }
933
17
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
934
17
}
935
#endif
936
937
static int ecx_validate(const void *keydata, int selection, int type,
938
    size_t keylen)
939
21.4k
{
940
21.4k
    const ECX_KEY *ecx = keydata;
941
21.4k
    int ok = keylen == ecx->keylen;
942
943
21.4k
    if (!ossl_prov_is_running())
944
0
        return 0;
945
946
21.4k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
947
24
        return 1; /* nothing to validate */
948
949
21.4k
    if (!ok) {
950
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
951
0
        return 0;
952
0
    }
953
954
21.4k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
955
21.4k
        ok = ok && ecx->haspubkey;
956
#ifdef FIPS_MODULE
957
        ok = ok && ecd_key_pub_check(ecx, type);
958
#endif
959
21.4k
    }
960
961
21.4k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
962
48
        ok = ok && ecx->privkey != NULL;
963
964
21.4k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
965
21.4k
        return ok;
966
967
24
    if (ecx_key_type_is_ed(type))
968
11
        ok = ok && ecd_key_pairwise_check(ecx, type);
969
13
    else
970
13
        ok = ok && ecx_key_pairwise_check(ecx, type);
971
972
24
    return ok;
973
21.4k
}
974
975
static int x25519_validate(const void *keydata, int selection, int checktype)
976
26.8k
{
977
26.8k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
978
26.8k
}
979
980
static int x448_validate(const void *keydata, int selection, int checktype)
981
62
{
982
62
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
983
62
}
984
985
static int ed25519_validate(const void *keydata, int selection, int checktype)
986
36
{
987
36
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
988
36
}
989
990
static int ed448_validate(const void *keydata, int selection, int checktype)
991
68
{
992
68
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
993
68
}
994
995
static void ecx_free_key(void *keydata)
996
157k
{
997
157k
    ossl_ecx_key_free((ECX_KEY *)keydata);
998
157k
}
999
1000
#define MAKE_KEYMGMT_FUNCTIONS(alg)                                                   \
1001
    const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = {                          \
1002
        { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key },                     \
1003
        { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_free_key },                     \
1004
        { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*)(void))alg##_get_params },           \
1005
        { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*)(void))alg##_gettable_params }, \
1006
        { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*)(void))alg##_set_params },           \
1007
        { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*)(void))alg##_settable_params }, \
1008
        { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has },                           \
1009
        { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match },                       \
1010
        { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate },               \
1011
        { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import },                     \
1012
        { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types },       \
1013
        { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export },                     \
1014
        { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types },       \
1015
        { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init },               \
1016
        { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params },     \
1017
        { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS,                                      \
1018
            (void (*)(void))ecx_gen_settable_params },                                \
1019
        { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen },                         \
1020
        { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup },           \
1021
        { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load },                         \
1022
        { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup },                           \
1023
        OSSL_DISPATCH_END                                                             \
1024
    };
1025
1026
MAKE_KEYMGMT_FUNCTIONS(x25519)
1027
MAKE_KEYMGMT_FUNCTIONS(x448)
1028
MAKE_KEYMGMT_FUNCTIONS(ed25519)
1029
MAKE_KEYMGMT_FUNCTIONS(ed448)
1030
1031
#ifdef S390X_EC_ASM
1032
#include "s390x_arch.h"
1033
1034
static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
1035
{
1036
    static const unsigned char generator[] = {
1037
        0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1038
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1039
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1040
    };
1041
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
1042
        gctx->propq);
1043
    unsigned char *privkey = NULL, *pubkey;
1044
1045
    if (key == NULL) {
1046
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1047
        goto err;
1048
    }
1049
1050
    /* If we're doing parameter generation then we just return a blank key */
1051
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1052
        return key;
1053
1054
    pubkey = key->pubkey;
1055
1056
    privkey = ossl_ecx_key_allocate_privkey(key);
1057
    if (privkey == NULL) {
1058
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1059
        goto err;
1060
    }
1061
1062
#ifndef FIPS_MODULE
1063
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1064
        if (gctx->type != ECX_KEY_TYPE_X25519)
1065
            goto err;
1066
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
1067
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1068
            goto err;
1069
    } else
1070
#endif
1071
    {
1072
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
1073
            goto err;
1074
    }
1075
1076
    privkey[0] &= 248;
1077
    privkey[31] &= 127;
1078
    privkey[31] |= 64;
1079
1080
    if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1081
        goto err;
1082
    key->haspubkey = 1;
1083
    return key;
1084
err:
1085
    ossl_ecx_key_free(key);
1086
    return NULL;
1087
}
1088
1089
static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
1090
{
1091
    static const unsigned char generator[] = {
1092
        0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094
        0x00, 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
1097
    };
1098
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
1099
        gctx->propq);
1100
    unsigned char *privkey = NULL, *pubkey;
1101
1102
    if (key == NULL) {
1103
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1104
        goto err;
1105
    }
1106
1107
    /* If we're doing parameter generation then we just return a blank key */
1108
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1109
        return key;
1110
1111
    pubkey = key->pubkey;
1112
1113
    privkey = ossl_ecx_key_allocate_privkey(key);
1114
    if (privkey == NULL) {
1115
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1116
        goto err;
1117
    }
1118
1119
#ifndef FIPS_MODULE
1120
    if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1121
        if (gctx->type != ECX_KEY_TYPE_X448)
1122
            goto err;
1123
        if (!ossl_ecx_dhkem_derive_private(key, privkey,
1124
                gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1125
            goto err;
1126
    } else
1127
#endif
1128
    {
1129
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1130
            goto err;
1131
    }
1132
1133
    privkey[0] &= 252;
1134
    privkey[55] |= 128;
1135
1136
    if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1137
        goto err;
1138
    key->haspubkey = 1;
1139
    return key;
1140
err:
1141
    ossl_ecx_key_free(key);
1142
    return NULL;
1143
}
1144
1145
static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
1146
{
1147
    static const unsigned char generator_x[] = {
1148
        0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1149
        0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1150
        0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1151
    };
1152
    static const unsigned char generator_y[] = {
1153
        0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1154
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1155
        0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1156
        0x66, 0x66
1157
    };
1158
    unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1159
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1160
        gctx->propq);
1161
    unsigned char *privkey = NULL, *pubkey;
1162
    unsigned int sz;
1163
    EVP_MD *sha = NULL;
1164
    int j;
1165
1166
    if (key == NULL) {
1167
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1168
        goto err;
1169
    }
1170
1171
    /* If we're doing parameter generation then we just return a blank key */
1172
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1173
        return key;
1174
1175
    pubkey = key->pubkey;
1176
1177
    privkey = ossl_ecx_key_allocate_privkey(key);
1178
    if (privkey == NULL) {
1179
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1180
        goto err;
1181
    }
1182
1183
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1184
        goto err;
1185
1186
    sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1187
    if (sha == NULL)
1188
        goto err;
1189
    j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1190
    EVP_MD_free(sha);
1191
    if (!j)
1192
        goto err;
1193
1194
    buff[0] &= 248;
1195
    buff[31] &= 63;
1196
    buff[31] |= 64;
1197
1198
    if (s390x_ed25519_mul(x_dst, pubkey,
1199
            generator_x, generator_y, buff)
1200
        != 1)
1201
        goto err;
1202
1203
    pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1204
    key->haspubkey = 1;
1205
    return key;
1206
err:
1207
    ossl_ecx_key_free(key);
1208
    return NULL;
1209
}
1210
1211
static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1212
{
1213
    static const unsigned char generator_x[] = {
1214
        0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1215
        0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1216
        0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1217
        0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1218
        0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1219
    };
1220
    static const unsigned char generator_y[] = {
1221
        0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1222
        0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1223
        0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1224
        0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1225
        0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1226
    };
1227
    unsigned char x_dst[57], buff[114];
1228
    ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1229
        gctx->propq);
1230
    unsigned char *privkey = NULL, *pubkey;
1231
    EVP_MD_CTX *hashctx = NULL;
1232
    EVP_MD *shake = NULL;
1233
1234
    if (key == NULL) {
1235
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1236
        goto err;
1237
    }
1238
1239
    /* If we're doing parameter generation then we just return a blank key */
1240
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1241
        return key;
1242
1243
    pubkey = key->pubkey;
1244
1245
    privkey = ossl_ecx_key_allocate_privkey(key);
1246
    if (privkey == NULL) {
1247
        ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1248
        goto err;
1249
    }
1250
1251
    shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1252
    if (shake == NULL)
1253
        goto err;
1254
    if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1255
        goto err;
1256
1257
    hashctx = EVP_MD_CTX_new();
1258
    if (hashctx == NULL)
1259
        goto err;
1260
    if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1261
        goto err;
1262
    if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1263
        goto err;
1264
    if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1265
        goto err;
1266
1267
    buff[0] &= -4;
1268
    buff[55] |= 0x80;
1269
    buff[56] = 0;
1270
1271
    if (s390x_ed448_mul(x_dst, pubkey,
1272
            generator_x, generator_y, buff)
1273
        != 1)
1274
        goto err;
1275
1276
    pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1277
    EVP_MD_CTX_free(hashctx);
1278
    EVP_MD_free(shake);
1279
    key->haspubkey = 1;
1280
    return key;
1281
err:
1282
    ossl_ecx_key_free(key);
1283
    EVP_MD_CTX_free(hashctx);
1284
    EVP_MD_free(shake);
1285
    return NULL;
1286
}
1287
#endif