Coverage Report

Created: 2022-08-24 06:31

/src/libressl/crypto/asn1/ameth_lib.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: ameth_lib.c,v 1.26 2022/06/27 12:36:05 tb Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 2006.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 *
12
 * 1. Redistributions of source code must retain the above copyright
13
 *    notice, this list of conditions and the following disclaimer.
14
 *
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in
17
 *    the documentation and/or other materials provided with the
18
 *    distribution.
19
 *
20
 * 3. All advertising materials mentioning features or use of this
21
 *    software must display the following acknowledgment:
22
 *    "This product includes software developed by the OpenSSL Project
23
 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24
 *
25
 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26
 *    endorse or promote products derived from this software without
27
 *    prior written permission. For written permission, please contact
28
 *    licensing@OpenSSL.org.
29
 *
30
 * 5. Products derived from this software may not be called "OpenSSL"
31
 *    nor may "OpenSSL" appear in their names without prior written
32
 *    permission of the OpenSSL Project.
33
 *
34
 * 6. Redistributions of any form whatsoever must retain the following
35
 *    acknowledgment:
36
 *    "This product includes software developed by the OpenSSL Project
37
 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38
 *
39
 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40
 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
43
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50
 * OF THE POSSIBILITY OF SUCH DAMAGE.
51
 * ====================================================================
52
 *
53
 * This product includes cryptographic software written by Eric Young
54
 * (eay@cryptsoft.com).  This product includes software written by Tim
55
 * Hudson (tjh@cryptsoft.com).
56
 *
57
 */
58
59
#include <stdio.h>
60
#include <string.h>
61
62
#include <openssl/opensslconf.h>
63
64
#include <openssl/asn1t.h>
65
#include <openssl/x509.h>
66
67
#ifndef OPENSSL_NO_ENGINE
68
#include <openssl/engine.h>
69
#endif
70
71
#include "asn1_locl.h"
72
#include "evp_locl.h"
73
74
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
75
extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
76
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
77
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
78
extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
79
extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[];
80
extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth;
81
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
82
extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
83
84
/* Keep this sorted in type order !! */
85
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
86
#ifndef OPENSSL_NO_RSA
87
  &rsa_asn1_meths[0],
88
  &rsa_asn1_meths[1],
89
#endif
90
#ifndef OPENSSL_NO_DH
91
  &dh_asn1_meth,
92
#endif
93
#ifndef OPENSSL_NO_DSA
94
  &dsa_asn1_meths[0],
95
  &dsa_asn1_meths[1],
96
  &dsa_asn1_meths[2],
97
  &dsa_asn1_meths[3],
98
  &dsa_asn1_meths[4],
99
#endif
100
#ifndef OPENSSL_NO_EC
101
  &eckey_asn1_meth,
102
#endif
103
#ifndef OPENSSL_NO_GOST
104
  &gostr01_asn1_meths[0],
105
  &gostimit_asn1_meth,
106
#endif
107
  &hmac_asn1_meth,
108
  &cmac_asn1_meth,
109
#ifndef OPENSSL_NO_RSA
110
  &rsa_pss_asn1_meth,
111
#endif
112
#ifndef OPENSSL_NO_GOST
113
  &gostr01_asn1_meths[1],
114
  &gostr01_asn1_meths[2],
115
#endif
116
};
117
118
typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
119
DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
120
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
121
122
static int ameth_cmp_BSEARCH_CMP_FN(const void *, const void *);
123
static int ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *, const EVP_PKEY_ASN1_METHOD * const *);
124
static const EVP_PKEY_ASN1_METHOD * *OBJ_bsearch_ameth(const EVP_PKEY_ASN1_METHOD * *key, const EVP_PKEY_ASN1_METHOD * const *base, int num);
125
126
static int
127
ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
128
    const EVP_PKEY_ASN1_METHOD * const *b)
129
17.7k
{
130
17.7k
  return ((*a)->pkey_id - (*b)->pkey_id);
131
17.7k
}
132
133
134
static int
135
ameth_cmp_BSEARCH_CMP_FN(const void *a_, const void *b_)
136
17.7k
{
137
17.7k
  const EVP_PKEY_ASN1_METHOD * const *a = a_;
138
17.7k
  const EVP_PKEY_ASN1_METHOD * const *b = b_;
139
17.7k
  return ameth_cmp(a, b);
140
17.7k
}
141
142
static const EVP_PKEY_ASN1_METHOD * *
143
OBJ_bsearch_ameth(const EVP_PKEY_ASN1_METHOD * *key, const EVP_PKEY_ASN1_METHOD * const *base, int num)
144
4.81k
{
145
4.81k
  return (const EVP_PKEY_ASN1_METHOD * *)OBJ_bsearch_(key, base, num, sizeof(const EVP_PKEY_ASN1_METHOD *),
146
4.81k
      ameth_cmp_BSEARCH_CMP_FN);
147
4.81k
}
148
149
int
150
EVP_PKEY_asn1_get_count(void)
151
0
{
152
0
  int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
153
0
  if (app_methods)
154
0
    num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
155
0
  return num;
156
0
}
157
158
const EVP_PKEY_ASN1_METHOD *
159
EVP_PKEY_asn1_get0(int idx)
160
0
{
161
0
  int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
162
0
  if (idx < 0)
163
0
    return NULL;
164
0
  if (idx < num)
165
0
    return standard_methods[idx];
166
0
  idx -= num;
167
0
  return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
168
0
}
169
170
static const EVP_PKEY_ASN1_METHOD *
171
pkey_asn1_find(int type)
172
4.81k
{
173
4.81k
  EVP_PKEY_ASN1_METHOD tmp;
174
4.81k
  const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
175
4.81k
  tmp.pkey_id = type;
176
4.81k
  if (app_methods) {
177
0
    int idx;
178
0
    idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
179
0
    if (idx >= 0)
180
0
      return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
181
0
  }
182
4.81k
  ret = OBJ_bsearch_ameth(&t, standard_methods,
183
4.81k
      sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *));
