Coverage Report

Created: 2025-07-23 06:08

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