Coverage Report

Created: 2025-11-16 06:40

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