Coverage Report

Created: 2025-12-04 06:33

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