Coverage Report

Created: 2025-12-08 06:22

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
16
{
41
16
    int num = OSSL_NELEM(standard_methods);
42
16
    if (app_methods)
43
0
        num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
44
16
    return num;
45
16
}
46
47
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_get0(int idx)
48
240
{
49
240
    int num = OSSL_NELEM(standard_methods);
50
240
    if (idx < 0)
51
0
        return NULL;
52
240
    if (idx < num)
53
240
        return standard_methods[idx];
54
0
    idx -= num;
55
0
    return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
56
240
}
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 = { 0, };
122
123
    /*
124
     * One of the following must be true:
125
     *
126
     * pem_str == NULL AND ASN1_PKEY_ALIAS is set
127
     * pem_str != NULL AND ASN1_PKEY_ALIAS is clear
128
     *
129
     * Anything else is an error and may lead to a corrupt ASN1 method table
130
     */
131
0
    if (!((ameth->pem_str == NULL
132
0
           && (ameth->pkey_flags & ASN1_PKEY_ALIAS) != 0)
133
0
          || (ameth->pem_str != NULL
134
0
              && (ameth->pkey_flags & ASN1_PKEY_ALIAS) == 0))) {
135
0
        ERR_raise(ERR_LIB_EVP, ERR_R_PASSED_INVALID_ARGUMENT);
136
0
        return 0;
137
0
    }
138
139
0
    if (app_methods == NULL) {
140
0
        app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
141
0
        if (app_methods == NULL)
142
0
            return 0;
143
0
    }
144
145
0
    tmp.pkey_id = ameth->pkey_id;
146
0
    if (sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp) >= 0) {
147
0
        ERR_raise(ERR_LIB_EVP,
148
0
                  EVP_R_PKEY_APPLICATION_ASN1_METHOD_ALREADY_REGISTERED);
149
0
        return 0;
150
0
    }
151
152
0
    if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
153
0
        return 0;
154
0
    sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
155
0
    return 1;
156
0
}
157
158
int EVP_PKEY_asn1_add_alias(int to, int from)
159
0
{
160
0
    EVP_PKEY_ASN1_METHOD *ameth;
161
0
    ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
162
0
    if (ameth == NULL)
163
0
        return 0;
164
0
    ameth->pkey_base_id = to;
165
0
    if (!EVP_PKEY_asn1_add0(ameth)) {
166
0
        EVP_PKEY_asn1_free(ameth);
167
0
        return 0;
168
0
    }
169
0
    return 1;
170
0
}
171
172
int EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id,
173
                            int *ppkey_flags, const char **pinfo,
174
                            const char **ppem_str,
175
                            const EVP_PKEY_ASN1_METHOD *ameth)
176
240
{
177
240
    if (!ameth)
178
0
        return 0;
179
240
    if (ppkey_id)
180
240
        *ppkey_id = ameth->pkey_id;
181
240
    if (ppkey_base_id)
182
240
        *ppkey_base_id = ameth->pkey_base_id;
183
240
    if (ppkey_flags)
184
240
        *ppkey_flags = ameth->pkey_flags;
185
240
    if (pinfo)
186
0
        *pinfo = ameth->info;
187
240
    if (ppem_str)
188
240
        *ppem_str = ameth->pem_str;
189
240
    return 1;
190
240
}
191
192
const EVP_PKEY_ASN1_METHOD *EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
193
0
{
194
0
    return pkey->ameth;
195
0
}
196
197
EVP_PKEY_ASN1_METHOD *EVP_PKEY_asn1_new(int id, int flags,
198
                                        const char *pem_str, const char *info)
