Import OpenSSL 0.9.8a
[dragonfly.git] / crypto / openssl-0.9 / crypto / asn1 / x_pubkey.c
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 */
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
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
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
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
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
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
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
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
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
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