Coverage Report

Created: 2026-10-28 06:28

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