Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/crypto/asn1/ameth_lib.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
/*
11
 * We need to use some engine deprecated APIs
12
 */
13
#include "internal/deprecated.h"
14
15
#include "internal/cryptlib.h"
16
#include <stdio.h>
17
#include <openssl/asn1t.h>
18
#include <openssl/x509.h>
19
#include <openssl/engine.h>
20
#include "crypto/asn1.h"
21
#include "crypto/evp.h"
22
23
#include "standard_methods.h"
24
25
typedef int sk_cmp_fn_type(const char *const *a, const char *const *b);
26
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
27
28
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
29
    const EVP_PKEY_ASN1_METHOD *, ameth);
30
31
static int ameth_cmp(const EVP_PKEY_ASN1_METHOD *const *a,
32
    const EVP_PKEY_ASN1_METHOD *const *b)
33
17.0M
{
34
17.0M
    return ((*a)->pkey_id - (*b)->pkey_id);
35
17.0M
}
36
37
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
38
    const EVP_PKEY_ASN1_METHOD *, ameth);
39
40
int EVP_PKEY_asn1_get_count(void)
41
5.83M
{
42
5.83M
    int num = OSSL_NELEM(standard_methods);
43
5.83M
    if (app_methods)
44
0
        num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
45
5.83M
    return num;
46
5.83M
}
47
48
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
49
77.3M
{
50
77.3M
    int num = OSSL_NELEM(standard_methods);
51
77.3M
    if (idx < 0)
52
0
        return NULL;
53
77.3M
    if (idx < num)
54
77.3M
        return standard_methods[idx];
55
0
    idx -= num;
56
0
    return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
57
77.3M
}
58
59
static const EVP_PKEY_ASN1_METHOD *pkey_asn1_find(int type)
60
5.55M
{
61
5.55M
    EVP_PKEY_ASN1_METHOD tmp;
62
5.55M
    const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
63
64
5.55M
    tmp.pkey_id = type;
65
5.55M
    if (app_methods) {
66
0
        int idx;
67
0
        idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
68
0
        if (idx >= 0)
69
0
            return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
70
0
    }
71
5.55M
    ret = OBJ_bsearch_ameth(&t, standard_methods, OSSL_NELEM(standard_methods));
72
5.55M
    if (ret == NULL || *ret == NULL)
73
993k
        return NULL;
74
4.56M
    return *ret;
75
5.55M
}
76
77
/*
78
 * Find an implementation of an ASN1 algorithm. If 'pe' is not NULL also
79
 * search through engines and set *pe to a functional reference to the engine
80
 * implementing 'type' or NULL if no engine implements it.
81
 */
82
83
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find(ENGINE **pe, int type)
84
4.55M
{
85
4.55M
    const EVP_PKEY_ASN1_METHOD *t;
86
87
4.63M
    for (;;) {
88
4.63M
        t = pkey_asn1_find(type);
89
4.63M
        if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
90
4.55M
            break;
91
81.4k
        type = t->pkey_base_id;
92
81.4k
    }
93
4.55M
    if (pe) {
94
4.53M
#ifndef OPENSSL_NO_ENGINE
95
4.53M
        ENGINE *e;
96
        /* type will contain the final unaliased type */
97
4.53M
        e = ENGINE_get_pkey_asn1_meth_engine(type);
98
4.53M
        if (e) {
99
0
            *pe = e;
100
0
            return ENGINE_get_pkey_asn1_meth(e, type);
101
0
        }
102
4.53M
#endif
103
4.53M
        *pe = NULL;
104
4.53M
    }
105
4.55M
    return t;
106
4.55M
}
107
108
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_find_str(ENGINE **pe,
109
    const char *str, int len)
