Coverage Report

Created: 2025-12-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/evp/pmeth_gn.c
Line
Count
Source
1
/*
2
 * Copyright 2006-2025 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License").  You may not use
5
 * this file except in compliance with the License.  You can obtain a copy
6
 * in the file LICENSE in the source distribution or at
7
 * https://www.openssl.org/source/license.html
8
 */
9
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <openssl/core.h>
13
#include <openssl/core_names.h>
14
#include "internal/cryptlib.h"
15
#include "internal/core.h"
16
#include "internal/common.h"
17
#include <openssl/objects.h>
18
#include <openssl/evp.h>
19
#include "crypto/bn.h"
20
#ifndef FIPS_MODULE
21
#include "crypto/asn1.h"
22
#endif
23
#include "crypto/evp.h"
24
#include "evp_local.h"
25
26
static int gen_init(EVP_PKEY_CTX *ctx, int operation)
27
0
{
28
0
    int ret = 0;
29
30
0
    if (ctx == NULL)
31
0
        goto not_supported;
32
33
0
    evp_pkey_ctx_free_old_ops(ctx);
34
0
    ctx->operation = operation;
35
36
0
    if (ctx->keymgmt == NULL || ctx->keymgmt->gen_init == NULL)
37
0
        goto legacy;
38
39
0
    switch (operation) {
40
0
    case EVP_PKEY_OP_PARAMGEN:
41
0
        ctx->op.keymgmt.genctx = evp_keymgmt_gen_init(ctx->keymgmt,
42
0
            OSSL_KEYMGMT_SELECT_ALL_PARAMETERS, NULL);
43
0
        break;
44
0
    case EVP_PKEY_OP_KEYGEN:
45
0
        ctx->op.keymgmt.genctx = evp_keymgmt_gen_init(ctx->keymgmt, OSSL_KEYMGMT_SELECT_KEYPAIR,
46
0
            NULL);
47
0
        break;
48
0
    }
49
50
0
    if (ctx->op.keymgmt.genctx == NULL)
51
0
        ERR_raise(ERR_LIB_EVP, EVP_R_INITIALIZATION_ERROR);
52
0
    else
53
0
        ret = 1;
54
0
    goto end;
55
56
0
legacy:
57
#ifdef FIPS_MODULE
58
    goto not_supported;
59
#else
60
0
    if (ctx->pmeth == NULL
61
0
        || (operation == EVP_PKEY_OP_PARAMGEN
62
0
            && ctx->pmeth->paramgen == NULL)
63
0
        || (operation == EVP_PKEY_OP_KEYGEN
64
0
            && ctx->pmeth->keygen == NULL))
65
0
        goto not_supported;
66
67
0
    ret = 1;
68
0
    switch (operation) {
69
0
    case EVP_PKEY_OP_PARAMGEN:
70
0
        if (ctx->pmeth->paramgen_init != NULL)
71
0
            ret = ctx->pmeth->paramgen_init(ctx);
72
0
        break;
73
0
    case EVP_PKEY_OP_KEYGEN:
74
0
        if (ctx->pmeth->keygen_init != NULL)
75
0
            ret = ctx->pmeth->keygen_init(ctx);
76
0
        break;
77
0
    }
78
0
#endif
79
80
0
end:
81
0
    if (ret <= 0 && ctx != NULL) {
82
0
        evp_pkey_ctx_free_old_ops(ctx);
83
0
        ctx->operation = EVP_PKEY_OP_UNDEFINED;
84
0
    }
85
0
    return ret;
86
87
0
not_supported:
88
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
89
0
    ret = -2;
90
0
    goto end;
91
0
}
92
93
int EVP_PKEY_paramgen_init(EVP_PKEY_CTX *ctx)
94
0
{
95
0
    return gen_init(ctx, EVP_PKEY_OP_PARAMGEN);
96
0
}
97
98
int EVP_PKEY_keygen_init(EVP_PKEY_CTX *ctx)
99
0
{
100
0
    return gen_init(ctx, EVP_PKEY_OP_KEYGEN);
101
0
}
102
103
static int ossl_callback_to_pkey_gencb(const OSSL_PARAM params[], void *arg)
104
0
{
105
0
    EVP_PKEY_CTX *ctx = arg;
106
0
    const OSSL_PARAM *param = NULL;
107
0
    int p = -1, n = -1;
108
109
0
    if (ctx->pkey_gencb == NULL)
110
0
        return 1; /* No callback?  That's fine */
111
112
0
    if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_POTENTIAL))
113
0
            == NULL
114
0
        || !OSSL_PARAM_get_int(param, &p))
115
0
        return 0;
