Coverage Report

Created: 2025-11-16 06:40

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
12.3k
#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
20
{
97
20
    if (!ossl_prov_is_running())
98
0
        return 0;
99
20
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
100
20
                            NULL);
101
20
}
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
55.2k
{
129
55.2k
    const ECX_KEY *key = keydata;
130
55.2k
    int ok = 0;
131
132
55.2k
    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
27.8k
        ok = 1;
138
139
27.8k
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
140
98
            ok = ok && key->haspubkey;
141
142
27.8k
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
143
26
            ok = ok && key->privkey != NULL;
144
27.8k
    }
145
55.2k
    return ok;
146
55.2k
}
147
148
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
149
49
{
150
49
    const ECX_KEY *key1 = keydata1;
151
49
    const ECX_KEY *key2 = keydata2;
152
49
    int ok = 1;
153
154
49
    if (!ossl_prov_is_running())
155
0
        return 0;
156
157
49
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
158
49
        ok = ok && key1->type == key2->type;
159
49
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
160
49
        int key_checked = 0;
161
162
49
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
163
49
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
164
49
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
165
49
            size_t pal = key1->keylen;
166
49
            size_t pbl = key2->keylen;
167
168
49
            if (pa != NULL && pb != NULL) {
169
49
                ok = ok
170
49
                    && key1->type == key2->type
171
49
                    && pal == pbl
172
49
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
173
49
                key_checked = 1;
174
49
            }
175
49
        }
176
49
        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
49
        ok = ok && key_checked;
192
49
    }
193
49
    return ok;
194
49
}
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
387k
{
217
387k
    if (key == NULL)
218
0
        return 0;
219
220
387k
    if (!ossl_param_build_set_octet_string(tmpl, params,
221
387k
                                           OSSL_PKEY_PARAM_PUB_KEY,
222
387k
                                           key->pubkey, key->keylen))
223
0
        return 0;
224
225
387k
    if (include_private
226
355k
        && key->privkey != NULL
227
318k
        && !ossl_param_build_set_octet_string(tmpl, params,
228
318k
                                              OSSL_PKEY_PARAM_PRIV_KEY,
229
318k
                                              key->privkey, key->keylen))
230
0
        return 0;
231
232
387k
    return 1;
233
387k
}
234
235
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
236
                      void *cbarg)
237
31.5k
{
238
31.5k
    ECX_KEY *key = keydata;
239
31.5k
    OSSL_PARAM_BLD *tmpl;
240
31.5k
    OSSL_PARAM *params = NULL;
241
31.5k
    int ret = 0;
242
243
31.5k
    if (!ossl_prov_is_running() || key == NULL)
244
0
        return 0;
245
246
31.5k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
247
0
        return 0;
248
249
31.5k
    tmpl = OSSL_PARAM_BLD_new();
250
31.5k
    if (tmpl == NULL)
251
0
        return 0;
252
253
31.5k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
254
31.5k
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
255
256
31.5k
        if (!key_to_params(key, tmpl, NULL, include_private))
257
0
            goto err;
258
31.5k
    }
259
260
31.5k
    params = OSSL_PARAM_BLD_to_param(tmpl);
261
31.5k
    if (params == NULL)
262
0
        goto err;
263
264
31.5k
    ret = param_cb(params, cbarg);
265
31.5k
    OSSL_PARAM_free(params);
266
31.5k
err:
267
31.5k
    OSSL_PARAM_BLD_free(tmpl);
268
31.5k
    return ret;
269
31.5k
}
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
278k
{
289
278k
    ECX_KEY *ecx = key;
290
278k
    OSSL_PARAM *p;
291
292
278k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
293
123k
        && !OSSL_PARAM_set_int(p, bits))
294
0
        return 0;
295
278k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
296
123k
        && !OSSL_PARAM_set_int(p, secbits))
297
0
        return 0;
298
278k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
299
123k
        && !OSSL_PARAM_set_int(p, size))
300
0
        return 0;
301
278k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
302
155k
            && (ecx->type == ECX_KEY_TYPE_X25519
303
155k
                || ecx->type == ECX_KEY_TYPE_X448)) {
304
155k
        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
305
0
            return 0;
306
155k
    }
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
278k
    return key_to_params(ecx, NULL, params, 1);
