Coverage Report

Created: 2025-12-04 06:33

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl35/providers/implementations/keymgmt/ecx_kmgmt.c
Line
Count
Source
1
/*
2
 * Copyright 2020-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
15.3k
#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
14
{
102
14
    return type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448;
103
14
}
104
105
static void *x25519_new_key(void *provctx)
106
17
{
107
17
    if (!ossl_prov_is_running())
108
0
        return 0;
109
17
    return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
110
17
                            NULL);
111
17
}
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
60.8k
{
139
60.8k
    const ECX_KEY *key = keydata;
140
60.8k
    int ok = 0;
141
142
60.8k
    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
30.6k
        ok = 1;
148
149
30.6k
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
150
112
            ok = ok && key->haspubkey;
151
152
30.6k
        if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
153
28
            ok = ok && key->privkey != NULL;
154
30.6k
    }
155
60.8k
    return ok;
156
60.8k
}
157
158
static int ecx_match(const void *keydata1, const void *keydata2, int selection)
159
56
{
160
56
    const ECX_KEY *key1 = keydata1;
161
56
    const ECX_KEY *key2 = keydata2;
162
56
    int ok = 1;
163
164
56
    if (!ossl_prov_is_running())
165
0
        return 0;
166
167
56
    if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
168
56
        ok = ok && key1->type == key2->type;
169
56
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
170
56
        int key_checked = 0;
171
172
56
        if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
173
56
            const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
174
56
            const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
175
56
            size_t pal = key1->keylen;
176
56
            size_t pbl = key2->keylen;
177
178
56
            if (pa != NULL && pb != NULL) {
179
56
                ok = ok
180
56
                    && key1->type == key2->type
181
56
                    && pal == pbl
182
56
                    && CRYPTO_memcmp(pa, pb, pal) == 0;
183
56
                key_checked = 1;
184
56
            }
185
56
        }
186
56
        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
56
        ok = ok && key_checked;
202
56
    }
203
56
    return ok;
204
56
}
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
441k
{
227
441k
    if (key == NULL)
228
0
        return 0;
229
230
441k
    if (!ossl_param_build_set_octet_string(tmpl, params,
231
441k
                                           OSSL_PKEY_PARAM_PUB_KEY,
232
441k
                                           key->pubkey, key->keylen))
233
0
        return 0;
234
235
441k
    if (include_private
236
399k
        && key->privkey != NULL
237
358k
        && !ossl_param_build_set_octet_string(tmpl, params,
238
358k
                                              OSSL_PKEY_PARAM_PRIV_KEY,
239
358k
                                              key->privkey, key->keylen))
240
0
        return 0;
241
242
441k
    return 1;
243
441k
}
244
245
static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
246
                      void *cbarg)
247
41.7k
{
248
41.7k
    ECX_KEY *key = keydata;
249
41.7k
    OSSL_PARAM_BLD *tmpl;
250
41.7k
    OSSL_PARAM *params = NULL;
251
41.7k
    int ret = 0;
252
253
41.7k
    if (!ossl_prov_is_running() || key == NULL)
254
0
        return 0;
255
256
41.7k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
257
0
        return 0;
258
259
41.7k
    tmpl = OSSL_PARAM_BLD_new();
260
41.7k
    if (tmpl == NULL)
261
0
        return 0;
262
263
41.7k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
264
41.7k
        int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
265
266
41.7k
        if (!key_to_params(key, tmpl, NULL, include_private))
267
0
            goto err;
268
41.7k
    }
269
270
41.7k
    params = OSSL_PARAM_BLD_to_param(tmpl);
271
41.7k
    if (params == NULL)
272
0
        goto err;
273
274
41.7k
    ret = param_cb(params, cbarg);
275
41.7k
    OSSL_PARAM_free(params);
276
41.7k
err:
277
41.7k
    OSSL_PARAM_BLD_free(tmpl);
278
41.7k
    return ret;
279
41.7k
}
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
273k
{
299
273k
    ECX_KEY *ecx = key;
300
273k
    OSSL_PARAM *p;
301
302
273k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
303
120k
        && !OSSL_PARAM_set_int(p, bits))
304
0
        return 0;
305
273k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
306
120k
        && !OSSL_PARAM_set_int(p, secbits))
307
0
        return 0;
308
273k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
309
120k
        && !OSSL_PARAM_set_int(p, size))
310
0
        return 0;
311
273k
    if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
312
152k
            && (ecx->type == ECX_KEY_TYPE_X25519
313
152k
                || ecx->type == ECX_KEY_TYPE_X448)) {
314
152k
        if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
315
0
            return 0;
316
152k
    }
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
273k
    return key_to_params(ecx, NULL, params, 1);
329
273k
}
330
331
static int ed_get_params(void *key, OSSL_PARAM params[])
332
1.03k
{
333
1.03k
    OSSL_PARAM *p;
334
335
1.03k
    if ((p = OSSL_PARAM_locate(params,
336
1.03k
                               OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
337
212
        && !OSSL_PARAM_set_utf8_string(p, ""))
338
0
        return 0;
339
1.03k
    return 1;
340
1.03k
}
341
342
static int x25519_get_params(void *key, OSSL_PARAM params[])
343
395k
{
344
395k
    return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
345
395k
                          X25519_KEYLEN);
346
395k
}
347
348
static int x448_get_params(void *key, OSSL_PARAM params[])
349
3.57k
{
350
3.57k
    return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
351
3.57k
                          X448_KEYLEN);
352
3.57k
}
353
354
static int ed25519_get_params(void *key, OSSL_PARAM params[])
355
425
{
356
425
    return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
357
425
                          ED25519_SIGSIZE)
358
425
        && ed_get_params(key, params);
359
425
}
360
361
static int ed448_get_params(void *key, OSSL_PARAM params[])
362
614
{
363
614
    return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
364
614
                          ED448_SIGSIZE)
365
614
        && ed_get_params(key, params);
366
614
}
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
5.77k
{
421
5.77k
    ECX_KEY *ecxkey = key;
422
5.77k
    const OSSL_PARAM *p;
423
424
5.77k
    if (ossl_param_is_empty(params))
425
0
        return 1;
426
427
5.77k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
428
5.77k
    if (p != NULL) {
429
5.77k
        void *buf = ecxkey->pubkey;
430
431
5.77k
        if (p->data_size != ecxkey->keylen
432
5.75k
                || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
433
5.75k
                                                NULL))
434
15
            return 0;
435
5.75k
        OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
436
5.75k
        ecxkey->privkey = NULL;
437
5.75k
        ecxkey->haspubkey = 1;
438
5.75k
    }
439
5.75k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
440
5.75k
    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
5.75k
    return 1;
447
5.75k
}
448
449
static int x25519_set_params(void *key, const OSSL_PARAM params[])
450
36.4k
{
451
36.4k
    return ecx_set_params(key, params);
452
36.4k
}
453
454
static int x448_set_params(void *key, const OSSL_PARAM params[])
455
69
{
456
69
    return ecx_set_params(key, params);
457
69
}
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
153k
{
503
153k
    OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
504
153k
    struct ecx_gen_ctx *gctx = NULL;
505
506
153k
    if (!ossl_prov_is_running())
507
0
        return NULL;
508
509
153k
    if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
510
153k
        gctx->libctx = libctx;
511
153k
        gctx->type = type;
512
153k
        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
153k
    } else {
522
0
        return NULL;
523
0
    }
524
153k
    if (!ecx_gen_set_params(gctx, params)) {
525
0
        ecx_gen_cleanup(gctx);
526
0
        gctx = NULL;
527
0
    }
528
153k
    return gctx;
529
153k
}
530
531
static void *x25519_gen_init(void *provctx, int selection,
532
                             const OSSL_PARAM params[])
533
153k
{
534
153k
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
535
153k
}
536
537
static void *x448_gen_init(void *provctx, int selection,
538
                           const OSSL_PARAM params[])
539
424
{
540
424
    return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
541
424
}
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
172k
{
557
172k
    struct ecx_gen_ctx *gctx = genctx;
558
172k
    const OSSL_PARAM *p;
559
560
172k
    if (gctx == NULL)
561
0
        return 0;
562
563
172k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
564
172k
    if (p != NULL) {
565
70.2k
        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
70.2k
        switch (gctx->type) {
573
69.9k
            case ECX_KEY_TYPE_X25519:
574
69.9k
                groupname = "x25519";
575
69.9k
                break;
576
263
            case ECX_KEY_TYPE_X448:
577
263
                groupname = "x448";
578
263
                break;
579
0
            default:
580
                /* We only support this for key exchange at the moment */
