GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libcrypto/crypto/../../libssl/src/crypto/asn1/x_pubkey.c Lines: 28 169 16.6 %
Date: 2016-12-06 Branches: 14 82 17.1 %

Line Branch Exec Source
1
/* $OpenBSD: x_pubkey.c,v 1.25 2015/02/11 04:00:39 jsing Exp $ */
2
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3
 * All rights reserved.
4
 *
5
 * This package is an SSL implementation written
6
 * by Eric Young (eay@cryptsoft.com).
7
 * The implementation was written so as to conform with Netscapes SSL.
8
 *
9
 * This library is free for commercial and non-commercial use as long as
10
 * the following conditions are aheared to.  The following conditions
11
 * apply to all code found in this distribution, be it the RC4, RSA,
12
 * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13
 * included with this distribution is covered by the same copyright terms
14
 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15
 *
16
 * Copyright remains Eric Young's, and as such any Copyright notices in
17
 * the code are not to be removed.
18
 * If this package is used in a product, Eric Young should be given attribution
19
 * as the author of the parts of the library used.
20
 * This can be in the form of a textual message at program startup or
21
 * in documentation (online or textual) provided with the package.
22
 *
23
 * Redistribution and use in source and binary forms, with or without
24
 * modification, are permitted provided that the following conditions
25
 * are met:
26
 * 1. Redistributions of source code must retain the copyright
27
 *    notice, this list of conditions and the following disclaimer.
28
 * 2. Redistributions in binary form must reproduce the above copyright
29
 *    notice, this list of conditions and the following disclaimer in the
30
 *    documentation and/or other materials provided with the distribution.
31
 * 3. All advertising materials mentioning features or use of this software
32
 *    must display the following acknowledgement:
33
 *    "This product includes cryptographic software written by
34
 *     Eric Young (eay@cryptsoft.com)"
35
 *    The word 'cryptographic' can be left out if the rouines from the library
36
 *    being used are not cryptographic related :-).
37
 * 4. If you include any Windows specific code (or a derivative thereof) from
38
 *    the apps directory (application code) you must include an acknowledgement:
39
 *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40
 *
41
 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
 * SUCH DAMAGE.
52
 *
53
 * The licence and distribution terms for any publically available version or
54
 * derivative of this code cannot be changed.  i.e. this code cannot simply be
55
 * copied and put under another distribution licence
56
 * [including the GNU Public Licence.]
57
 */
