Coverage Report

Created: 2025-12-10 06:24

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