581
0
                break;
582
70.2k
        }
583
70.2k
        if (p->data_type != OSSL_PARAM_UTF8_STRING
584
70.2k
                || groupname == NULL
585
70.2k
                || 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
70.2k
    }
590
172k
    p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
591
172k
    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
172k
    p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
600
172k
    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
172k
    return 1;
611
172k
}
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
90.1k
{
695
90.1k
    ECX_KEY *key;
696
90.1k
    unsigned char *privkey;
697
698
90.1k
    if (gctx == NULL)
699
0
        return NULL;
700
90.1k
    if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
701
90.1k
                                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
90.1k
    if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
708
2.66k
        return key;
709
710
87.5k
    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
87.5k
#ifndef FIPS_MODULE
715
87.5k
    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
87.5k
#endif
723
87.5k
    {
724
87.5k
        if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
725
0
            goto err;
726
87.5k
    }
727
728
87.5k
    switch (gctx->type) {
729
87.3k
    case ECX_KEY_TYPE_X25519:
730
87.3k
        privkey[0] &= 248;
731
87.3k
        privkey[X25519_KEYLEN - 1] &= 127;
732
87.3k
        privkey[X25519_KEYLEN - 1] |= 64;
733
87.3k
        ossl_x25519_public_from_private(key->pubkey, privkey);
734
87.3k
        break;
735
156
    case ECX_KEY_TYPE_X448:
736
156
        privkey[0] &= 252;
737
156
        privkey[X448_KEYLEN - 1] |= 128;
738
156
        ossl_x448_public_from_private(key->pubkey, privkey);
739
156
        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
87.5k
    }
751
87.5k
    key->haspubkey = 1;
752
87.5k
    return key;
753
0
err:
754
0
    ossl_ecx_key_free(key);
755
0
    return NULL;
756
87.5k
}
757
758
static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
759
153k
{
760
153k
    struct ecx_gen_ctx *gctx = genctx;
761
762
153k
    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
153k
    return ecx_gen(gctx);
770
153k
}
771
772
static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
773
424
{
774
424
    struct ecx_gen_ctx *gctx = genctx;
775
776
424
    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
424
    return ecx_gen(gctx);
784
424
}
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
153k
{
855
153k
    struct ecx_gen_ctx *gctx = genctx;
856
857
153k
    if (gctx == NULL)
858
0
        return;
859
860
153k
    OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
861
153k
    OPENSSL_free(gctx->propq);
862
153k
    OPENSSL_free(gctx);
863
153k
}
864
865
void *ecx_load(const void *reference, size_t reference_sz)
866
4.21k
{
867
4.21k
    ECX_KEY *key = NULL;
868
869
4.21k
    if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
870
        /* The contents of the reference is the address to our object */
871
4.21k
        key = *(ECX_KEY **)reference;
872
        /* We grabbed, so we detach it */
873
4.21k
        *(ECX_KEY **)reference = NULL;
874
4.21k
        return key;
875
4.21k
    }
