Coverage Report

Created: 2025-12-04 06:33

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