58
59
#include <stdio.h>
60
61
#include <openssl/opensslconf.h>
62
63
#include <openssl/asn1t.h>
64
#include <openssl/err.h>
65
#include <openssl/x509.h>
66
67
#ifndef OPENSSL_NO_DSA
68
#include <openssl/dsa.h>
69
#endif
70
#ifndef OPENSSL_NO_RSA
71
#include <openssl/rsa.h>
72
#endif
73
74
#include "asn1_locl.h"
75
76
/* Minor tweak to operation: free up EVP_PKEY */
77
static int
78
pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
79
644
{
80
644
	if (operation == ASN1_OP_FREE_POST) {
81
		X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
82
		EVP_PKEY_free(pubkey->pkey);
83
	}
84
644
	return 1;
85
}
86
87
static const ASN1_AUX X509_PUBKEY_aux = {
88
	.asn1_cb = pubkey_cb,
89
};
90
static const ASN1_TEMPLATE X509_PUBKEY_seq_tt[] = {
91
	{
92
		.offset = offsetof(X509_PUBKEY, algor),
93
		.field_name = "algor",
94
		.item = &X509_ALGOR_it,
95
	},
96
	{
97
		.offset = offsetof(X509_PUBKEY, public_key),
98
		.field_name = "public_key",
99
		.item = &ASN1_BIT_STRING_it,
100
	},
101
};
102
103
const ASN1_ITEM X509_PUBKEY_it = {
104
	.itype = ASN1_ITYPE_SEQUENCE,
105
	.utype = V_ASN1_SEQUENCE,
106
	.templates = X509_PUBKEY_seq_tt,
107
	.tcount = sizeof(X509_PUBKEY_seq_tt) / sizeof(ASN1_TEMPLATE),
108
	.funcs = &X509_PUBKEY_aux,
109
	.size = sizeof(X509_PUBKEY),
110
	.sname = "X509_PUBKEY",
111
};
112
113
114
X509_PUBKEY *
115
d2i_X509_PUBKEY(X509_PUBKEY **a, const unsigned char **in, long len)
116
{
117
	return (X509_PUBKEY *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
118
	    &X509_PUBKEY_it);
119
}
120
121
int
122
i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **out)
123
{
124
	return ASN1_item_i2d((ASN1_VALUE *)a, out, &X509_PUBKEY_it);
125
}
126
127
X509_PUBKEY *
128
X509_PUBKEY_new(void)
129
{
130
	return (X509_PUBKEY *)ASN1_item_new(&X509_PUBKEY_it);
131
}
132
133
void
134
X509_PUBKEY_free(X509_PUBKEY *a)
135
{
136
	ASN1_item_free((ASN1_VALUE *)a, &X509_PUBKEY_it);
137
}
138
139
int
140
X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
141
{
142
	X509_PUBKEY *pk = NULL;
143
144
	if (x == NULL)
145
		return (0);
146
	if ((pk = X509_PUBKEY_new()) == NULL)
147
		goto error;
148
149
	if (pkey->ameth) {
150
		if (pkey->ameth->pub_encode) {
151
			if (!pkey->ameth->pub_encode(pk, pkey)) {
152
				X509err(X509_F_X509_PUBKEY_SET,
153
				    X509_R_PUBLIC_KEY_ENCODE_ERROR);
154
				goto error;
155
			}
156
		} else {
157
			X509err(X509_F_X509_PUBKEY_SET,
158
			    X509_R_METHOD_NOT_SUPPORTED);
159
			goto error;
160
		}
161
	} else {
162
		X509err(X509_F_X509_PUBKEY_SET, X509_R_UNSUPPORTED_ALGORITHM);
163
		goto error;
164
	}
165
166
	if (*x != NULL)
167
		X509_PUBKEY_free(*x);
168
169
	*x = pk;
170
171
	return 1;
172
173
error:
174
	if (pk != NULL)
175
		X509_PUBKEY_free(pk);
176
	return 0;
177
}
178
179
EVP_PKEY *
180
X509_PUBKEY_get(X509_PUBKEY *key)
181
25
{
182
25
	EVP_PKEY *ret = NULL;
183
184
25
	if (key == NULL)
185
		goto error;
186
187
25
	if (key->pkey != NULL) {
188
17
		CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
189
17
		return key->pkey;
190
	}
191
192
8
	if (key->public_key == NULL)
193
		goto error;
194
195
8
	if ((ret = EVP_PKEY_new()) == NULL) {
196
		X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
197
		goto error;
198
	}
199
200
8
	if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) {
201
		X509err(X509_F_X509_PUBKEY_GET, X509_R_UNSUPPORTED_ALGORITHM);
202
		goto error;
203
	}
204
205
8
	if (ret->ameth->pub_decode) {
206
8
		if (!ret->ameth->pub_decode(ret, key)) {
207
			X509err(X509_F_X509_PUBKEY_GET,
208
			    X509_R_PUBLIC_KEY_DECODE_ERROR);
209
			goto error;
210
		}
211
	} else {
212
		X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED);
213
		goto error;
214
	}
215
216
	/* Check to see if another thread set key->pkey first */
217
8
	CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY);
218
8
	if (key->pkey) {
219
		CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
220
		EVP_PKEY_free(ret);
221
		ret = key->pkey;
222
	} else {
223
8
		key->pkey = ret;
224
8
		CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY);
225
	}
226
8
	CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
227
228
8
	return ret;
229
230
error:
231
	EVP_PKEY_free(ret);
232
	return (NULL);
233
}
234
235
/* Now two pseudo ASN1 routines that take an EVP_PKEY structure
236
 * and encode or decode as X509_PUBKEY
237
 */
238
239
EVP_PKEY *
240
d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp, long length)
241
{
242
	X509_PUBKEY *xpk;
243
	EVP_PKEY *pktmp;
244
	xpk = d2i_X509_PUBKEY(NULL, pp, length);
245
	if (!xpk)
246
		return NULL;
247
	pktmp = X509_PUBKEY_get(xpk);
248
	X509_PUBKEY_free(xpk);
249
	if (!pktmp)
250
		return NULL;
251
	if (a) {
252
		EVP_PKEY_free(*a);
253
		*a = pktmp;
254
	}
255
	return pktmp;
256
}
257
258
int
259
i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
260
{
261
	X509_PUBKEY *xpk = NULL;
262
	int ret;
263
	if (!a)
264
		return 0;
265
	if (!X509_PUBKEY_set(&xpk, a))
266
		return 0;
267
	ret = i2d_X509_PUBKEY(xpk, pp);
268
	X509_PUBKEY_free(xpk);
269
	return ret;
270
}
271
272
/* The following are equivalents but which return RSA and DSA
273
 * keys
274
 */
