Coverage Report

Created: 2025-12-31 07:12

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