319
278k
}
320
321
static int ed_get_params(void *key, OSSL_PARAM params[])
322
822
{
323
822
    OSSL_PARAM *p;
324
325
822
    if ((p = OSSL_PARAM_locate(params,
326
822
                               OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
327
105
        && !OSSL_PARAM_set_utf8_string(p, ""))
328
0
        return 0;
329
822
    return 1;
330
822
}
331
332
static int x25519_get_params(void *key, OSSL_PARAM params[])
333
351k
{
334
351k
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
335
351k
                          X25519_KEYLEN);
336
351k
}
337
338
static int x448_get_params(void *key, OSSL_PARAM params[])
339
3.56k
{
340
3.56k
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
341
3.56k
                          X448_KEYLEN);
342
3.56k
}
343
344
static int ed25519_get_params(void *key, OSSL_PARAM params[])
345
217
{
346
217
    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
347
217
                          ED25519_SIGSIZE)
348
217
        && ed_get_params(key, params);
349
217
}
350
351
static int ed448_get_params(void *key, OSSL_PARAM params[])
352
605
{
353
605
    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
354
605
                          ED448_SIGSIZE)
355
605
        && ed_get_params(key, params);
356
605
}
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.6k
{
411
20.6k
    ECX_KEY *ecxkey = key;
412
20.6k
    const OSSL_PARAM *p;
413
414
20.6k
    if (params == NULL)
415
0
        return 1;
416
417
20.6k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
418
20.6k
    if (p != NULL) {
419
20.6k
        void *buf = ecxkey->pubkey;
420
421
20.6k
        if (p->data_size != ecxkey->keylen
422
20.5k
                || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
423
20.5k
                                                NULL))
424
71
            return 0;
425
20.5k
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
426
20.5k
        ecxkey->privkey = NULL;
427
20.5k
        ecxkey->haspubkey = 1;
428
20.5k
    }
429
20.5k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
430
20.5k
    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.5k
    return 1;
437
20.5k
}
438
439
static int x25519_set_params(void *key, const OSSL_PARAM params[])
440
33.1k
{
441
33.1k
    return ecx_set_params(key, params);
442
33.1k
}
443
444
static int x448_set_params(void *key, const OSSL_PARAM params[])
445
63
{
446
63
    return ecx_set_params(key, params);
447
63
}
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
132k
{
493
132k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
494
132k
    struct ecx_gen_ctx *gctx = NULL;
495
496
132k
    if (!ossl_prov_is_running())
497
0
        return NULL;
498
499
132k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
500
132k
        gctx->libctx = libctx;
501
132k
        gctx->type = type;
502
132k
        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
132k
    } else {
512
0
        return NULL;
513
0
    }
514
132k
    if (!ecx_gen_set_params(gctx, params)) {
515
0
        ecx_gen_cleanup(gctx);
516
0
        gctx = NULL;
517
0
    }
518
132k
    return gctx;
519
132k
}
520
521
static void *x25519_gen_init(void *provctx, int selection,
522
                             const OSSL_PARAM params[])
523
132k
{
524
132k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
525
132k
}
526
527
static void *x448_gen_init(void *provctx, int selection,
528
                           const OSSL_PARAM params[])
