Coverage Report

Created: 2026-09-12 06:55

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