Coverage Report

Created: 2025-11-16 06:40

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