Coverage Report

Created: 2025-07-23 06:08

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