110
4.78M
{
111
4.78M
    int i;
112
4.78M
    const EVP_PKEY_ASN1_METHOD *ameth = NULL;
113
114
4.78M
    if (len == -1)
115
953k
        len = (int)strlen(str);
116
4.78M
    if (pe) {
117
4.78M
#ifndef OPENSSL_NO_ENGINE
118
4.78M
        ENGINE *e;
119
4.78M
        ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
120
4.78M
        if (ameth) {
121
            /*
122
             * Convert structural into functional reference
123
             */
124
0
            if (!ENGINE_init(e))
125
0
                ameth = NULL;
126
0
            ENGINE_free(e);
127
0
            *pe = e;
128
0
            return ameth;
129
0
        }
130
4.78M
#endif
131
4.78M
        *pe = NULL;
132
4.78M
    }
133
67.0M
    for (i = EVP_PKEY_asn1_get_count(); i-- > 0;) {
134
63.7M
        ameth = EVP_PKEY_asn1_get0(i);
135
63.7M
        if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
136
20.4M
            continue;
137
43.3M
        if ((int)strlen(ameth->pem_str) == len
138
2.50M
            && OPENSSL_strncasecmp(ameth->pem_str, str, len) == 0)
139
1.48M
            return ameth;
140
43.3M
    }
141
3.29M
    return NULL;
142
4.78M
}
143
144
int EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
145
0
{
146
0
    EVP_PKEY_ASN1_METHOD tmp = {
147
0
        0,
148
0
    };
149
150
    /*
151
     * One of the following must be true:
152
     *
153
     * pem_str == NULL AND ASN1_PKEY_ALIAS is set
154
     * pem_str != NULL AND ASN1_PKEY_ALIAS is clear
155
     *
156
     * Anything else is an error and may lead to a corrupt ASN1 method table
157
     */
158
0
    if (!((ameth->pem_str == NULL
159
0
              && (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0)
160
0
            || (ameth->pem_str != NULL
161
0
                && (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
162
0
        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
163
0
        return 0;
164
0
    }
165
166
0
    if (app_methods == NULL) {
167
0
        app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
168
0
        if (app_methods == NULL)
169
0
            return 0;
170
0
    }
171
172
0
    tmp.pkey_id = ameth->pkey_id;
173
0
    if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) {
174
0
        ERR_raise(ERR_LIB_EVP,
175
0
            EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
176
0
        return 0;
177
0
    }
178
179
0
    if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
180
0
        return 0;
181
0
    sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
182
0
    return 1;
183
0
}
184
185
int EVP_PKEY_asn1_add_alias(int to, int from)
186
0
{
187
0
    EVP_PKEY_ASN1_METHOD *ameth;
188
0
    ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
189
0
    if (ameth == NULL)
190
0
        return 0;
191
0
    ameth->pkey_base_id = to;
192
0
    if (!EVP_PKEY_asn1_add0(ameth)) {
193
0
        EVP_PKEY_asn1_free(ameth);
194
0
        return 0;
195
0
    }
196
0
    return 1;
197
0
}
198
199
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
200
    int *ppkey_flags, const char **pinfo,
201
    const char **ppem_str,
202
    const EVP_PKEY_ASN1_METHOD *ameth)
203
1.50k
{
204
1.50k
    if (!ameth)
205
0
        return 0;
206
1.50k
    if (ppkey_id)
207
1.50k
        *ppkey_id = ameth->pkey_id;
208
1.50k
    if (ppkey_base_id)
209
1.50k
        *ppkey_base_id = ameth->pkey_base_id;
210
1.50k
    if (ppkey_flags)
211
1.50k
        *ppkey_flags = ameth->pkey_flags;
212
1.50k
    if (pinfo)
213
0
        *pinfo = ameth->info;
214
1.50k
    if (ppem_str)
215
1.50k
        *ppem_str = ameth->pem_str;
216
1.50k
    return 1;
217
1.50k
}
218
219
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
220
0
{
221
0
    return pkey->ameth;
222
0
}
223
224
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
225
    const char *pem_str, const char *info)
226
0
{
227
0
    EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
228
229
0
    if (ameth == NULL)
230
0
        return NULL;
231
232
0
    ameth->pkey_id = id;
233
0
    ameth->pkey_base_id = id;
234
0
    ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
235
236
0
    if (info) {
237
0
        ameth->info = OPENSSL_strdup(info);
238
0
        if (ameth->info == NULL)
239
0
            goto err;
240
0
    }
241
242
0
    if (pem_str) {
243
0
        ameth->pem_str = OPENSSL_strdup(pem_str);
244
0
        if (ameth->pem_str == NULL)
245
0
            goto err;
246
0
    }
247
248
0
    return ameth;
249
250
0
err:
251
0
    EVP_PKEY_asn1_free(ameth);
252
0
    return NULL;
253
0
}
254
255
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
256
    const EVP_PKEY_ASN1_METHOD *src)
257
0
{
258
0
    int pkey_id = dst->pkey_id;
259
0
    int pkey_base_id = dst->pkey_base_id;
260
0
    unsigned long pkey_flags = dst->pkey_flags;
261
0
    char *pem_str = dst->pem_str;
262
0
    char *info = dst->info;
263
264
0
    *dst = *src;
265
266
    /* We only copy the function pointers so restore the other values */
267
0
    dst->pkey_id = pkey_id;
268
0
    dst->pkey_base_id = pkey_base_id;
269
0
    dst->pkey_flags = pkey_flags;
270
0
    dst->pem_str = pem_str;
271
0
    dst->info = info;
272
0
}
273
274
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
275
0
{
276
0
    if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
277
0
        OPENSSL_free(ameth->pem_str);
278
0
        OPENSSL_free(ameth->info);
279
0
        OPENSSL_free(ameth);
280
0
    }
281
0
}
282
283
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
284
    int (*pub_decode)(EVP_PKEY *pk,
285
        const X509_PUBKEY *pub),
286
    int (*pub_encode)(X509_PUBKEY *pub,
287
        const EVP_PKEY *pk),
288
    int (*pub_cmp)(const EVP_PKEY *a,
289
        const EVP_PKEY *b),
290
    int (*pub_print)(BIO *out,
291
        const EVP_PKEY *pkey,
292
        int indent, ASN1_PCTX *pctx),
293
    int (*pkey_size)(const EVP_PKEY *pk),