529
360
{
530
360
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
531
360
}
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
177k
{
547
177k
    struct ecx_gen_ctx *gctx = genctx;
548
177k
    const OSSL_PARAM *p;
549
550
177k
    if (gctx == NULL)
551
0
        return 0;
552
553
177k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
554
177k
    if (p != NULL) {
555
71.9k
        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
71.9k
        switch (gctx->type) {
563
71.6k
            case ECX_KEY_TYPE_X25519:
564
71.6k
                groupname = "x25519";
565
71.6k
                break;
566
293
            case ECX_KEY_TYPE_X448:
567
293
                groupname = "x448";
568
293
                break;
569
0
            default:
570
                /* We only support this for key exchange at the moment */
571
0
                break;
572
71.9k
        }
573
71.9k
        if (p->data_type != OSSL_PARAM_UTF8_STRING
574
71.9k
                || groupname == NULL
575
71.9k
                || 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
71.9k
    }
580
177k
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
581
177k
    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
177k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
590
177k
    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
177k
    return 1;
601
177k
}
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
56.4k
{
685
56.4k
    ECX_KEY *key;
686
56.4k
    unsigned char *privkey;
687
688
56.4k
    if (gctx == NULL)
689
0
        return NULL;
690
56.4k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
691
56.4k
                                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
56.4k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
698
2.58k
        return key;
699
700
53.9k
    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
53.9k
#ifndef FIPS_MODULE
705
53.9k
    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
53.9k
#endif
714
53.9k
    {
715
53.9k
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
716
0
            goto err;
717
53.9k
    }
718
719
53.9k
    switch (gctx->type) {
720
53.6k
    case ECX_KEY_TYPE_X25519:
721
53.6k
        privkey[0] &= 248;
722
53.6k
        privkey[X25519_KEYLEN - 1] &= 127;
723
53.6k
        privkey[X25519_KEYLEN - 1] |= 64;
724
53.6k
        ossl_x25519_public_from_private(key->pubkey, privkey);
725
53.6k
        break;
726
254
    case ECX_KEY_TYPE_X448:
727
254
        privkey[0] &= 252;
728
254
        privkey[X448_KEYLEN - 1] |= 128;
729
254
        ossl_x448_public_from_private(key->pubkey, privkey);
730
254
        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
53.9k
    }
742
53.9k
    key->haspubkey = 1;
743
53.9k
    return key;
744
0
err:
745
0
    ossl_ecx_key_free(key);
746
0
    return NULL;
747
53.9k
}
748
749
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
750
132k
{
751
132k
    struct ecx_gen_ctx *gctx = genctx;
752
753
132k
    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
132k
    return ecx_gen(gctx);
761
132k
}
762
763
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
764
360
{
765
360
    struct ecx_gen_ctx *gctx = genctx;
766
767
360
    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
360
    return ecx_gen(gctx);
775
360
}
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
132k
{
846
132k
    struct ecx_gen_ctx *gctx = genctx;
847
848
132k
    if (gctx == NULL)
849
0
        return;
850
851
132k
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
852
132k
    OPENSSL_free(gctx->propq);
853
132k
    OPENSSL_free(gctx);
854
132k
}
855
856
void *ecx_load(const void *reference, size_t reference_sz)
857
4.09k
{
858
4.09k
    ECX_KEY *key = NULL;
859
860
4.09k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
861
        /* The contents of the reference is the address to our object */
862
4.09k
        key = *(ECX_KEY **)reference;
863
        /* We grabbed, so we detach it */
864
4.09k
        *(ECX_KEY **)reference = NULL;
865
4.09k
        return key;
866
4.09k
    }
867
0
    return NULL;
868
4.09k
}
869
870
static void *ecx_dup(const void *keydata_from, int selection)
871
27.5k
{
872
27.5k
    if (ossl_prov_is_running())
873
27.5k
        return ossl_ecx_key_dup(keydata_from, selection);
874
0
    return NULL;
875
27.5k
}
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
3
    case ECX_KEY_TYPE_X25519:
883
3
        ossl_x25519_public_from_private(pub, ecx->privkey);
884
3
        break;
885
6
    case ECX_KEY_TYPE_X448:
886
6
        ossl_x448_public_from_private(pub, ecx->privkey);
887
6
        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
12
{
921
12
    uint8_t pub[64];
922
923
12
    switch (type) {
924
3
    case ECX_KEY_TYPE_ED25519:
925
3
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
926
3
                                              ecx->propq))
927
0
            return 0;
928
3
        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
12
    }
937
12
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
938
12
}
939
#endif
940
941
static int ecx_validate(const void *keydata, int selection, int type,
942
                        size_t keylen)
943
12.3k
{
944
12.3k
    const ECX_KEY *ecx = keydata;
945
12.3k
    int ok = keylen == ecx->keylen;
946
947
12.3k
    if (!ossl_prov_is_running())
948
0
        return 0;
949
950
12.3k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
951
26
        return 1; /* nothing to validate */
952
953
12.3k
    if (!ok) {
954
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
955
0
        return 0;
956
0
    }
957
958
12.3k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
959
12.3k
        ok = ok && ecx->haspubkey;
960
#ifdef FIPS_MODULE
961
        ok = ok && ecd_key_pub_check(ecx, type);
962
#endif
963
12.3k
    }
964
965
12.3k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
966
52
        ok = ok && ecx->privkey != NULL;
967
968
12.3k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
969
12.3k
        return ok;
970
971
26
    if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448)
972
15
        ok = ok && ecd_key_pairwise_check(ecx, type);
973
11
    else
974
11
        ok = ok && ecx_key_pairwise_check(ecx, type);
975
976
26
    return ok;
977
12.3k
}
978
979
static int x25519_validate(const void *keydata, int selection, int checktype)
980
31.2k
{
981
31.2k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
982
31.2k
}
983
984
static int x448_validate(const void *keydata, int selection, int checktype)
985
81
{
986
81
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
987
81
}
988
989
static int ed25519_validate(const void *keydata, int selection, int checktype)
990
40
{
991
40
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
992
40
}
993
994
static int ed448_validate(const void *keydata, int selection, int checktype)
995
72
{
996
72
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
997
72
}
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