184
4.81k
  if (!ret || !*ret)
185
70
    return NULL;
186
4.74k
  return *ret;
187
4.81k
}
188
189
/* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
190
 * also search through engines and set *pe to a functional reference
191
 * to the engine implementing 'type' or NULL if no engine implements
192
 * it.
193
 */
194
195
const EVP_PKEY_ASN1_METHOD *
196
EVP_PKEY_asn1_find(ENGINE **pe, int type)
197
4.80k
{
198
4.80k
  const EVP_PKEY_ASN1_METHOD *t;
199
200
4.81k
  for (;;) {
201
4.81k
    t = pkey_asn1_find(type);
202
4.81k
    if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
203
4.80k
      break;
204
8
    type = t->pkey_base_id;
205
8
  }
206
4.80k
  if (pe) {
207
4.80k
#ifndef OPENSSL_NO_ENGINE
208
4.80k
    ENGINE *e;
209
    /* type will contain the final unaliased type */
210
4.80k
    e = ENGINE_get_pkey_asn1_meth_engine(type);
211
4.80k
    if (e) {
212
0
      *pe = e;
213
0
      return ENGINE_get_pkey_asn1_meth(e, type);
214
0
    }
215
4.80k
#endif
216
4.80k
    *pe = NULL;
217
4.80k
  }
218
4.80k
  return t;
219
4.80k
}
220
221
const EVP_PKEY_ASN1_METHOD *
222
EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len)
223
0
{
224
0
  int i;
225
0
  const EVP_PKEY_ASN1_METHOD *ameth;
226
0
  if (len == -1)
227
0
    len = strlen(str);
228
0
  if (pe) {
229
0
#ifndef OPENSSL_NO_ENGINE
230
0
    ENGINE *e;
231
0
    ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
232
0
    if (ameth) {
233
      /* Convert structural into
234
       * functional reference
235
       */
236
0
      if (!ENGINE_init(e))
237
0
        ameth = NULL;
238
0
      ENGINE_free(e);
239
0
      *pe = e;
240
0
      return ameth;
241
0
    }
242
0
#endif
243
0
    *pe = NULL;
244
0
  }
245
0
  for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
246
0
    ameth = EVP_PKEY_asn1_get0(i);
247
0
    if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
248
0
      continue;
249
0
    if (((int)strlen(ameth->pem_str) == len) &&
250
0
        !strncasecmp(ameth->pem_str, str, len))
251
0
      return ameth;
252
0
  }
253
0
  return NULL;
254
0
}
255
256
int
257
EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
258
0
{
259
0
  if (app_methods == NULL) {
260
0
    app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
261
0
    if (!app_methods)
262
0
      return 0;
263
0
  }
264
0
  if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
265
0
    return 0;
266
0
  sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
267
0
  return 1;
268
0
}
269
270
int
271
EVP_PKEY_asn1_add_alias(int to, int from)
272
0
{
273
0
  EVP_PKEY_ASN1_METHOD *ameth;
274
275
0
  ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
276
0
  if (!ameth)
277
0
    return 0;
278
0
  ameth->pkey_base_id = to;
279
0
  if (!EVP_PKEY_asn1_add0(ameth)) {
280
0
    EVP_PKEY_asn1_free(ameth);
281
0
    return 0;
282
0
  }
283
0
  return 1;
284
0
}
285
286
int
287
EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
288
    const char **pinfo, const char **ppem_str,
289
    const EVP_PKEY_ASN1_METHOD *ameth)