294
    int (*pkey_bits)(const EVP_PKEY *pk))
295
0
{
296
0
    ameth->pub_decode = pub_decode;
297
0
    ameth->pub_encode = pub_encode;
298
0
    ameth->pub_cmp = pub_cmp;
299
0
    ameth->pub_print = pub_print;
300
0
    ameth->pkey_size = pkey_size;
301
0
    ameth->pkey_bits = pkey_bits;
302
0
}
303
304
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
305
    int (*priv_decode)(EVP_PKEY *pk,
306
        const PKCS8_PRIV_KEY_INFO
307
            *p8inf),
308
    int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8,
309
        const EVP_PKEY *pk),
310
    int (*priv_print)(BIO *out,
311
        const EVP_PKEY *pkey,
312
        int indent,
313
        ASN1_PCTX *pctx))
314
0
{
315
0
    ameth->priv_decode = priv_decode;
316
0
    ameth->priv_encode = priv_encode;
317
0
    ameth->priv_print = priv_print;
318
0
}
319
320
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
321
    int (*param_decode)(EVP_PKEY *pkey,
322
        const unsigned char **pder,
323
        int derlen),
324
    int (*param_encode)(const EVP_PKEY *pkey,
325
        unsigned char **pder),
326
    int (*param_missing)(const EVP_PKEY *pk),
327
    int (*param_copy)(EVP_PKEY *to,
328
        const EVP_PKEY *from),
329
    int (*param_cmp)(const EVP_PKEY *a,
330
        const EVP_PKEY *b),
331
    int (*param_print)(BIO *out,
332
        const EVP_PKEY *pkey,
333
        int indent, ASN1_PCTX *pctx))
334
0
{
335
0
    ameth->param_decode = param_decode;
336
0
    ameth->param_encode = param_encode;
337
0
    ameth->param_missing = param_missing;
338
0
    ameth->param_copy = param_copy;
339
0
    ameth->param_cmp = param_cmp;
340
0
    ameth->param_print = param_print;
341
0
}
342
343
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
344
    void (*pkey_free)(EVP_PKEY *pkey))
345
0
{
346
0
    ameth->pkey_free = pkey_free;
347
0
}
348
349
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
350
    int (*pkey_ctrl)(EVP_PKEY *pkey, int op,
351
        long arg1, void *arg2))
352
0
{
353
0
    ameth->pkey_ctrl = pkey_ctrl;
354
0
}
355
356
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
357
    int (*pkey_security_bits)(const EVP_PKEY
358
            *pk))
359
0
{
360
0
    ameth->pkey_security_bits = pkey_security_bits;
361
0
}
362
363
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
364
    int (*item_verify)(EVP_MD_CTX *ctx,
365
        const ASN1_ITEM *it,
366
        const void *data,
367
        const X509_ALGOR *a,
368
        const ASN1_BIT_STRING *sig,
369
        EVP_PKEY *pkey),
370
    int (*item_sign)(EVP_MD_CTX *ctx,
371
        const ASN1_ITEM *it,
372
        const void *data,
373
        X509_ALGOR *alg1,
374
        X509_ALGOR *alg2,
375
        ASN1_BIT_STRING *sig))
376
0
{
377
0
    ameth->item_sign = item_sign;
378
0
    ameth->item_verify = item_verify;
379
0
}
380
381
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
382
    int (*siginf_set)(X509_SIG_INFO *siginf,
383
        const X509_ALGOR *alg,
384
        const ASN1_STRING *sig))
385
0
{
386
0
    ameth->siginf_set = siginf_set;
387
0
}
388
389
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
390
    int (*pkey_check)(const EVP_PKEY *pk))
391
0
{
392
0
    ameth->pkey_check = pkey_check;
393
0
}
394
395
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
396
    int (*pkey_pub_check)(const EVP_PKEY *pk))
397
0
{
398
0
    ameth->pkey_public_check = pkey_pub_check;
399
0
}
400
401
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
402
    int (*pkey_param_check)(const EVP_PKEY *pk))
403
0
{
404
0
    ameth->pkey_param_check = pkey_param_check;
405
0
}
406
407
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
408
    int (*set_priv_key)(EVP_PKEY *pk,
409
        const unsigned char
410
            *priv,
411
        size_t len))
412
0
{
413
0
    ameth->set_priv_key = set_priv_key;
414
0
}
415
416
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
417
    int (*set_pub_key)(EVP_PKEY *pk,
418
        const unsigned char *pub,
419
        size_t len))
420
0
{
421
0
    ameth->set_pub_key = set_pub_key;
422
0
}
423
424
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
425
    int (*get_priv_key)(const EVP_PKEY *pk,
426
        unsigned char *priv,
427
        size_t *len))
428
0
{
429
0
    ameth->get_priv_key = get_priv_key;
430
0
}
431
432
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
433
    int (*get_pub_key)(const EVP_PKEY *pk,
434
        unsigned char *pub,
435
        size_t *len))
436
0
{
437
0
    ameth->get_pub_key = get_pub_key;
438
0
}