Coverage Report

Created: 2025-08-11 07:04

/src/openssl33/providers/implementations/keymgmt/ecx_kmgmt.c
Line
Count
Source (jump to first uncovered line)
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
11.4k
#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
19
{
96
19
    if (!ossl_prov_is_running())
97
0
        return 0;
98
19
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
99
19
                            NULL);
100
19
}
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
52.1k
{
128
52.1k
    const ECX_KEY *key = keydata;
129
52.1k
    int ok = 0;
130
131
52.1k
    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
26.2k
        ok = 1;
137
138
26.2k
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
139
134
            ok = ok && key->haspubkey;
140
141
26.2k
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
142
29
            ok = ok && key->privkey != NULL;
143
26.2k
    }
144
52.1k
    return ok;
145
52.1k
}
146
147
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
148
67
{
149
67
    const ECX_KEY *key1 = keydata1;
150
67
    const ECX_KEY *key2 = keydata2;
151
67
    int ok = 1;
152
153
67
    if (!ossl_prov_is_running())
154
0
        return 0;
155
156
67
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
157
67
        ok = ok && key1->type == key2->type;
158
67
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
159
67
        int key_checked = 0;
160
161
67
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
162
67
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
163
67
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
164
67
            size_t pal = key1->keylen;
165
67
            size_t pbl = key2->keylen;
166
167
67
            if (pa != NULL && pb != NULL) {
168
67
                ok = ok
169
67
                    && key1->type == key2->type
170
67
                    && pal == pbl
171
67
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
172
67
                key_checked = 1;
173
67
            }
174
67
        }
175
67
        if (!key_checked
176
67
            && (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
67
        ok = ok && key_checked;
191
67
    }
192
67
    return ok;
193
67
}
194
195
static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
196
19
{
197
19
    ECX_KEY *key = keydata;
198
19
    int ok = 1;
199
19
    int include_private;
200
201
19
    if (!ossl_prov_is_running() || key == NULL)
202
0
        return 0;
203
204
19
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
205
0
        return 0;
206
207
19
    include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
208
19
    ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
209
210
19
    return ok;
211
19
}
212
213
static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
214
                         OSSL_PARAM params[], int include_private)
215
374k
{
216
374k
    if (key == NULL)
217
0
        return 0;
218
219
374k
    if (!ossl_param_build_set_octet_string(tmpl, params,
220
374k
                                           OSSL_PKEY_PARAM_PUB_KEY,
221
374k
                                           key->pubkey, key->keylen))
222
0
        return 0;
223
224
374k
    if (include_private
225
374k
        && key->privkey != NULL
226
374k
        && !ossl_param_build_set_octet_string(tmpl, params,
227
308k
                                              OSSL_PKEY_PARAM_PRIV_KEY,
228
308k
                                              key->privkey, key->keylen))
229
0
        return 0;
230
231
374k
    return 1;
232
374k
}
233
234
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
235
                      void *cbarg)
236
30.1k
{
237
30.1k
    ECX_KEY *key = keydata;
238
30.1k
    OSSL_PARAM_BLD *tmpl;
239
30.1k
    OSSL_PARAM *params = NULL;
240
30.1k
    int ret = 0;
241
242
30.1k
    if (!ossl_prov_is_running() || key == NULL)
243
0
        return 0;
244
245
30.1k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
246
0
        return 0;
247
248
30.1k
    tmpl = OSSL_PARAM_BLD_new();
249
30.1k
    if (tmpl == NULL)
250
0
        return 0;
251
252
30.1k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
253
30.1k
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
254
255
30.1k
        if (!key_to_params(key, tmpl, NULL, include_private))
256
0
            goto err;
257
30.1k
    }
258
259
30.1k
    params = OSSL_PARAM_BLD_to_param(tmpl);
260
30.1k
    if (params == NULL)
261
0
        goto err;
262
263
30.1k
    ret = param_cb(params, cbarg);
264
30.1k
    OSSL_PARAM_free(params);
265
30.1k
err:
266
30.1k
    OSSL_PARAM_BLD_free(tmpl);
267
30.1k
    return ret;
268
30.1k
}
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
270k
{
288
270k
    ECX_KEY *ecx = key;
289
270k
    OSSL_PARAM *p;
290
291
270k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
292
270k
        && !OSSL_PARAM_set_int(p, bits))
293
0
        return 0;
294
270k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
295
270k
        && !OSSL_PARAM_set_int(p, secbits))
296
0
        return 0;
297
270k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
298
270k
        && !OSSL_PARAM_set_int(p, size))
299
0
        return 0;
300
270k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
301
270k
            && (ecx->type == ECX_KEY_TYPE_X25519
302
150k
                || ecx->type == ECX_KEY_TYPE_X448)) {
303
150k
        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
304
0
            return 0;
305
150k
    }