290
0
{
291
0
  if (!ameth)
292
0
    return 0;
293
0
  if (ppkey_id)
294
0
    *ppkey_id = ameth->pkey_id;
295
0
  if (ppkey_base_id)
296
0
    *ppkey_base_id = ameth->pkey_base_id;
297
0
  if (ppkey_flags)
298
0
    *ppkey_flags = ameth->pkey_flags;
299
0
  if (pinfo)
300
0
    *pinfo = ameth->info;
301
0
  if (ppem_str)
302
0
    *ppem_str = ameth->pem_str;
303
0
  return 1;
304
0
}
305
306
const EVP_PKEY_ASN1_METHOD*
307
EVP_PKEY_get0_asn1(const EVP_PKEY *pkey)
308
0
{
309
0
  return pkey->ameth;
310
0
}
311
312
EVP_PKEY_ASN1_METHOD*
313
EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info)
314
0
{
315
0
  EVP_PKEY_ASN1_METHOD *ameth;
316
317
0
  if ((ameth = calloc(1, sizeof(EVP_PKEY_ASN1_METHOD))) == NULL)
318
0
    return NULL;
319
320
0
  ameth->pkey_id = id;
321
0
  ameth->pkey_base_id = id;
322
0
  ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
323
324
0
  if (info != NULL) {
325
0
    if ((ameth->info = strdup(info)) == NULL)
326
0
      goto err;
327
0
  }
328
329
0
  if (pem_str != NULL) {
330
0
    if ((ameth->pem_str = strdup(pem_str)) == NULL)
331
0
      goto err;
332
0
  }
333
334
0
  return ameth;
335
336
0
 err:
337
0
  EVP_PKEY_asn1_free(ameth);
338
0
  return NULL;
339
0
}
340
341
void
342
EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src)
343
0
{
344
0
  EVP_PKEY_ASN1_METHOD preserve;
345
346
0
  preserve.pkey_id = dst->pkey_id;
347
0
  preserve.pkey_base_id = dst->pkey_base_id;
348
0
  preserve.pkey_flags = dst->pkey_flags;
349
0
  preserve.pem_str = dst->pem_str;
350
0
  preserve.info = dst->info;
351
352
0
  *dst = *src;
353
354
0
  dst->pkey_id = preserve.pkey_id;
355
0
  dst->pkey_base_id = preserve.pkey_base_id;
356
0
  dst->pkey_flags = preserve.pkey_flags;
357
0
  dst->pem_str = preserve.pem_str;
358
0
  dst->info = preserve.info;
359
0
}
360
361
void
362
EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
363
0
{
364
0
  if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
365
0
    free(ameth->pem_str);
366
0
    free(ameth->info);
367
0
    free(ameth);
368
0
  }
369
0
}
370
371
void
372
EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
373
    int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
374
    int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
375
    int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
376
    int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
377
  ASN1_PCTX *pctx),
378
    int (*pkey_size)(const EVP_PKEY *pk),
379
    int (*pkey_bits)(const EVP_PKEY *pk))
380
0
{
381
0
  ameth->pub_decode = pub_decode;
382
0
  ameth->pub_encode = pub_encode;
383
0
  ameth->pub_cmp = pub_cmp;
384
0
  ameth->pub_print = pub_print;
385
0
  ameth->pkey_size = pkey_size;
386
0
  ameth->pkey_bits = pkey_bits;
387
0
}
388
389
void
390
EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
391
    int (*priv_decode)(EVP_PKEY *pk, const PKCS8_PRIV_KEY_INFO *p8inf),
392
    int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
393
    int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
394
  ASN1_PCTX *pctx))
395
0
{
396
0
  ameth->priv_decode = priv_decode;
397
0
  ameth->priv_encode = priv_encode;
398
0
  ameth->priv_print = priv_print;
399
0
}
400
401
void
402
EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
403
    int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen),
404
    int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
405
    int (*param_missing)(const EVP_PKEY *pk),
406
    int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
407
    int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
408
    int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
409
  ASN1_PCTX *pctx))
410
0
{
411
0
  ameth->param_decode = param_decode;
412
0
  ameth->param_encode = param_encode;
413
0
  ameth->param_missing = param_missing;
414
0
  ameth->param_copy = param_copy;
415
0
  ameth->param_cmp = param_cmp;
416
0
  ameth->param_print = param_print;
417
0
}
418
419
void
420
EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
421
    void (*pkey_free)(EVP_PKEY *pkey))
422
0
{
423
0
  ameth->pkey_free = pkey_free;
424
0
}
425
426
void
427
EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
428
    int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2))
429
0
{
430
0
  ameth->pkey_ctrl = pkey_ctrl;
431
0
}
432
433
void
434
EVP_PKEY_asn1_set_security_bits(EVP_PKEY_ASN1_METHOD *ameth,
435
    int (*pkey_security_bits)(const EVP_PKEY *pkey))
436
0
{
437
0
  ameth->pkey_security_bits = pkey_security_bits;
438
0
}
439
440
void
441
EVP_PKEY_asn1_set_check(EVP_PKEY_ASN1_METHOD *ameth,
442
    int (*pkey_check)(const EVP_PKEY *pk))
443
0
{
444
0
  ameth->pkey_check = pkey_check;
445
0
}
446
447
void
448
EVP_PKEY_asn1_set_public_check(EVP_PKEY_ASN1_METHOD *ameth,
449
    int (*pkey_public_check)(const EVP_PKEY *pk))
450
0
{
451
0
  ameth->pkey_public_check = pkey_public_check;
452
0
}
453
454
void
455
EVP_PKEY_asn1_set_param_check(EVP_PKEY_ASN1_METHOD *ameth,
456
    int (*pkey_param_check)(const EVP_PKEY *pk))
457
0
{
458
0
  ameth->pkey_param_check = pkey_param_check;
459
0
}