GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/asn1/ameth_lib.c Lines: 35 170 20.6 %
Date: 2016-12-06 Branches: 16 74 21.6 %

Line Branch Exec Source
1
/* $OpenBSD: ameth_lib.c,v 1.15 2014/11/09 19:17:13 miod 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
73
extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
74
extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
75
extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
76
extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
77
extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[];
78
extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth;
79
extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
80
extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
81
82
/* Keep this sorted in type order !! */
83
static const EVP_PKEY_ASN1_METHOD *standard_methods[] = {
84
#ifndef OPENSSL_NO_RSA
85
	&rsa_asn1_meths[0],
86
	&rsa_asn1_meths[1],
87
#endif
88
#ifndef OPENSSL_NO_DH
89
	&dh_asn1_meth,
90
#endif
91
#ifndef OPENSSL_NO_DSA
92
	&dsa_asn1_meths[0],
93
	&dsa_asn1_meths[1],
94
	&dsa_asn1_meths[2],
95
	&dsa_asn1_meths[3],
96
	&dsa_asn1_meths[4],
97
#endif
98
#ifndef OPENSSL_NO_EC
99
	&eckey_asn1_meth,
100
#endif
101
#ifndef OPENSSL_NO_GOST
102
	&gostr01_asn1_meths[0],
103
	&gostimit_asn1_meth,
104
#endif
105
	&hmac_asn1_meth,
106
	&cmac_asn1_meth,
107
#ifndef OPENSSL_NO_GOST
108
	&gostr01_asn1_meths[1],
109
	&gostr01_asn1_meths[2],
110
#endif
111
};
112
113
typedef int sk_cmp_fn_type(const char * const *a, const char * const *b);
114
DECLARE_STACK_OF(EVP_PKEY_ASN1_METHOD)
115
static STACK_OF(EVP_PKEY_ASN1_METHOD) *app_methods = NULL;
116
117
DECLARE_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
118
    const EVP_PKEY_ASN1_METHOD *, ameth);
119
120
static int
121
ameth_cmp(const EVP_PKEY_ASN1_METHOD * const *a,
122
    const EVP_PKEY_ASN1_METHOD * const *b)
123
118
{
124
118
	return ((*a)->pkey_id - (*b)->pkey_id);
125
}
126
127
154
IMPLEMENT_OBJ_BSEARCH_CMP_FN(const EVP_PKEY_ASN1_METHOD *,
128
    const EVP_PKEY_ASN1_METHOD *, ameth);
129
130
int
131
EVP_PKEY_asn1_get_count(void)
132
2
{
133
2
	int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
134
2
	if (app_methods)
135
		num += sk_EVP_PKEY_ASN1_METHOD_num(app_methods);
136
2
	return num;
137
}
138
139
const EVP_PKEY_ASN1_METHOD *
140
EVP_PKEY_asn1_get0(int idx)
141
2
{
142
2
	int num = sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *);
143
2
	if (idx < 0)
144
		return NULL;
145
2
	if (idx < num)
146
2
		return standard_methods[idx];
147
	idx -= num;
148
	return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
149
}
150
151
static const EVP_PKEY_ASN1_METHOD *
152
pkey_asn1_find(int type)
153
36
{
154
	EVP_PKEY_ASN1_METHOD tmp;
155
36
	const EVP_PKEY_ASN1_METHOD *t = &tmp, **ret;
156
36
	tmp.pkey_id = type;
157
36
	if (app_methods) {
158
		int idx;
159
		idx = sk_EVP_PKEY_ASN1_METHOD_find(app_methods, &tmp);
160
		if (idx >= 0)
161
			return sk_EVP_PKEY_ASN1_METHOD_value(app_methods, idx);
162
	}
163
36
	ret = OBJ_bsearch_ameth(&t, standard_methods,
164
	    sizeof(standard_methods) / sizeof(EVP_PKEY_ASN1_METHOD *));
165

36
	if (!ret || !*ret)
166
		return NULL;
167
36
	return *ret;
168
}
169
170
/* Find an implementation of an ASN1 algorithm. If 'pe' is not NULL
171
 * also search through engines and set *pe to a functional reference
172
 * to the engine implementing 'type' or NULL if no engine implements
173
 * it.
174
 */