116
0
    if ((param = OSSL_PARAM_locate_const(params, OSSL_GEN_PARAM_ITERATION))
117
0
            == NULL
118
0
        || !OSSL_PARAM_get_int(param, &n))
119
0
        return 0;
120
121
0
    ctx->keygen_info[0] = p;
122
0
    ctx->keygen_info[1] = n;
123
124
0
    return ctx->pkey_gencb(ctx);
125
0
}
126
127
int EVP_PKEY_generate(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
128
0
{
129
0
    int ret = 0;
130
0
    EVP_PKEY *allocated_pkey = NULL;
131
    /* Legacy compatible keygen callback info, only used with provider impls */
132
0
    int gentmp[2];
133
134
0
    if (ppkey == NULL)
135
0
        return -1;
136
137
0
    if (ctx == NULL)
138
0
        goto not_supported;
139
140
0
    if ((ctx->operation & EVP_PKEY_OP_TYPE_GEN) == 0)
141
0
        goto not_initialized;
142
143
0
    if (*ppkey == NULL)
144
0
        *ppkey = allocated_pkey = EVP_PKEY_new();
145
146
0
    if (*ppkey == NULL) {
147
0
        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
148
0
        return -1;
149
0
    }
150
151
0
    if (ctx->op.keymgmt.genctx == NULL)
152
0
        goto legacy;
153
154
    /*
155
     * Assigning gentmp to ctx->keygen_info is something our legacy
156
     * implementations do.  Because the provider implementations aren't
157
     * allowed to reach into our EVP_PKEY_CTX, we need to provide similar
158
     * space for backward compatibility.  It's ok that we attach a local
159
     * variable, as it should only be useful in the calls down from here.
160
     * This is cleared as soon as it isn't useful any more, i.e. directly
161
     * after the evp_keymgmt_util_gen() call.
162
     */
163
0
    ctx->keygen_info = gentmp;
164
0
    ctx->keygen_info_count = 2;
165
166
0
    ret = 1;
167
0
    if (ctx->pkey != NULL) {
168
0
        EVP_KEYMGMT *tmp_keymgmt = ctx->keymgmt;
169
0
        void *keydata = evp_pkey_export_to_provider(ctx->pkey, ctx->libctx,
170
0
            &tmp_keymgmt, ctx->propquery);
171
172
0
        if (tmp_keymgmt == NULL)
173
0
            goto not_supported;
174
        /*
175
         * It's ok if keydata is NULL here.  The backend is expected to deal
176
         * with that as it sees fit.
177
         */
178
0
        ret = evp_keymgmt_gen_set_template(ctx->keymgmt,
179
0
            ctx->op.keymgmt.genctx, keydata);
180
0
    }
181
182
    /*
183
     * the returned value from evp_keymgmt_util_gen() is cached in *ppkey,
184
     * so we do not need to save it, just check it.
185
     */
186
0
    ret = ret
187
0
        && (evp_keymgmt_util_gen(*ppkey, ctx->keymgmt, ctx->op.keymgmt.genctx,
188
0
                ossl_callback_to_pkey_gencb, ctx)
189
0
            != NULL);
190
191
0
    ctx->keygen_info = NULL;
192
193
0
#if !defined(FIPS_MODULE) && !defined(OPENSSL_NO_DEPRECATED_3_6)
194
    /* In case |*ppkey| was originally a legacy key */
195
0
    if (ret)
196
0
        evp_pkey_free_legacy(*ppkey);
197
0
#endif
198
199
    /*
200
     * Because we still have legacy keys
201
     */
202
0
    (*ppkey)->type = ctx->legacy_keytype;
203
204
0
    goto end;
205
206
0
legacy:
207
#ifdef FIPS_MODULE
208
    goto not_supported;
209
#else
210
    /*
211
     * If we get here then we're using legacy paramgen/keygen. In that case
212
     * the pkey in ctx (if there is one) had better not be provided (because the
213
     * legacy methods may not know how to handle it). However we can only get
214
     * here if ctx->op.keymgmt.genctx == NULL, but that should never be the case
215
     * if ctx->pkey is provided because we don't allow this when we initialise
216
     * the ctx.
217
     */
218
0
    if (ctx->pkey != NULL && !ossl_assert(!evp_pkey_is_provided(ctx->pkey)))
219
0
        goto not_accessible;
220
221
0
    switch (ctx->operation) {
222
0
    case EVP_PKEY_OP_PARAMGEN:
223
0
        ret = ctx->pmeth->paramgen(ctx, *ppkey);
224
0
        break;
225
0
    case EVP_PKEY_OP_KEYGEN:
226
0
        ret = ctx->pmeth->keygen(ctx, *ppkey);
227
0
        break;
228
0
    default:
229
0
        goto not_supported;
230
0
    }
231
0
#endif
232
233
0
end:
234
0
    if (ret <= 0) {
235
0
        if (allocated_pkey != NULL)
236
0
            *ppkey = NULL;
237
0
        EVP_PKEY_free(allocated_pkey);
238
0
    }
239
0
    return ret;
240
241
0
not_supported:
242
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
243
0
    ret = -2;
244
0
    goto end;
245
0
not_initialized:
246
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
247
0
    ret = -1;
248
0
    goto end;
249
0
#ifndef FIPS_MODULE
250
0
not_accessible:
251
0
    ERR_raise(ERR_LIB_EVP, EVP_R_INACCESSIBLE_DOMAIN_PARAMETERS);
252
0
    ret = -1;
253
0
    goto end;
254
0
#endif
255
0
}
256
257
int EVP_PKEY_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
258
0
{
259
0
    if (ctx->operation != EVP_PKEY_OP_PARAMGEN) {
260
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
261
0
        return -1;
262
0
    }
263
0
    return EVP_PKEY_generate(ctx, ppkey);
264
0
}
265
266
int EVP_PKEY_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey)
267
0
{
268
0
    if (ctx->operation != EVP_PKEY_OP_KEYGEN) {
269
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_INITIALIZED);
270
0
        return -1;
271
0
    }
