Coverage Report

Created: 2025-12-04 06:33

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