Coverage Report

Created: 2026-07-23 06:28

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