272
0
    return EVP_PKEY_generate(ctx, ppkey);
273
0
}
274
275
void EVP_PKEY_CTX_set_cb(EVP_PKEY_CTX *ctx, EVP_PKEY_gen_cb *cb)
276
0
{
277
0
    ctx->pkey_gencb = cb;
278
0
}
279
280
EVP_PKEY_gen_cb *EVP_PKEY_CTX_get_cb(EVP_PKEY_CTX *ctx)
281
0
{
282
0
    return ctx->pkey_gencb;
283
0
}
284
285
/*
286
 * "translation callback" to call EVP_PKEY_CTX callbacks using BN_GENCB style
287
 * callbacks.
288
 */
289
290
static int trans_cb(int a, int b, BN_GENCB *gcb)
291
0
{
292
0
    EVP_PKEY_CTX *ctx = BN_GENCB_get_arg(gcb);
293
0
    ctx->keygen_info[0] = a;
294
0
    ctx->keygen_info[1] = b;
295
0
    return ctx->pkey_gencb(ctx);
296
0
}
297
298
void evp_pkey_set_cb_translate(BN_GENCB *cb, EVP_PKEY_CTX *ctx)
299
0
{
300
0
    BN_GENCB_set(cb, trans_cb, ctx);
301
0
}
302
303
int EVP_PKEY_CTX_get_keygen_info(EVP_PKEY_CTX *ctx, int idx)
304
0
{
305
0
    if (idx == -1)
306
0
        return ctx->keygen_info_count;
307
0
    if (idx < 0 || idx > ctx->keygen_info_count)
308
0
        return 0;
309
0
    return ctx->keygen_info[idx];
310
0
}
311
312
#ifndef FIPS_MODULE
313
314
EVP_PKEY *EVP_PKEY_new_mac_key(int type, ENGINE *e,
315
    const unsigned char *key, int keylen)
316
0
{
317
0
    EVP_PKEY_CTX *mac_ctx = NULL;
318
0
    EVP_PKEY *mac_key = NULL;
319
320
0
    if (!ossl_assert(e == NULL))
321
0
        return NULL;
322
0
    mac_ctx = EVP_PKEY_CTX_new_id(type, NULL);
323
0
    if (!mac_ctx)
324
0
        return NULL;
325
0
    if (EVP_PKEY_keygen_init(mac_ctx) <= 0)
326
0
        goto merr;
327
0
    if (EVP_PKEY_CTX_set_mac_key(mac_ctx, key, keylen) <= 0)
328
0
        goto merr;
329
0
    if (EVP_PKEY_keygen(mac_ctx, &mac_key) <= 0)
330
0
        goto merr;
331
0
merr:
332
0
    EVP_PKEY_CTX_free(mac_ctx);
333
0
    return mac_key;
334
0
}
335
336
#endif /* FIPS_MODULE */
337
338
/*- All methods below can also be used in FIPS_MODULE */
339
340
static int fromdata_init(EVP_PKEY_CTX *ctx, int operation)
341
0
{
342
0
    if (ctx == NULL || ctx->keytype == NULL)
343
0
        goto not_supported;
344
345
0
    evp_pkey_ctx_free_old_ops(ctx);
346
0
    if (ctx->keymgmt == NULL)
347
0
        goto not_supported;
348
349
0
    ctx->operation = operation;
350
0
    return 1;
351
352
0
not_supported:
353
0
    if (ctx != NULL)
354
0
        ctx->operation = EVP_PKEY_OP_UNDEFINED;
355
0
    ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
356
0
    return -2;
357
0
}
358
359
int EVP_PKEY_fromdata_init(EVP_PKEY_CTX *ctx)
360
0
{
361
0
    return fromdata_init(ctx, EVP_PKEY_OP_FROMDATA);
362
0
}
363
364
int EVP_PKEY_fromdata(EVP_PKEY_CTX *ctx, EVP_PKEY **ppkey, int selection,
365
    OSSL_PARAM params[])
