xref: /openbsd-src/lib/libcrypto/asn1/x_pubkey.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
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/asn1_mac.h>
62 #include <openssl/x509.h>
63 
64 int i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **pp)
65 	{
66 	M_ASN1_I2D_vars(a);
67 
68 	M_ASN1_I2D_len(a->algor,	i2d_X509_ALGOR);
69 	M_ASN1_I2D_len(a->public_key,	i2d_ASN1_BIT_STRING);
70 
71 	M_ASN1_I2D_seq_total();
72 
73 	M_ASN1_I2D_put(a->algor,	i2d_X509_ALGOR);
74 	M_ASN1_I2D_put(a->public_key,	i2d_ASN1_BIT_STRING);
75 
76 	M_ASN1_I2D_finish();
77 	}
78 
79 X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **a, unsigned char **pp,
80 	     long length)
81 	{
82 	M_ASN1_D2I_vars(a,X509_PUBKEY *,X509_PUBKEY_new);
83 
84 	M_ASN1_D2I_Init();
85 	M_ASN1_D2I_start_sequence();
86 	M_ASN1_D2I_get(ret->algor,d2i_X509_ALGOR);
87 	M_ASN1_D2I_get(ret->public_key,d2i_ASN1_BIT_STRING);
88 	if (ret->pkey != NULL)
89 		{
90 		EVP_PKEY_free(ret->pkey);
91 		ret->pkey=NULL;
92 		}
93 	M_ASN1_D2I_Finish(a,X509_PUBKEY_free,ASN1_F_D2I_X509_PUBKEY);
94 	}
95 
96 X509_PUBKEY *X509_PUBKEY_new(void)
97 	{
98 	X509_PUBKEY *ret=NULL;
99 	ASN1_CTX c;
100 
101 	M_ASN1_New_Malloc(ret,X509_PUBKEY);
102 	M_ASN1_New(ret->algor,X509_ALGOR_new);
103 	M_ASN1_New(ret->public_key,M_ASN1_BIT_STRING_new);
104 	ret->pkey=NULL;
105 	return(ret);
106 	M_ASN1_New_Error(ASN1_F_X509_PUBKEY_NEW);
107 	}
108 
109 void X509_PUBKEY_free(X509_PUBKEY *a)
110 	{
111 	if (a == NULL) return;
112 	X509_ALGOR_free(a->algor);
113 	M_ASN1_BIT_STRING_free(a->public_key);
114 	if (a->pkey != NULL) EVP_PKEY_free(a->pkey);
115 	OPENSSL_free(a);
116 	}
117 
118 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
119 	{
120 	int ok=0;
121 	X509_PUBKEY *pk;
122 	X509_ALGOR *a;
123 	ASN1_OBJECT *o;
124 	unsigned char *s,*p;
125 	int i;
126 
127 	if (x == NULL) return(0);
128 
129 	if ((pk=X509_PUBKEY_new()) == NULL) goto err;
130 	a=pk->algor;
131 
132 	/* set the algorithm id */
133 	if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
134 	ASN1_OBJECT_free(a->algorithm);
135 	a->algorithm=o;
136 
137 	/* Set the parameter list */
138 	if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA))
139 		{
140 		if ((a->parameter == NULL) ||
141 			(a->parameter->type != V_ASN1_NULL))
142 			{
143 			ASN1_TYPE_free(a->parameter);
144 			a->parameter=ASN1_TYPE_new();
145 			a->parameter->type=V_ASN1_NULL;
146 			}
147 		}
148 	else
149 #ifndef NO_DSA
150 		if (pkey->type == EVP_PKEY_DSA)
151 		{
152 		unsigned char *pp;
153 		DSA *dsa;
154 
155 		dsa=pkey->pkey.dsa;
156 		dsa->write_params=0;
157 		ASN1_TYPE_free(a->parameter);
158 		i=i2d_DSAparams(dsa,NULL);
159 		p=(unsigned char *)OPENSSL_malloc(i);
160 		pp=p;
161 		i2d_DSAparams(dsa,&pp);
162 		a->parameter=ASN1_TYPE_new();
163 		a->parameter->type=V_ASN1_SEQUENCE;
164 		a->parameter->value.sequence=ASN1_STRING_new();
165 		ASN1_STRING_set(a->parameter->value.sequence,p,i);
166 		OPENSSL_free(p);
167 		}
168 	else
169 #endif
170 		{
171 		X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
172 		goto err;
173 		}
174 
175 	if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
176 	if ((s=(unsigned char *)OPENSSL_malloc(i+1)) == NULL) goto err;
177 	p=s;
178 	i2d_PublicKey(pkey,&p);
179 	if (!M_ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err;
180 	/* Set number of unused bits to zero */
181 	pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
182 	pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
183 
184 	OPENSSL_free(s);
185 
186 #if 0
187 	CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
188 	pk->pkey=pkey;
189 #endif
190 
191 	if (*x != NULL)
192 		X509_PUBKEY_free(*x);
193 
194 	*x=pk;
195 	pk=NULL;
196 
197 	ok=1;
198 err:
199 	if (pk != NULL) X509_PUBKEY_free(pk);
200 	return(ok);
201 	}
202 
203 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
204 	{
205 	EVP_PKEY *ret=NULL;
206 	long j;
207 	int type;
208 	unsigned char *p;
209 #ifndef NO_DSA
210 	X509_ALGOR *a;
211 #endif
212 
213 	if (key == NULL) goto err;
214 
215 	if (key->pkey != NULL)
216 	    {
217 	    CRYPTO_add(&key->pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
218 	    return(key->pkey);
219 	    }
220 
221 	if (key->public_key == NULL) goto err;
222 
223 	type=OBJ_obj2nid(key->algor->algorithm);
224 	p=key->public_key->data;
225         j=key->public_key->length;
226         if ((ret=d2i_PublicKey(type,NULL,&p,(long)j)) == NULL)
227 		{
228 		X509err(X509_F_X509_PUBKEY_GET,X509_R_ERR_ASN1_LIB);
229 		goto err;
230 		}
231 	ret->save_parameters=0;
232 
233 #ifndef NO_DSA
234 	a=key->algor;
235 	if (ret->type == EVP_PKEY_DSA)
236 		{
237 		if (a->parameter && (a->parameter->type == V_ASN1_SEQUENCE))
238 			{
239 			ret->pkey.dsa->write_params=0;
240 			p=a->parameter->value.sequence->data;
241 			j=a->parameter->value.sequence->length;
242 			if (!d2i_DSAparams(&ret->pkey.dsa,&p,(long)j))
243 				goto err;
244 			}
245 		ret->save_parameters=1;
246 		}
247 #endif
248 	key->pkey=ret;
249 	CRYPTO_add(&ret->references,1,CRYPTO_LOCK_EVP_PKEY);
250 	return(ret);
251 err:
252 	if (ret != NULL)
253 		EVP_PKEY_free(ret);
254 	return(NULL);
255 	}
256 
257 /* Now two pseudo ASN1 routines that take an EVP_PKEY structure
258  * and encode or decode as X509_PUBKEY
259  */
260 
261 EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, unsigned char **pp,
262 	     long length)
263 {
264 	X509_PUBKEY *xpk;
265 	EVP_PKEY *pktmp;
266 	xpk = d2i_X509_PUBKEY(NULL, pp, length);
267 	if(!xpk) return NULL;
268 	pktmp = X509_PUBKEY_get(xpk);
269 	X509_PUBKEY_free(xpk);
270 	if(!pktmp) return NULL;
271 	if(a) {
272 		EVP_PKEY_free(*a);
273 		*a = pktmp;
274 	}
275 	return pktmp;
276 }
277 
278 int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
279 {
280 	X509_PUBKEY *xpk=NULL;
281 	int ret;
282 	if(!a) return 0;
283 	if(!X509_PUBKEY_set(&xpk, a)) return 0;
284 	ret = i2d_X509_PUBKEY(xpk, pp);
285 	X509_PUBKEY_free(xpk);
286 	return ret;
287 }
288 
289 /* The following are equivalents but which return RSA and DSA
290  * keys
291  */
292 #ifndef NO_RSA
293 RSA *d2i_RSA_PUBKEY(RSA **a, unsigned char **pp,
294 	     long length)
295 {
296 	EVP_PKEY *pkey;
297 	RSA *key;
298 	unsigned char *q;
299 	q = *pp;
300 	pkey = d2i_PUBKEY(NULL, &q, length);
301 	if(!pkey) return NULL;
302 	key = EVP_PKEY_get1_RSA(pkey);
303 	EVP_PKEY_free(pkey);
304 	if(!key) return NULL;
305 	*pp = q;
306 	if(a) {
307 		RSA_free(*a);
308 		*a = key;
309 	}
310 	return key;
311 }
312 
313 int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
314 {
315 	EVP_PKEY *pktmp;
316 	int ret;
317 	if(!a) return 0;
318 	pktmp = EVP_PKEY_new();
319 	if(!pktmp) {
320 		ASN1err(ASN1_F_I2D_RSA_PUBKEY, ERR_R_MALLOC_FAILURE);
321 		return 0;
322 	}
323 	EVP_PKEY_set1_RSA(pktmp, a);
324 	ret = i2d_PUBKEY(pktmp, pp);
325 	EVP_PKEY_free(pktmp);
326 	return ret;
327 }
328 #endif
329 
330 #ifndef NO_DSA
331 DSA *d2i_DSA_PUBKEY(DSA **a, unsigned char **pp,
332 	     long length)
333 {
334 	EVP_PKEY *pkey;
335 	DSA *key;
336 	unsigned char *q;
337 	q = *pp;
338 	pkey = d2i_PUBKEY(NULL, &q, length);
339 	if(!pkey) return NULL;
340 	key = EVP_PKEY_get1_DSA(pkey);
341 	EVP_PKEY_free(pkey);
342 	if(!key) return NULL;
343 	*pp = q;
344 	if(a) {
345 		DSA_free(*a);
346 		*a = key;
347 	}
348 	return key;
349 }
350 
351 int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
352 {
353 	EVP_PKEY *pktmp;
354 	int ret;
355 	if(!a) return 0;
356 	pktmp = EVP_PKEY_new();
357 	if(!pktmp) {
358 		ASN1err(ASN1_F_I2D_DSA_PUBKEY, ERR_R_MALLOC_FAILURE);
359 		return 0;
360 	}
361 	EVP_PKEY_set1_DSA(pktmp, a);
362 	ret = i2d_PUBKEY(pktmp, pp);
363 	EVP_PKEY_free(pktmp);
364 	return ret;
365 }
366 #endif
367