xref: /onnv-gate/usr/src/common/openssl/crypto/asn1/x_pubkey.c (revision 2139:6243c3338933)
1 /* crypto/asn1/x_pubkey.c */
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 #include "cryptlib.h"
61 #include <openssl/asn1t.h>
62 #include <openssl/x509.h>
63 #ifndef OPENSSL_NO_RSA
64 #include <openssl/rsa.h>
65 #endif
66 #ifndef OPENSSL_NO_DSA
67 #include <openssl/dsa.h>
68 #endif
69 
70 /* Minor tweak to operation: free up EVP_PKEY */
pubkey_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it)71 static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it)
72 	{
73 	if (operation == ASN1_OP_FREE_POST)
74 		{
75 		X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
76 		EVP_PKEY_free(pubkey->pkey);
77 		}
78 	return 1;
79 	}
80 
81 ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
82 	ASN1_SIMPLE(X509_PUBKEY, algor, X509_ALGOR),
83 	ASN1_SIMPLE(X509_PUBKEY, public_key, ASN1_BIT_STRING)
84 } ASN1_SEQUENCE_END_cb(X509_PUBKEY, X509_PUBKEY)
85 
86 IMPLEMENT_ASN1_FUNCTIONS(X509_PUBKEY)
87 
88 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
89 	{
90 	X509_PUBKEY *pk=NULL;
91 	X509_ALGOR *a;
92 	ASN1_OBJECT *o;
93 	unsigned char *s,*p = NULL;
94 	int i;
95 
96 	if (x == NULL) return(0);
97 
98 	if ((pk=X509_PUBKEY_new()) == NULL) goto err;
99 	a=pk->algor;
100 
101 	/* set the algorithm id */
102 	if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
103 	ASN1_OBJECT_free(a->algorithm);
104 	a->algorithm=o;
105 
106 	/* Set the parameter list */
107 	if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA))
108 		{
109 		if ((a->parameter == NULL) ||
110 			(a->parameter->type != V_ASN1_NULL))
111 			{
112 			ASN1_TYPE_free(a->parameter);
113 			if (!(a->parameter=ASN1_TYPE_new()))
114 				{
115 				X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
116 				goto err;
117 				}
118 			a->parameter->type=V_ASN1_NULL;
119 			}
120 		}
121 #ifndef OPENSSL_NO_DSA
122 	else if (pkey->type == EVP_PKEY_DSA)
123 		{
124 		unsigned char *pp;
125 		DSA *dsa;
126 
127 		dsa=pkey->pkey.dsa;
128 		dsa->write_params=0;
129 		ASN1_TYPE_free(a->parameter);
130 		if ((i=i2d_DSAparams(dsa,NULL)) <= 0)
131 			goto err;
132 		if (!(p=(unsigned char *)OPENSSL_malloc(i)))
133 			{
134 			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
135 			goto err;
136 			}
137 		pp=p;
138 		i2d_DSAparams(dsa,&pp);
139 		if (!(a->parameter=ASN1_TYPE_new()))
140 			{
141 			OPENSSL_free(p);
142 			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
143 			goto err;
144 			}
145 		a->parameter->type=V_ASN1_SEQUENCE;
146 		if (!(a->parameter->value.sequence=ASN1_STRING_new()))
147 			{
148 			OPENSSL_free(p);
149 			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
150 			goto err;
151 			}
152 		if (!ASN1_STRING_set(a->parameter->value.sequence,p,i))
153 			{
154 			OPENSSL_free(p);
155 			X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
156 			goto err;
157 			}
158 		OPENSSL_free(p);
159 		}
160 #endif
161 #ifndef OPENSSL_NO_EC
162 	else if (pkey->type == EVP_PKEY_EC)
163 		{
164 		int nid=0;
165 		unsigned char *pp;
166 		EC_KEY *ec_key;
167 		const EC_GROUP *group;
168 
169 		ec_key = pkey->pkey.ec;
170 		ASN1_TYPE_free(a->parameter);
171 
172 		if ((a->parameter = ASN1_TYPE_new()) == NULL)
173 			{
174 			X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
175 			goto err;
176 			}
177 
178 		group = EC_KEY_get0_group(ec_key);
179 		if (EC_GROUP_get_asn1_flag(group)
180                      && (nid = EC_GROUP_get_curve_name(group)))
181 			{
182 			/* just set the OID */
183 			a->parameter->type = V_ASN1_OBJECT;
184 			a->parameter->value.object = OBJ_nid2obj(nid);
185 			}
186 		else /* explicit parameters */
187 			{
188 			if ((i = i2d_ECParameters(ec_key, NULL)) == 0)
189 				{
190 				X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
191 				goto err;
192 				}
193 			if ((p = (unsigned char *) OPENSSL_malloc(i)) == NULL)
194 				{
195 				X509err(X509_F_X509_PUBKEY_SET, ERR_R_MALLOC_FAILURE);
196 				goto err;
197 				}
198 			pp = p;
199 			if (!i2d_ECParameters(ec_key, &pp))
200 				{
201 				X509err(X509_F_X509_PUBKEY_SET, ERR_R_EC_LIB);
202 				OPENSSL_free(p);
203 				goto err;
204 				}
205 			a->parameter->type = V_ASN1_SEQUENCE;
206 			if ((a->parameter->value.sequence = ASN1_STRING_new()) == NULL)
207 				{
208 				X509err(X509_F_X509_PUBKEY_SET, ERR_R_ASN1_LIB);
209 				OPENSSL_free(p);
210 				goto err;
211 				}
212 			ASN1_STRING_set(a->parameter->value.sequence, p, i);
213 			OPENSSL_free(p);
214 			}
215 		}
216 #endif
217 	else if (1)
218 		{
219 		X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
220 		goto err;
221 		}
222 
223 	if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
224 	if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL)
225 		{
226 		X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
227 		goto err;
228 		}
229 	p=s;
230 	i2d_PublicKey(pkey,&p);
231 	if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i))
232 		{
233 		X509err(X509_F_X509_PUBKEY_SET,ERR_R_MALLOC_FAILURE);
234 		goto err;
235 		}
236   	/* Set number of unused bits to zero */
237 	pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
238 	pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
239 
240 	OPENSSL_free(s);
241 
242 #if 0
243 	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
244 	pk->pkey=pkey;
245 #endif
246 
247 	if (*x != NULL)
248 		X509_PUBKEY_free(*x);
249 
250 	*x=pk;
251 
252 	return 1;
253 err:
254 	if (pk != NULL) X509_PUBKEY_free(pk);
255 	return 0;
256 	}
257 
X509_PUBKEY_get(X509_PUBKEY * key)258 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
259 	{
260 	EVP_PKEY *ret=NULL;
261 	long j;
262 	int type;
263 	const unsigned char *p;
264 #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
265 	const unsigned char *cp;
266 	X509_ALGOR *a;
267 #endif
268 
269 	if (key == NULL) goto err;
270 
271 	if (key->pkey != NULL)
272 		{
273 		CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY);
274 		return(key->pkey);
275 		}
276 
277 	if (key->public_key == NULL) goto err;
278 
279 	type=OBJ_obj2nid(key->algor->algorithm);
280 	if ((ret = EVP_PKEY_new()) == NULL)
281 		{
282 		X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
283 		goto err;
284 		}
285 	ret->type = EVP_PKEY_type(type);
286 
287 	/* the parameters must be extracted before the public key (ECDSA!) */
288 
289 #if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_ECDSA)
290 	a=key->algor;
291 #endif
292 
293 	if (0)
294 		;
295 #ifndef OPENSSL_NO_DSA
296 	else if (ret->type == EVP_PKEY_DSA)
297 		{
298 		if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
299 			{
300 			if ((ret->pkey.dsa = DSA_new()) == NULL)
301 				{
302 				X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE);
303 				goto err;
304 				}
305 			ret->pkey.dsa->write_params=0;
306 			cp=p=a->parameter->value.sequence->data;
307 			j=a->parameter->value.sequence->length;
308 			if (!d2i_DSAparams(&ret->pkey.dsa, &cp, (long)j))
309 				goto err;
310 			}
311 		ret->save_parameters=1;
312 		}
313 #endif
314 #ifndef OPENSSL_NO_EC
315 	else if (ret->type == EVP_PKEY_EC)
316 		{
317 		if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
318 			{
319 			/* type == V_ASN1_SEQUENCE => we have explicit parameters
320                          * (e.g. parameters in the X9_62_EC_PARAMETERS-structure )
321 			 */
322 			if ((ret->pkey.ec= EC_KEY_new()) == NULL)
323 				{
324 				X509err(X509_F_X509_PUBKEY_GET,
325 					ERR_R_MALLOC_FAILURE);
326 				goto err;
327 				}
328 			cp = p = a->parameter->value.sequence->data;
329 			j = a->parameter->value.sequence->length;
330 			if (!d2i_ECParameters(&ret->pkey.ec, &cp, (long)j))
331 				{
332 				X509err(X509_F_X509_PUBKEY_GET, ERR_R_EC_LIB);
333 				goto err;
334 				}
335 			}
336 		else if (a->parameter && (a->parameter->type == V_ASN1_OBJECT))
337 			{
338 			/* type == V_ASN1_OBJECT => the parameters are given
339 			 * by an asn1 OID
340 			 */
341 			EC_KEY   *ec_key;
342 			EC_GROUP *group;
343 
344 			if (ret->pkey.ec == NULL)
345 				ret->pkey.ec = EC_KEY_new();
346 			ec_key = ret->pkey.ec;
347 			if (ec_key == NULL)
348 				goto err;
349 			group = EC_GROUP_new_by_curve_name(OBJ_obj2nid(a->parameter->value.object));
350 			if (group == NULL)
351 				goto err;
352 			EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
353 			if (EC_KEY_set_group(ec_key, group) == 0)
354 				goto err;
355 			EC_GROUP_free(group);
356 			}
357 			/* the case implicitlyCA is currently not implemented */
358 		ret->save_parameters = 1;
359 		}
360 #endif
361 
362 	p=key->public_key->data;
363         j=key->public_key->length;
364         if (!d2i_PublicKey(type, &ret, &p, (long)j))
365 		{
366 		X509err(X509_F_X509_PUBKEY_GET, X509_R_ERR_ASN1_LIB);
367 		goto err;
368 		}
369 
370 	key->pkey = ret;
371 	CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY);
372 	return(ret);
373 err:
374 	if (ret != NULL)
375 		EVP_PKEY_free(ret);
376 	return(NULL);
377 	}
378 
379 /* Now two pseudo ASN1 routines that take an EVP_PKEY structure
380  * and encode or decode as X509_PUBKEY
381  */
382 
d2i_PUBKEY(EVP_PKEY ** a,const unsigned char ** pp,long length)383 EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
384 	     long length)
385 	{
386 	X509_PUBKEY *xpk;
387 	EVP_PKEY *pktmp;
388 	xpk = d2i_X509_PUBKEY(NULL, pp, length);
389 	if(!xpk) return NULL;
390 	pktmp = X509_PUBKEY_get(xpk);
391 	X509_PUBKEY_free(xpk);
392 	if(!pktmp) return NULL;
393 	if(a)
394 		{
395 		EVP_PKEY_free(*a);
396 		*a = pktmp;
397 		}
398 	return pktmp;
399 	}
400 
i2d_PUBKEY(EVP_PKEY * a,unsigned char ** pp)401 int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
402 	{
403 	X509_PUBKEY *xpk=NULL;
404 	int ret;
405 	if(!a) return 0;
406 	if(!X509_PUBKEY_set(&xpk, a)) return 0;
407 	ret = i2d_X509_PUBKEY(xpk, pp);
408 	X509_PUBKEY_free(xpk);
409 	return ret;
410 	}
411 
412 /* The following are equivalents but which return RSA and DSA
413  * keys
414  */
415 #ifndef OPENSSL_NO_RSA
d2i_RSA_PUBKEY(RSA ** a,const unsigned char ** pp,long length)416 RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
417 	     long length)
418 	{
419 	EVP_PKEY *pkey;
420 	RSA *key;
421 	const unsigned char *q;
422 	q = *pp;
423 	pkey = d2i_PUBKEY(NULL, &q, length);
424 	if (!pkey) return NULL;
425 	key = EVP_PKEY_get1_RSA(pkey);
426 	EVP_PKEY_free(pkey);
427 	if (!key) return NULL;
428 	*pp = q;
429 	if (a)
430 		{
431 		RSA_free(*a);
432 		*a = key;
433 		}
434 	return key;
435 	}
436 
i2d_RSA_PUBKEY(RSA * a,unsigned char ** pp)437 int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
438 	{
439 	EVP_PKEY *pktmp;
440 	int ret;
441 	if (!a) return 0;
442 	pktmp = EVP_PKEY_new();
443 	if (!pktmp)
444 		{
445 		ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
446 		return 0;
447 		}
448 	EVP_PKEY_set1_RSA(pktmp, a);
449 	ret = i2d_PUBKEY(pktmp, pp);
450 	EVP_PKEY_free(pktmp);
451 	return ret;
452 	}
453 #endif
454 
455 #ifndef OPENSSL_NO_DSA
d2i_DSA_PUBKEY(DSA ** a,const unsigned char ** pp,long length)456 DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
457 	     long length)
458 	{
459 	EVP_PKEY *pkey;
460 	DSA *key;
461 	const unsigned char *q;
462 	q = *pp;
463 	pkey = d2i_PUBKEY(NULL, &q, length);
464 	if (!pkey) return NULL;
465 	key = EVP_PKEY_get1_DSA(pkey);
466 	EVP_PKEY_free(pkey);
467 	if (!key) return NULL;
468 	*pp = q;
469 	if (a)
470 		{
471 		DSA_free(*a);
472 		*a = key;
473 		}
474 	return key;
475 	}
476 
i2d_DSA_PUBKEY(DSA * a,unsigned char ** pp)477 int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
478 	{
479 	EVP_PKEY *pktmp;
480 	int ret;
481 	if(!a) return 0;
482 	pktmp = EVP_PKEY_new();
483 	if(!pktmp)
484 		{
485 		ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
486 		return 0;
487 		}
488 	EVP_PKEY_set1_DSA(pktmp, a);
489 	ret = i2d_PUBKEY(pktmp, pp);
490 	EVP_PKEY_free(pktmp);
491 	return ret;
492 	}
493 #endif
494 
495 #ifndef OPENSSL_NO_EC
d2i_EC_PUBKEY(EC_KEY ** a,const unsigned char ** pp,long length)496 EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
497 	{
498 	EVP_PKEY *pkey;
499 	EC_KEY *key;
500 	const unsigned char *q;
501 	q = *pp;
502 	pkey = d2i_PUBKEY(NULL, &q, length);
503 	if (!pkey) return(NULL);
504 	key = EVP_PKEY_get1_EC_KEY(pkey);
505 	EVP_PKEY_free(pkey);
506 	if (!key)  return(NULL);
507 	*pp = q;
508 	if (a)
509 		{
510 		EC_KEY_free(*a);
511 		*a = key;
512 		}
513 	return(key);
514 	}
515 
i2d_EC_PUBKEY(EC_KEY * a,unsigned char ** pp)516 int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
517 	{
518 	EVP_PKEY *pktmp;
519 	int ret;
520 	if (!a)	return(0);
521 	if ((pktmp = EVP_PKEY_new()) == NULL)
522 		{
523 		ASN1err(ASN1_F_I2D_EC_PUBKEY, ERR_R_MALLOC_FAILURE);
524 		return(0);
525 		}
526 	EVP_PKEY_set1_EC_KEY(pktmp, a);
527 	ret = i2d_PUBKEY(pktmp, pp);
528 	EVP_PKEY_free(pktmp);
529 	return(ret);
530 	}
531 #endif
532