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