OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
x_pubkey.c
Go to the documentation of this file.
1 /* crypto/asn1/x_pubkey.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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 #include "asn1_locl.h"
64 #ifndef OPENSSL_NO_RSA
65 #include <openssl/rsa.h>
66 #endif
67 #ifndef OPENSSL_NO_DSA
68 #include <openssl/dsa.h>
69 #endif
70 
71 /* Minor tweak to operation: free up EVP_PKEY */
72 static int pubkey_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
73  void *exarg)
74  {
75  if (operation == ASN1_OP_FREE_POST)
76  {
77  X509_PUBKEY *pubkey = (X509_PUBKEY *)*pval;
78  EVP_PKEY_free(pubkey->pkey);
79  }
80  return 1;
81  }
82 
83 ASN1_SEQUENCE_cb(X509_PUBKEY, pubkey_cb) = {
87 
89 
90 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
91  {
92  X509_PUBKEY *pk=NULL;
93 
94  if (x == NULL) return(0);
95 
96  if ((pk=X509_PUBKEY_new()) == NULL) goto error;
97 
98  if (pkey->ameth)
99  {
100  if (pkey->ameth->pub_encode)
101  {
102  if (!pkey->ameth->pub_encode(pk, pkey))
103  {
106  goto error;
107  }
108  }
109  else
110  {
113  goto error;
114  }
115  }
116  else
117  {
119  goto error;
120  }
121 
122  if (*x != NULL)
123  X509_PUBKEY_free(*x);
124 
125  *x=pk;
126 
127  return 1;
128 error:
129  if (pk != NULL) X509_PUBKEY_free(pk);
130  return 0;
131  }
132 
134  {
135  EVP_PKEY *ret=NULL;
136 
137  if (key == NULL) goto error;
138 
139  if (key->pkey != NULL)
140  {
142  return key->pkey;
143  }
144 
145  if (key->public_key == NULL) goto error;
146 
147  if ((ret = EVP_PKEY_new()) == NULL)
148  {
150  goto error;
151  }
152 
153  if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm)))
154  {
156  goto error;
157  }
158 
159  if (ret->ameth->pub_decode)
160  {
161  if (!ret->ameth->pub_decode(ret, key))
162  {
165  goto error;
166  }
167  }
168  else
169  {
171  goto error;
172  }
173 
174  /* Check to see if another thread set key->pkey first */
176  if (key->pkey)
177  {
178  EVP_PKEY_free(ret);
179  ret = key->pkey;
180  }
181  else
182  key->pkey = ret;
185 
186  return ret;
187 
188  error:
189  if (ret != NULL)
190  EVP_PKEY_free(ret);
191  return(NULL);
192  }
193 
194 /* Now two pseudo ASN1 routines that take an EVP_PKEY structure
195  * and encode or decode as X509_PUBKEY
196  */
197 
198 EVP_PKEY *d2i_PUBKEY(EVP_PKEY **a, const unsigned char **pp,
199  long length)
200  {
201  X509_PUBKEY *xpk;
202  EVP_PKEY *pktmp;
203  xpk = d2i_X509_PUBKEY(NULL, pp, length);
204  if(!xpk) return NULL;
205  pktmp = X509_PUBKEY_get(xpk);
206  X509_PUBKEY_free(xpk);
207  if(!pktmp) return NULL;
208  if(a)
209  {
210  EVP_PKEY_free(*a);
211  *a = pktmp;
212  }
213  return pktmp;
214  }
215 
216 int i2d_PUBKEY(EVP_PKEY *a, unsigned char **pp)
217  {
218  X509_PUBKEY *xpk=NULL;
219  int ret;
220  if(!a) return 0;
221  if(!X509_PUBKEY_set(&xpk, a)) return 0;
222  ret = i2d_X509_PUBKEY(xpk, pp);
223  X509_PUBKEY_free(xpk);
224  return ret;
225  }
226 
227 /* The following are equivalents but which return RSA and DSA
228  * keys
229  */
230 #ifndef OPENSSL_NO_RSA
231 RSA *d2i_RSA_PUBKEY(RSA **a, const unsigned char **pp,
232  long length)
233  {
234  EVP_PKEY *pkey;
235  RSA *key;
236  const unsigned char *q;
237  q = *pp;
238  pkey = d2i_PUBKEY(NULL, &q, length);
239  if (!pkey) return NULL;
240  key = EVP_PKEY_get1_RSA(pkey);
241  EVP_PKEY_free(pkey);
242  if (!key) return NULL;
243  *pp = q;
244  if (a)
245  {
246  RSA_free(*a);
247  *a = key;
248  }
249  return key;
250  }
251 
252 int i2d_RSA_PUBKEY(RSA *a, unsigned char **pp)
253  {
254  EVP_PKEY *pktmp;
255  int ret;
256  if (!a) return 0;
257  pktmp = EVP_PKEY_new();
258  if (!pktmp)
259  {
261  return 0;
262  }
263  EVP_PKEY_set1_RSA(pktmp, a);
264  ret = i2d_PUBKEY(pktmp, pp);
265  EVP_PKEY_free(pktmp);
266  return ret;
267  }
268 #endif
269 
270 #ifndef OPENSSL_NO_DSA
271 DSA *d2i_DSA_PUBKEY(DSA **a, const unsigned char **pp,
272  long length)
273  {
274  EVP_PKEY *pkey;
275  DSA *key;
276  const unsigned char *q;
277  q = *pp;
278  pkey = d2i_PUBKEY(NULL, &q, length);
279  if (!pkey) return NULL;
280  key = EVP_PKEY_get1_DSA(pkey);
281  EVP_PKEY_free(pkey);
282  if (!key) return NULL;
283  *pp = q;
284  if (a)
285  {
286  DSA_free(*a);
287  *a = key;
288  }
289  return key;
290  }
291 
292 int i2d_DSA_PUBKEY(DSA *a, unsigned char **pp)
293  {
294  EVP_PKEY *pktmp;
295  int ret;
296  if(!a) return 0;
297  pktmp = EVP_PKEY_new();
298  if(!pktmp)
299  {
301  return 0;
302  }
303  EVP_PKEY_set1_DSA(pktmp, a);
304  ret = i2d_PUBKEY(pktmp, pp);
305  EVP_PKEY_free(pktmp);
306  return ret;
307  }
308 #endif
309 
310 #ifndef OPENSSL_NO_EC
311 EC_KEY *d2i_EC_PUBKEY(EC_KEY **a, const unsigned char **pp, long length)
312  {
313  EVP_PKEY *pkey;
314  EC_KEY *key;
315  const unsigned char *q;
316  q = *pp;
317  pkey = d2i_PUBKEY(NULL, &q, length);
318  if (!pkey) return(NULL);
319  key = EVP_PKEY_get1_EC_KEY(pkey);
320  EVP_PKEY_free(pkey);
321  if (!key) return(NULL);
322  *pp = q;
323  if (a)
324  {
325  EC_KEY_free(*a);
326  *a = key;
327  }
328  return(key);
329  }
330 
331 int i2d_EC_PUBKEY(EC_KEY *a, unsigned char **pp)
332  {
333  EVP_PKEY *pktmp;
334  int ret;
335  if (!a) return(0);
336  if ((pktmp = EVP_PKEY_new()) == NULL)
337  {
339  return(0);
340  }
341  EVP_PKEY_set1_EC_KEY(pktmp, a);
342  ret = i2d_PUBKEY(pktmp, pp);
343  EVP_PKEY_free(pktmp);
344  return(ret);
345  }
346 #endif
347 
349  int ptype, void *pval,
350  unsigned char *penc, int penclen)
351  {
352  if (!X509_ALGOR_set0(pub->algor, aobj, ptype, pval))
353  return 0;
354  if (penc)
355  {
356  if (pub->public_key->data)
358  pub->public_key->data = penc;
359  pub->public_key->length = penclen;
360  /* Set number of unused bits to zero */
363  }
364  return 1;
365  }
366 
368  const unsigned char **pk, int *ppklen,
369  X509_ALGOR **pa,
370  X509_PUBKEY *pub)
371  {
372  if (ppkalg)
373  *ppkalg = pub->algor->algorithm;
374  if (pk)
375  {
376  *pk = pub->public_key->data;
377  *ppklen = pub->public_key->length;
378  }
379  if (pa)
380  *pa = pub->algor;
381  return 1;
382  }