175
176
const EVP_PKEY_ASN1_METHOD *
177
EVP_PKEY_asn1_find(ENGINE **pe, int type)
178
36
{
179
	const EVP_PKEY_ASN1_METHOD *t;
180
181
	for (;;) {
182
36
		t = pkey_asn1_find(type);
183

36
		if (!t || !(t->pkey_flags & ASN1_PKEY_ALIAS))
184
			break;
185
		type = t->pkey_base_id;
186
	}
187
36
	if (pe) {
188
#ifndef OPENSSL_NO_ENGINE
189
		ENGINE *e;
190
		/* type will contain the final unaliased type */
191
36
		e = ENGINE_get_pkey_asn1_meth_engine(type);
192
36
		if (e) {
193
			*pe = e;
194
			return ENGINE_get_pkey_asn1_meth(e, type);
195
		}
196
#endif
197
36
		*pe = NULL;
198
	}
199
36
	return t;
200
}
201
202
const EVP_PKEY_ASN1_METHOD *
203
EVP_PKEY_asn1_find_str(ENGINE **pe, const char *str, int len)
204
2
{
205
	int i;
206
	const EVP_PKEY_ASN1_METHOD *ameth;
207
2
	if (len == -1)
208
		len = strlen(str);
209
2
	if (pe) {
210
#ifndef OPENSSL_NO_ENGINE
211
		ENGINE *e;
212
		ameth = ENGINE_pkey_asn1_find_str(&e, str, len);
213
		if (ameth) {
214
			/* Convert structural into
215
			 * functional reference
216
			 */
217
			if (!ENGINE_init(e))
218
				ameth = NULL;
219
			ENGINE_free(e);
220
			*pe = e;
221
			return ameth;
222
		}
223
#endif
224
		*pe = NULL;
225
	}
226
2
	for (i = 0; i < EVP_PKEY_asn1_get_count(); i++) {
227
2
		ameth = EVP_PKEY_asn1_get0(i);
228
2
		if (ameth->pkey_flags & ASN1_PKEY_ALIAS)
229
			continue;
230

2
		if (((int)strlen(ameth->pem_str) == len) &&
231
		    !strncasecmp(ameth->pem_str, str, len))
232
2
			return ameth;
233
	}
234
	return NULL;
235
}
236
237
int
238
EVP_PKEY_asn1_add0(const EVP_PKEY_ASN1_METHOD *ameth)
239
{
240
	if (app_methods == NULL) {
241
		app_methods = sk_EVP_PKEY_ASN1_METHOD_new(ameth_cmp);
242
		if (!app_methods)
243
			return 0;
244
	}
245
	if (!sk_EVP_PKEY_ASN1_METHOD_push(app_methods, ameth))
246
		return 0;
247
	sk_EVP_PKEY_ASN1_METHOD_sort(app_methods);
248
	return 1;
249
}
250
251
int
252
EVP_PKEY_asn1_add_alias(int to, int from)
253
{
254
	EVP_PKEY_ASN1_METHOD *ameth;
255
256
	ameth = EVP_PKEY_asn1_new(from, ASN1_PKEY_ALIAS, NULL, NULL);
257
	if (!ameth)
258
		return 0;
259
	ameth->pkey_base_id = to;
260
	if (!EVP_PKEY_asn1_add0(ameth)) {
261
		EVP_PKEY_asn1_free(ameth);
262
		return 0;
263
	}
264
	return 1;
265
}
266
267
int
268
EVP_PKEY_asn1_get0_info(int *ppkey_id, int *ppkey_base_id, int *ppkey_flags,
269
    const char **pinfo, const char **ppem_str,
270
    const EVP_PKEY_ASN1_METHOD *ameth)