306
307
270k
    return key_to_params(ecx, NULL, params, 1);
308
270k
}
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
822
        && !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
340k
{
323
340k
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
324
340k
                          X25519_KEYLEN);
325
340k
}
326
327
static int x448_get_params(void *key, OSSL_PARAM params[])
328
3.32k
{
329
3.32k
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
330
3.32k
                          X448_KEYLEN);
331
3.32k
}
332
333
static int ed25519_get_params(void *key, OSSL_PARAM params[])
334
205
{
335
205
    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
336
205
                          ED25519_SIGSIZE)
337
205
        && ed_get_params(key, params);
338
205
}
339
340
static int ed448_get_params(void *key, OSSL_PARAM params[])
341
560
{
342
560
    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
343
560
                          ED448_SIGSIZE)
344
560
        && ed_get_params(key, params);
345
560
}
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
21.2k
{
399
21.2k
    ECX_KEY *ecxkey = key;
400
21.2k
    const OSSL_PARAM *p;
401
402
21.2k
    if (params == NULL)
403
0
        return 1;
404
405
21.2k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
406
21.2k
    if (p != NULL) {
407
21.2k
        void *buf = ecxkey->pubkey;
408
409
21.2k
        if (p->data_size != ecxkey->keylen
410
21.2k
                || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
411
21.1k
                                                NULL))
412
70
            return 0;
413
21.1k
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
414
21.1k
        ecxkey->privkey = NULL;
415
21.1k
        ecxkey->haspubkey = 1;
416
21.1k
    }
417
21.1k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
418
21.1k
    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
21.1k
    return 1;
425
21.1k
}
426
427
static int x25519_set_params(void *key, const OSSL_PARAM params[])
428
33.6k
{
429
33.6k
    return ecx_set_params(key, params);
430
33.6k
}
431
432
static int x448_set_params(void *key, const OSSL_PARAM params[])
433
43
{
434
43
    return ecx_set_params(key, params);
435
43
}
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
130k
{
480
130k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
481
130k
    struct ecx_gen_ctx *gctx = NULL;
482
483
130k
    if (!ossl_prov_is_running())
484
0
        return NULL;
485
486
130k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
487
130k
        gctx->libctx = libctx;
488
130k
        gctx->type = type;
489
130k
        gctx->selection = selection;
490
130k
    } else {
491
0
        return NULL;
492
0
    }
493
130k
    if (!ecx_gen_set_params(gctx, params)) {
494
0
        ecx_gen_cleanup(gctx);
495
0
        gctx = NULL;
496
0
    }
497
130k
    return gctx;
498
130k
}
499
500
static void *x25519_gen_init(void *provctx, int selection,
501
                             const OSSL_PARAM params[])
502
130k
{
503
130k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
504
130k
}
505
506
static void *x448_gen_init(void *provctx, int selection,
507
                           const OSSL_PARAM params[])