275
#ifndef OPENSSL_NO_RSA
276
RSA *
277
d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp, long length)
278
{
279
	EVP_PKEY *pkey;
280
	RSA *key;
281
	const unsigned char *q;
282
	q = *pp;
283
	pkey = d2i_PUBKEY(NULL, &q, length);
284
	if (!pkey)
285
		return NULL;
286
	key = EVP_PKEY_get1_RSA(pkey);
287
	EVP_PKEY_free(pkey);
288
	if (!key)
289
		return NULL;
290
	*pp = q;
291
	if (a) {
292
		RSA_free(*a);
293
		*a = key;
294
	}
295
	return key;
296
}
297
298
int
299
i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
300
{
301
	EVP_PKEY *pktmp;
302
	int ret;
303
	if (!a)
304
		return 0;
305
	pktmp = EVP_PKEY_new();
306
	if (!pktmp) {
307
		ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
308
		return 0;
309
	}
310
	EVP_PKEY_set1_RSA(pktmp, a);
311
	ret = i2d_PUBKEY(pktmp, pp);
312
	EVP_PKEY_free(pktmp);
313
	return ret;
314
}
315
#endif
316
317
#ifndef OPENSSL_NO_DSA
318
DSA *
319
d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp, long length)
320
{
321
	EVP_PKEY *pkey;
322
	DSA *key;
323
	const unsigned char *q;
324
	q = *pp;
325
	pkey = d2i_PUBKEY(NULL, &q, length);
326
	if (!pkey)
327
		return NULL;
328
	key = EVP_PKEY_get1_DSA(pkey);
329
	EVP_PKEY_free(pkey);
330
	if (!key)
331
		return NULL;
332
	*pp = q;
333
	if (a) {
334
		DSA_free(*a);
335
		*a = key;
336
	}
337
	return key;
338
}
339
340
int
341
i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
342
{
343
	EVP_PKEY *pktmp;
344
	int ret;
345
	if (!a)
346
		return 0;
347
	pktmp = EVP_PKEY_new();
348
	if (!pktmp) {
349
		ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
350
		return 0;
351
	}
352
	EVP_PKEY_set1_DSA(pktmp, a);
353
	ret = i2d_PUBKEY(pktmp, pp);
354
	EVP_PKEY_free(pktmp);
355
	return ret;
356
}
357
#endif
358
359
#ifndef OPENSSL_NO_EC
360
EC_KEY *
361
d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
362
{
363
	EVP_PKEY *pkey;
364
	EC_KEY *key;
365
	const unsigned char *q;
366
	q = *pp;
367
	pkey = d2i_PUBKEY(NULL, &q, length);
368
	if (!pkey)
369
		return (NULL);
370
	key = EVP_PKEY_get1_EC_KEY(pkey);
371
	EVP_PKEY_free(pkey);
372
	if (!key)
373
		return (NULL);
374
	*pp = q;
375
	if (a) {
376
		EC_KEY_free(*a);
377
		*a = key;
378
	}
379
	return (key);
380
}
381
382
int
383
i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
384
{
385
	EVP_PKEY *pktmp;
386
	int ret;
387
	if (!a)
388
		return (0);
389
	if ((pktmp = EVP_PKEY_new()) == NULL) {
390
		ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
391
		return (0);
392
	}
393
	EVP_PKEY_set1_EC_KEY(pktmp, a);
394
	ret = i2d_PUBKEY(pktmp, pp);
395
	EVP_PKEY_free(pktmp);
396
	return (ret);
397
}
398
#endif
399
400
int
401
X509_PUBKEY_set0_param(X509_PUBKEY *pub, ASN1_OBJECT *aobj, int ptype,
402
    void *pval, unsigned char *penc, int penclen)
403
{
404
	if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
405
		return 0;
406
	if (penc) {
407
		free(pub->public_key->data);
408
		pub->public_key->data = penc;
409
		pub->public_key->length = penclen;
410
		/* Set number of unused bits to zero */
411
		pub->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
412
		pub->public_key->flags |= ASN1_STRING_FLAG_BITS_LEFT;
413
	}
414
	return 1;
415
}
416
417
int
418
X509_PUBKEY_get0_param(ASN1_OBJECT **ppkalg, const unsigned char **pk,
419
    int *ppklen, X509_ALGOR **pa, X509_PUBKEY *pub)
420
8
{
421
8
	if (ppkalg)
422
		*ppkalg = pub->algor->algorithm;
423
8
	if (pk) {
424
8
		*pk = pub->public_key->data;
425
8
		*ppklen = pub->public_key->length;
426
	}
427
8
	if (pa)
428
2
		*pa = pub->algor;
429
8
	return 1;
430
}