Coverage Report

Created: 2025-08-03 07:12

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