199
0
{
200
0
    EVP_PKEY_ASN1_METHOD *ameth = OPENSSL_zalloc(sizeof(*ameth));
201
202
0
    if (ameth == NULL)
203
0
        return NULL;
204
205
0
    ameth->pkey_id = id;
206
0
    ameth->pkey_base_id = id;
207
0
    ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
208
209
0
    if (info) {
210
0
        ameth->info = OPENSSL_strdup(info);
211
0
        if (ameth->info == NULL)
212
0
            goto err;
213
0
    }
214
215
0
    if (pem_str) {
216
0
        ameth->pem_str = OPENSSL_strdup(pem_str);
217
0
        if (ameth->pem_str == NULL)
218
0
            goto err;
219
0
    }
220
221
0
    return ameth;
222
223
0
 err:
224
0
    EVP_PKEY_asn1_free(ameth);
225
0
    return NULL;
226
0
}
227
228
void EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst,
229
                        const EVP_PKEY_ASN1_METHOD *src)
230
0
{
231
0
    int pkey_id = dst->pkey_id;
232
0
    int pkey_base_id = dst->pkey_base_id;
233
0
    unsigned long pkey_flags = dst->pkey_flags;
234
0
    char *pem_str = dst->pem_str;
235
0
    char *info = dst->info;
236
237
0
    *dst = *src;
238
239
    /* We only copy the function pointers so restore the other values */
240
0
    dst->pkey_id = pkey_id;
241
0
    dst->pkey_base_id = pkey_base_id;
242
0
    dst->pkey_flags = pkey_flags;
243
0
    dst->pem_str = pem_str;
244
0
    dst->info = info;
245
0
}
246
247
void EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
248
0
{
249
0
    if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
250
0
        OPENSSL_free(ameth->pem_str);
251
0
        OPENSSL_free(ameth->info);
252
0
        OPENSSL_free(ameth);
253
0
    }
254
0
}
255
256
void EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
257
                              int (*pub_decode) (EVP_PKEY *pk,
258
                                                 const X509_PUBKEY *pub),
259
                              int (*pub_encode) (X509_PUBKEY *pub,
260
                                                 const EVP_PKEY *pk),
261
                              int (*pub_cmp) (const EVP_PKEY *a,
262
                                              const EVP_PKEY *b),
263
                              int (*pub_print) (BIO *out,
264
                                                const EVP_PKEY *pkey,
265
                                                int indent, ASN1_PCTX *pctx),
266
                              int (*pkey_size) (const EVP_PKEY *pk),
267
                              int (*pkey_bits) (const EVP_PKEY *pk))
268
0
{
269
0
    ameth->pub_decode = pub_decode;
270
0
    ameth->pub_encode = pub_encode;
271
0
    ameth->pub_cmp = pub_cmp;
272
0
    ameth->pub_print = pub_print;
273
0
    ameth->pkey_size = pkey_size;
274
0
    ameth->pkey_bits = pkey_bits;
275
0
}
276
277
void EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
278
                               int (*priv_decode) (EVP_PKEY *pk,
279
                                                   const PKCS8_PRIV_KEY_INFO
280
                                                   *p8inf),
281
                               int (*priv_encode) (PKCS8_PRIV_KEY_INFO *p8,
282
                                                   const EVP_PKEY *pk),
283
                               int (*priv_print) (BIO *out,
284
                                                  const EVP_PKEY *pkey,
285
                                                  int indent,
286
                                                  ASN1_PCTX *pctx))
287
0
{
288
0
    ameth->priv_decode = priv_decode;
289
0
    ameth->priv_encode = priv_encode;
290
0
    ameth->priv_print = priv_print;
291
0
}
292
293
void EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
294
                             int (*param_decode) (EVP_PKEY *pkey,
295
                                                  const unsigned char **pder,
296
                                                  int derlen),
297
                             int (*param_encode) (const EVP_PKEY *pkey,
298
                                                  unsigned char **pder),
299
                             int (*param_missing) (const EVP_PKEY *pk),
300
                             int (*param_copy) (EVP_PKEY *to,
301
                                                const EVP_PKEY *from),
302
                             int (*param_cmp) (const EVP_PKEY *a,
303
                                               const EVP_PKEY *b),
304
                             int (*param_print) (BIO *out,
305
                                                 const EVP_PKEY *pkey,
306
                                                 int indent, ASN1_PCTX *pctx))