271
{
272
	if (!ameth)
273
		return 0;
274
	if (ppkey_id)
275
		*ppkey_id = ameth->pkey_id;
276
	if (ppkey_base_id)
277
		*ppkey_base_id = ameth->pkey_base_id;
278
	if (ppkey_flags)
279
		*ppkey_flags = ameth->pkey_flags;
280
	if (pinfo)
281
		*pinfo = ameth->info;
282
	if (ppem_str)
283
		*ppem_str = ameth->pem_str;
284
	return 1;
285
}
286
287
const EVP_PKEY_ASN1_METHOD*
288
EVP_PKEY_get0_asn1(EVP_PKEY *pkey)
289
{
290
	return pkey->ameth;
291
}
292
293
EVP_PKEY_ASN1_METHOD*
294
EVP_PKEY_asn1_new(int id, int flags, const char *pem_str, const char *info)
295
{
296
	EVP_PKEY_ASN1_METHOD *ameth;
297
298
	ameth = calloc(1, sizeof(EVP_PKEY_ASN1_METHOD));
299
	if (!ameth)
300
		return NULL;
301
302
	ameth->pkey_id = id;
303
	ameth->pkey_base_id = id;
304
	ameth->pkey_flags = flags | ASN1_PKEY_DYNAMIC;
305
306
	if (info) {
307
		ameth->info = strdup(info);
308
		if (!ameth->info)
309
			goto err;
310
	} else
311
		ameth->info = NULL;
312
313
	if (pem_str) {
314
		ameth->pem_str = strdup(pem_str);
315
		if (!ameth->pem_str)
316
			goto err;
317
	} else
318
		ameth->pem_str = NULL;
319
320
	ameth->pub_decode = 0;
321
	ameth->pub_encode = 0;
322
	ameth->pub_cmp = 0;
323
	ameth->pub_print = 0;
324
325
	ameth->priv_decode = 0;
326
	ameth->priv_encode = 0;
327
	ameth->priv_print = 0;
328
329
	ameth->old_priv_encode = 0;
330
	ameth->old_priv_decode = 0;
331
332
	ameth->item_verify = 0;
333
	ameth->item_sign = 0;
334
335
	ameth->pkey_size = 0;
336
	ameth->pkey_bits = 0;
337
338
	ameth->param_decode = 0;
339
	ameth->param_encode = 0;
340
	ameth->param_missing = 0;
341
	ameth->param_copy = 0;
342
	ameth->param_cmp = 0;
343
	ameth->param_print = 0;
344
345
	ameth->pkey_free = 0;
346
	ameth->pkey_ctrl = 0;
347
348
	return ameth;
349
350
err:
351
	EVP_PKEY_asn1_free(ameth);
352
	return NULL;
353
}
354
355
void
356
EVP_PKEY_asn1_copy(EVP_PKEY_ASN1_METHOD *dst, const EVP_PKEY_ASN1_METHOD *src)
357
{
358
	dst->pub_decode = src->pub_decode;
359
	dst->pub_encode = src->pub_encode;
360
	dst->pub_cmp = src->pub_cmp;
361
	dst->pub_print = src->pub_print;
362
363
	dst->priv_decode = src->priv_decode;
364
	dst->priv_encode = src->priv_encode;
365
	dst->priv_print = src->priv_print;
366
367
	dst->old_priv_encode = src->old_priv_encode;
368
	dst->old_priv_decode = src->old_priv_decode;
369
370
	dst->pkey_size = src->pkey_size;
371
	dst->pkey_bits = src->pkey_bits;
372
373
	dst->param_decode = src->param_decode;
374
	dst->param_encode = src->param_encode;
375
	dst->param_missing = src->param_missing;
376
	dst->param_copy = src->param_copy;
377
	dst->param_cmp = src->param_cmp;
378
	dst->param_print = src->param_print;
379
380
	dst->pkey_free = src->pkey_free;
381
	dst->pkey_ctrl = src->pkey_ctrl;
382
383
	dst->item_sign = src->item_sign;
384
	dst->item_verify = src->item_verify;
385
}
386
387
void
388
EVP_PKEY_asn1_free(EVP_PKEY_ASN1_METHOD *ameth)
389
{
390
	if (ameth && (ameth->pkey_flags & ASN1_PKEY_DYNAMIC)) {
391
		free(ameth->pem_str);
392
		free(ameth->info);
393
		free(ameth);
394
	}
395
}
396
397
void
398
EVP_PKEY_asn1_set_public(EVP_PKEY_ASN1_METHOD *ameth,
399
    int (*pub_decode)(EVP_PKEY *pk, X509_PUBKEY *pub),
400
    int (*pub_encode)(X509_PUBKEY *pub, const EVP_PKEY *pk),
401
    int (*pub_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
402
    int (*pub_print)(BIO *out, const EVP_PKEY *pkey, int indent,
403
	ASN1_PCTX *pctx),
404
    int (*pkey_size)(const EVP_PKEY *pk),
405
    int (*pkey_bits)(const EVP_PKEY *pk))
406
{
407
	ameth->pub_decode = pub_decode;
408
	ameth->pub_encode = pub_encode;
409
	ameth->pub_cmp = pub_cmp;
410
	ameth->pub_print = pub_print;
411
	ameth->pkey_size = pkey_size;
412
	ameth->pkey_bits = pkey_bits;
413
}
414
415
void
416
EVP_PKEY_asn1_set_private(EVP_PKEY_ASN1_METHOD *ameth,
417
    int (*priv_decode)(EVP_PKEY *pk, PKCS8_PRIV_KEY_INFO *p8inf),
418
    int (*priv_encode)(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pk),
419
    int (*priv_print)(BIO *out, const EVP_PKEY *pkey, int indent,
420
	ASN1_PCTX *pctx))
421
{
422
	ameth->priv_decode = priv_decode;
423
	ameth->priv_encode = priv_encode;
424
	ameth->priv_print = priv_print;
425
}
426
427
void
428
EVP_PKEY_asn1_set_param(EVP_PKEY_ASN1_METHOD *ameth,
429
    int (*param_decode)(EVP_PKEY *pkey, const unsigned char **pder, int derlen),
430
    int (*param_encode)(const EVP_PKEY *pkey, unsigned char **pder),
431
    int (*param_missing)(const EVP_PKEY *pk),
432
    int (*param_copy)(EVP_PKEY *to, const EVP_PKEY *from),
433
    int (*param_cmp)(const EVP_PKEY *a, const EVP_PKEY *b),
434
    int (*param_print)(BIO *out, const EVP_PKEY *pkey, int indent,
435
	ASN1_PCTX *pctx))
436
{
437
	ameth->param_decode = param_decode;
438
	ameth->param_encode = param_encode;
439
	ameth->param_missing = param_missing;
440
	ameth->param_copy = param_copy;
441
	ameth->param_cmp = param_cmp;
442
	ameth->param_print = param_print;
443
}
444
445
void
446
EVP_PKEY_asn1_set_free(EVP_PKEY_ASN1_METHOD *ameth,
447
    void (*pkey_free)(EVP_PKEY *pkey))
448
{
449
	ameth->pkey_free = pkey_free;
450
}
451
452
void
453
EVP_PKEY_asn1_set_ctrl(EVP_PKEY_ASN1_METHOD *ameth,
454
    int (*pkey_ctrl)(EVP_PKEY *pkey, int op, long arg1, void *arg2))
455
{
456
	ameth->pkey_ctrl = pkey_ctrl;
457
}