366
0
{
367
0
    void *keydata = NULL;
368
0
    EVP_PKEY *allocated_pkey = NULL;
369
370
0
    if (ctx == NULL || (ctx->operation & EVP_PKEY_OP_FROMDATA) == 0) {
371
0
        ERR_raise(ERR_LIB_EVP, EVP_R_OPERATION_NOT_SUPPORTED_FOR_THIS_KEYTYPE);
372
0
        return -2;
373
0
    }
374
375
0
    if (ppkey == NULL)
376
0
        return -1;
377
378
0
    if (*ppkey == NULL)
379
0
        allocated_pkey = *ppkey = EVP_PKEY_new();
380
381
0
    if (*ppkey == NULL) {
382
0
        ERR_raise(ERR_LIB_EVP, ERR_R_EVP_LIB);
383
0
        return -1;
384
0
    }
385
386
0
    keydata = evp_keymgmt_util_fromdata(*ppkey, ctx->keymgmt, selection, params);
387
0
    if (keydata == NULL) {
388
0
        if (allocated_pkey != NULL) {
389
0
            *ppkey = NULL;
390
0
            EVP_PKEY_free(allocated_pkey);
391
0
        }
392
0
        return 0;
393
0
    }
394
    /* keydata is cached in *ppkey, so we need not bother with it further */
395
0
    return 1;
396
0
}
397
398
const OSSL_PARAM *EVP_PKEY_fromdata_settable(EVP_PKEY_CTX *ctx, int selection)
399
0
{
400
    /* We call fromdata_init to get ctx->keymgmt populated */
401
0
    if (fromdata_init(ctx, EVP_PKEY_OP_UNDEFINED) == 1)
402
0
        return evp_keymgmt_import_types(ctx->keymgmt, selection);
403
0
    return NULL;
404
0
}
405
406
static OSSL_CALLBACK ossl_pkey_todata_cb;
407
408
static int ossl_pkey_todata_cb(const OSSL_PARAM params[], void *arg)
409
0
{
410
0
    OSSL_PARAM **ret = arg;
411
412
0
    *ret = OSSL_PARAM_dup(params);
413
0
    return 1;
414
0
}
415
416
int EVP_PKEY_todata(const EVP_PKEY *pkey, int selection, OSSL_PARAM **params)
417
0
{
418
0
    if (params == NULL)
419
0
        return 0;
420
0
    return EVP_PKEY_export(pkey, selection, ossl_pkey_todata_cb, params);
421
0
}
422
423
#ifndef FIPS_MODULE
424
struct fake_import_data_st {
425
    OSSL_CALLBACK *export_cb;
426
    void *export_cbarg;
427
};
428
429
static OSSL_FUNC_keymgmt_import_fn pkey_fake_import;
430
static int pkey_fake_import(void *fake_keydata, int ignored_selection,
431
    const OSSL_PARAM params[])
432
0
{
433
0
    struct fake_import_data_st *data = fake_keydata;
434
435
0
    return data->export_cb(params, data->export_cbarg);
436
0
}
437
#endif
438
439
int EVP_PKEY_export(const EVP_PKEY *pkey, int selection,
440
    OSSL_CALLBACK *export_cb, void *export_cbarg)
441
0
{
442
0
    if (pkey == NULL) {
443
0
        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_NULL_PARAMETER);
444
0
        return 0;
445
0
    }
446
0
#ifndef FIPS_MODULE
447
0
    if (evp_pkey_is_legacy(pkey)) {
448
0
        struct fake_import_data_st data;
449
450
0
        data.export_cb = export_cb;
451
0
        data.export_cbarg = export_cbarg;
452
453
        /*
454
         * We don't need to care about libctx or propq here, as we're only
455
         * interested in the resulting OSSL_PARAM array.
456
         */
457
0
        return pkey->ameth->export_to(pkey, &data, pkey_fake_import,
458
0
            NULL, NULL);
459
0
    }
460
0
#endif
461
0
    return evp_keymgmt_util_export(pkey, selection, export_cb, export_cbarg);
462
0
}