307
0
{
308
0
    ameth->param_decode = param_decode;
309
0
    ameth->param_encode = param_encode;
310
0
    ameth->param_missing = param_missing;
311
0
    ameth->param_copy = param_copy;
312
0
    ameth->param_cmp = param_cmp;
313
0
    ameth->param_print = param_print;
314
0
}
315
316
void EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
317
                            void (*pkey_free) (EVP_PKEY *pkey))
318
0
{
319
0
    ameth->pkey_free = pkey_free;
320
0
}
321
322
void EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
323
                            int (*pkey_ctrl) (EVP_PKEY *pkey, int op,
324
                                              long arg1, void *arg2))
325
0
{
326
0
    ameth->pkey_ctrl = pkey_ctrl;
327
0
}
328
329
void EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
330
                                     int (*pkey_security_bits) (const EVP_PKEY
331
                                                                *pk))
332
0
{
333
0
    ameth->pkey_security_bits = pkey_security_bits;
334
0
}
335
336
void EVP_PKEY_asn1_set_item(EVP_PKEY_ASN1_METHOD *ameth,
337
                            int (*item_verify) (EVP_MD_CTX *ctx,
338
                                                const ASN1_ITEM *it,
339
                                                const void *data,
340
                                                const X509_ALGOR *a,
341
                                                const ASN1_BIT_STRING *sig,
342
                                                EVP_PKEY *pkey),
343
                            int (*item_sign) (EVP_MD_CTX *ctx,
344
                                              const ASN1_ITEM *it,
345
                                              const void *data,
346
                                              X509_ALGOR *alg1,
347
                                              X509_ALGOR *alg2,
348
                                              ASN1_BIT_STRING *sig))
349
0
{
350
0
    ameth->item_sign = item_sign;
351
0
    ameth->item_verify = item_verify;
352
0
}
353
354
void EVP_PKEY_asn1_set_siginf(EVP_PKEY_ASN1_METHOD *ameth,
355
                              int (*siginf_set) (X509_SIG_INFO *siginf,
356
                                                 const X509_ALGOR *alg,
357
                                                 const ASN1_STRING *sig))
358
0
{
359
0
    ameth->siginf_set = siginf_set;
360
0
}
361
362
void EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
363
                             int (*pkey_check) (const EVP_PKEY *pk))
364
0
{
365
0
    ameth->pkey_check = pkey_check;
366
0
}
367
368
void EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
369
                                    int (*pkey_pub_check) (const EVP_PKEY *pk))
370
0
{
371
0
    ameth->pkey_public_check = pkey_pub_check;
372
0
}
373
374
void EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
375
                                   int (*pkey_param_check) (const EVP_PKEY *pk))
376
0
{
377
0
    ameth->pkey_param_check = pkey_param_check;
378
0
}
379
380
void EVP_PKEY_asn1_set_set_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
381
                                    int (*set_priv_key) (EVP_PKEY *pk,
382
                                                         const unsigned char
383
                                                            *priv,
384
                                                         size_t len))
385
0
{
386
0
    ameth->set_priv_key = set_priv_key;
387
0
}
388
389
void EVP_PKEY_asn1_set_set_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
390
                                   int (*set_pub_key) (EVP_PKEY *pk,
391
                                                       const unsigned char *pub,
392
                                                       size_t len))
393
0
{
394
0
    ameth->set_pub_key = set_pub_key;
395
0
}
396
397
void EVP_PKEY_asn1_set_get_priv_key(EVP_PKEY_ASN1_METHOD *ameth,
398
                                    int (*get_priv_key) (const EVP_PKEY *pk,
399
                                                         unsigned char *priv,
400
                                                         size_t *len))
401
0
{
402
0
    ameth->get_priv_key = get_priv_key;
403
0
}
404
405
void EVP_PKEY_asn1_set_get_pub_key(EVP_PKEY_ASN1_METHOD *ameth,
406
                                   int (*get_pub_key) (const EVP_PKEY *pk,
407
                                                       unsigned char *pub,
408
                                                       size_t *len))
409
0
{
410
0
    ameth->get_pub_key = get_pub_key;
411
0
}