876
0
    return NULL;
877
4.21k
}
878
879
static void *ecx_dup(const void *keydata_from, int selection)
880
30.2k
{
881
30.2k
    if (ossl_prov_is_running())
882
30.2k
        return ossl_ecx_key_dup(keydata_from, selection);
883
0
    return NULL;
884
30.2k
}
885
886
static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
887
9
{
888
9
    uint8_t pub[64];
889
890
9
    switch (type) {
891
4
    case ECX_KEY_TYPE_X25519:
892
4
        ossl_x25519_public_from_private(pub, ecx->privkey);
893
4
        break;
894
5
    case ECX_KEY_TYPE_X448:
895
5
        ossl_x448_public_from_private(pub, ecx->privkey);
896
5
        break;
897
0
    default:
898
0
        return 0;
899
9
    }
900
9
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
901
9
}
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
13
{
930
13
    uint8_t pub[64];
931
932
13
    switch (type) {
933
4
    case ECX_KEY_TYPE_ED25519:
934
4
        if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
935
4
                                              ecx->propq))
936
0
            return 0;
937
4
        break;
938
9
    case ECX_KEY_TYPE_ED448:
939
9
        if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
940
9
                                            ecx->propq))
941
0
            return 0;
942
9
        break;
943
9
    default:
944
0
        return 0;
945
13
    }
946
13
    return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
947
13
}
948
#endif
949
950
static int ecx_validate(const void *keydata, int selection, int type,
951
                        size_t keylen)
952
15.3k
{
953
15.3k
    const ECX_KEY *ecx = keydata;
954
15.3k
    int ok = keylen == ecx->keylen;
955
956
15.3k
    if (!ossl_prov_is_running())
957
0
        return 0;
958
959
15.3k
    if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
960
14
        return 1; /* nothing to validate */
961
962
15.3k
    if (!ok) {
963
0
        ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
964
0
        return 0;
965
0
    }
966
967
15.3k
    if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
968
15.3k
        ok = ok && ecx->haspubkey;
969
#ifdef FIPS_MODULE
970
        ok = ok && ecd_key_pub_check(ecx, type);
971
#endif
972
15.3k
    }
973
974
15.3k
    if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
975
28
        ok = ok && ecx->privkey != NULL;
976
977
15.3k
    if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
978
15.3k
        return ok;
979
980
14
    if (ecx_key_type_is_ed(type))
981
6
        ok = ok && ecd_key_pairwise_check(ecx, type);
982
8
    else
983
8
        ok = ok && ecx_key_pairwise_check(ecx, type);
984
985
14
    return ok;
986
15.3k
}
987
988
static int x25519_validate(const void *keydata, int selection, int checktype)
989
34.4k
{
990
34.4k
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
991
34.4k
}
992
993
static int x448_validate(const void *keydata, int selection, int checktype)
994
87
{
995
87
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
996
87
}
997
998
static int ed25519_validate(const void *keydata, int selection, int checktype)
999
48
{
1000
48
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
1001
48
}
1002
1003
static int ed448_validate(const void *keydata, int selection, int checktype)
1004
80
{
1005
80
    return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
1006
80
}
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