Coverage Report

Created: 2025-08-28 07:07

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