508
468
{
509
468
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
510
468
}
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
239k
{
526
239k
    struct ecx_gen_ctx *gctx = genctx;
527
239k
    const OSSL_PARAM *p;
528
529
239k
    if (gctx == NULL)
530
0
        return 0;
531
532
239k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
533
239k
    if (p != NULL) {
534
87.8k
        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
87.8k
        switch (gctx->type) {
542
87.3k
            case ECX_KEY_TYPE_X25519:
543
87.3k
                groupname = "x25519";
544
87.3k
                break;
545
454
            case ECX_KEY_TYPE_X448:
546
454
                groupname = "x448";
547
454
                break;
548
0
            default:
549
                /* We only support this for key exchange at the moment */
550
0
                break;
551
87.8k
        }
552
87.8k
        if (p->data_type != OSSL_PARAM_UTF8_STRING
553
87.8k
                || groupname == NULL
554
87.8k
                || 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
87.8k
    }
559
239k
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
560
239k
    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
239k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
569
239k
    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
239k
    return 1;
580
239k
}
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
55.9k
{
664
55.9k
    ECX_KEY *key;
665
55.9k
    unsigned char *privkey;
666
667
55.9k
    if (gctx == NULL)
668
0
        return NULL;
669
55.9k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
670
55.9k
                                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
55.9k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
677
3.91k
        return key;
678
679
52.0k
    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
52.0k
#ifndef FIPS_MODULE
684
52.0k
    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
52.0k
#endif
693
52.0k
    {
694
52.0k
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
695
0
            goto err;
696
52.0k
    }
697
698
52.0k
    switch (gctx->type) {
699
51.6k
    case ECX_KEY_TYPE_X25519:
700
51.6k
        privkey[0] &= 248;
701
51.6k
        privkey[X25519_KEYLEN - 1] &= 127;
702
51.6k
        privkey[X25519_KEYLEN - 1] |= 64;
703
51.6k
        ossl_x25519_public_from_private(key->pubkey, privkey);
704
51.6k
        break;
705
393
    case ECX_KEY_TYPE_X448:
706
393
        privkey[0] &= 252;
707
393
        privkey[X448_KEYLEN - 1] |= 128;
708
393
        ossl_x448_public_from_private(key->pubkey, privkey);
709
393
        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
52.0k
    }
721
52.0k
    key->haspubkey = 1;
722
52.0k
    return key;
723
0
err:
724
0
    ossl_ecx_key_free(key);
725
0
    return NULL;
726
52.0k
}
727
728
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
729
130k
{
730
130k
    struct ecx_gen_ctx *gctx = genctx;
731
732
130k
    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
130k
    return ecx_gen(gctx);
740
130k
}
741
742
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
743
468
{
744
468
    struct ecx_gen_ctx *gctx = genctx;
745
746
468
    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
468
    return ecx_gen(gctx);
754
468
}
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
130k
{
825
130k
    struct ecx_gen_ctx *gctx = genctx;
826
827
130k
    if (gctx == NULL)
828
0
        return;
829
830
130k
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
831
130k
    OPENSSL_free(gctx->propq);
832
130k
    OPENSSL_free(gctx);
833
130k
}
834
835
void *ecx_load(const void *reference, size_t reference_sz)
836
2.85k
{
837
2.85k
    ECX_KEY *key = NULL;
838
839
2.85k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
840
        /* The contents of the reference is the address to our object */
841
2.85k
        key = *(ECX_KEY **)reference;
842
        /* We grabbed, so we detach it */
843
2.85k
        *(ECX_KEY **)reference = NULL;
844
2.85k
        return key;
845
2.85k
    }
846
0
    return NULL;
847
2.85k
}
848
849
static void *ecx_dup(const void *keydata_from, int selection)
850
25.9k
{
851
25.9k
    if (ossl_prov_is_running())
852
25.9k
        return ossl_ecx_key_dup(keydata_from, selection);
853
0
    return NULL;
854
25.9k
}
855
856
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
857
24
{
858
24
    uint8_t pub[64];
859
860
24
    switch (type) {
861
5
    case ECX_KEY_TYPE_X25519:
862
5
        ossl_x25519_public_from_private(pub, ecx->privkey);
863
5
        break;
864
19
    case ECX_KEY_TYPE_X448:
865
19
        ossl_x448_public_from_private(pub, ecx->privkey);
866
19
        break;
867
0
    default:
868
0
        return 0;
869
24
    }
870
24
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
871
24
}
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
16
{
881
16
    uint8_t pub[64];
882
883
16
    switch (type) {
884
4
    case ECX_KEY_TYPE_ED25519:
885
4
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
886
4
                                              ecx->propq))
887
0
            return 0;
888
4
        break;
889
12
    case ECX_KEY_TYPE_ED448:
890
12
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
891
12
                                            ecx->propq))
892
0
            return 0;
893
12
        break;
894
12
    default:
895
0
        return 0;
896
16
    }
897
16
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
898
16
}
899
#endif
900
901
static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
902
11.4k
{
903
11.4k
    const ECX_KEY *ecx = keydata;
904
11.4k
    int ok = keylen == ecx->keylen;
905
906
11.4k
    if (!ossl_prov_is_running())
907
0
        return 0;
908
909
11.4k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
910
43
        return 1; /* nothing to validate */
911
912
11.3k
    if (!ok) {
913
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
914
0
        return 0;
915
0
    }
916
917
11.3k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
918
11.3k
        ok = ok && ecx->haspubkey;
919
920
11.3k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
921
86
        ok = ok && ecx->privkey != NULL;
922
923
11.3k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
924
11.3k
        return ok;
925
926
43
    if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448)
927
17
        ok = ok && ecd_key_pairwise_check(ecx, type);
928
26
    else
929
26
        ok = ok && ecx_key_pairwise_check(ecx, type);
930
931
43
    return ok;
932
11.3k
}
933
934
static int x25519_validate(const void *keydata, int selection, int checktype)
935
30.3k
{
936
30.3k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
937
30.3k
}
938
939
static int x448_validate(const void *keydata, int selection, int checktype)
940
120
{
941
120
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
942
120
}
943
944
static int ed25519_validate(const void *keydata, int selection, int checktype)
945
44
{
946
44
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
947
44
}
948
949
static int ed448_validate(const void *keydata, int selection, int checktype)
950
76
{
951
76
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
952
76
}
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