Coverage Report

Created: 2024-05-21 06:33

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