Coverage Report

Created: 2026-10-28 06:28

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