Change functions to ANSI C.
[openssl.git] / 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 "asn1_mac.h"
62
63 /*
64  * ASN1err(ASN1_F_D2I_X509_PUBKEY,ERR_R_ASN1_LENGTH_MISMATCH);
65  * ASN1err(ASN1_F_X509_PUBKEY_NEW,ERR_R_ASN1_LENGTH_MISMATCH);
66  */
67
68 int i2d_X509_PUBKEY(X509_PUBKEY *a, unsigned char **pp)
69         {
70         M_ASN1_I2D_vars(a);
71
72         M_ASN1_I2D_len(a->algor,        i2d_X509_ALGOR);
73         M_ASN1_I2D_len(a->public_key,   i2d_ASN1_BIT_STRING);
74
75         M_ASN1_I2D_seq_total();
76
77         M_ASN1_I2D_put(a->algor,        i2d_X509_ALGOR);
78         M_ASN1_I2D_put(a->public_key,   i2d_ASN1_BIT_STRING);
79
80         M_ASN1_I2D_finish();
81         }
82
83 X509_PUBKEY *d2i_X509_PUBKEY(X509_PUBKEY **a, unsigned char **pp,
84              long length)
85         {
86         M_ASN1_D2I_vars(a,X509_PUBKEY *,X509_PUBKEY_new);
87
88         M_ASN1_D2I_Init();
89         M_ASN1_D2I_start_sequence();
90         M_ASN1_D2I_get(ret->algor,d2i_X509_ALGOR);
91         M_ASN1_D2I_get(ret->public_key,d2i_ASN1_BIT_STRING);
92         if (ret->pkey != NULL)
93                 {
94                 EVP_PKEY_free(ret->pkey);
95                 ret->pkey=NULL;
96                 }
97         M_ASN1_D2I_Finish(a,X509_PUBKEY_free,ASN1_F_D2I_X509_PUBKEY);
98         }
99
100 X509_PUBKEY *X509_PUBKEY_new(void)
101         {
102         X509_PUBKEY *ret=NULL;
103         ASN1_CTX c;
104
105         M_ASN1_New_Malloc(ret,X509_PUBKEY);
106         M_ASN1_New(ret->algor,X509_ALGOR_new);
107         M_ASN1_New(ret->public_key,ASN1_BIT_STRING_new);
108         ret->pkey=NULL;
109         return(ret);
110         M_ASN1_New_Error(ASN1_F_X509_PUBKEY_NEW);
111         }
112
113 void X509_PUBKEY_free(X509_PUBKEY *a)
114         {
115         if (a == NULL) return;
116         X509_ALGOR_free(a->algor);
117         ASN1_BIT_STRING_free(a->public_key);
118         if (a->pkey != NULL) EVP_PKEY_free(a->pkey);
119         Free((char *)a);
120         }
121
122 int X509_PUBKEY_set(X509_PUBKEY **x, EVP_PKEY *pkey)
123         {
124         int ok=0;
125         X509_PUBKEY *pk;
126         X509_ALGOR *a;
127         ASN1_OBJECT *o;
128         unsigned char *s,*p;
129         int i;
130
131         if (x == NULL) return(0);
132
133         if ((pk=X509_PUBKEY_new()) == NULL) goto err;
134         a=pk->algor;
135
136         /* set the algorithm id */
137         if ((o=OBJ_nid2obj(pkey->type)) == NULL) goto err;
138         ASN1_OBJECT_free(a->algorithm);
139         a->algorithm=o;
140
141         /* Set the parameter list */
142         if (!pkey->save_parameters || (pkey->type == EVP_PKEY_RSA))
143                 {
144                 if ((a->parameter == NULL) ||
145                         (a->parameter->type != V_ASN1_NULL))
146                         {
147                         ASN1_TYPE_free(a->parameter);
148                         a->parameter=ASN1_TYPE_new();
149                         a->parameter->type=V_ASN1_NULL;
150                         }
151                 }
152         else
153 #ifndef NO_DSA
154                 if (pkey->type == EVP_PKEY_DSA)
155                 {
156                 unsigned char *pp;
157                 DSA *dsa;
158
159                 dsa=pkey->pkey.dsa;
160                 dsa->write_params=0;
161                 ASN1_TYPE_free(a->parameter);
162                 i=i2d_DSAparams(dsa,NULL);
163                 p=(unsigned char *)Malloc(i);
164                 pp=p;
165                 i2d_DSAparams(dsa,&pp);
166                 a->parameter=ASN1_TYPE_new();
167                 a->parameter->type=V_ASN1_SEQUENCE;
168                 a->parameter->value.sequence=ASN1_STRING_new();
169                 ASN1_STRING_set(a->parameter->value.sequence,p,i);
170                 Free(p);
171                 }
172         else
173 #endif
174                 {
175                 X509err(X509_F_X509_PUBKEY_SET,X509_R_UNSUPPORTED_ALGORITHM);
176                 goto err;
177                 }
178
179         if ((i=i2d_PublicKey(pkey,NULL)) <= 0) goto err;
180         if ((s=(unsigned char *)Malloc(i+1)) == NULL) goto err;
181         p=s;
182         i2d_PublicKey(pkey,&p);
183         if (!ASN1_BIT_STRING_set(pk->public_key,s,i)) goto err;
184         /* Set number of unused bits to zero */
185         pk->public_key->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07);
186         pk->public_key->flags|=ASN1_STRING_FLAG_BITS_LEFT;
187
188         Free(s);
189
190         CRYPTO_add(&pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
191         pk->pkey=pkey;
192
193         if (*x != NULL)
194                 X509_PUBKEY_free(*x);
195
196         *x=pk;
197         pk=NULL;
198
199         ok=1;
200 err:
201         if (pk != NULL) X509_PUBKEY_free(pk);
202         return(ok);
203         }
204
205 EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key)
206         {
207         EVP_PKEY *ret=NULL;
208         long j;
209         int type;
210         unsigned char *p;
211 #ifndef NO_DSA
212         X509_ALGOR *a;
213 #endif
214
215         if (key == NULL) goto err;
216
217         if (key->pkey != NULL)
218             {
219             CRYPTO_add(&key->pkey->references,1,CRYPTO_LOCK_EVP_PKEY);
220             return(key->pkey);
221             }
222
223         if (key->public_key == NULL) goto err;
224
225         type=OBJ_obj2nid(key->algor->algorithm);
226         p=key->public_key->data;
227         j=key->public_key->length;
228         if ((ret=d2i_PublicKey(type,NULL,&p,(long)j)) == NULL)
229                 {
230                 X509err(X509_F_X509_PUBKEY_GET,X509_R_ERR_ASN1_LIB);
231                 goto err;
232                 }
233         ret->save_parameters=0;
234
235 #ifndef NO_DSA
236         a=key->algor;
237         if (ret->type == EVP_PKEY_DSA)
238                 {
239                 if (a->parameter->type == V_ASN1_SEQUENCE)
240                         {
241                         ret->pkey.dsa->write_params=0;
242                         p=a->parameter->value.sequence->data;
243                         j=a->parameter->value.sequence->length;
244                         if (!d2i_DSAparams(&ret->pkey.dsa,&p,(long)j))
245                                 goto err;
246                         }
247                 ret->save_parameters=1;
248                 }
249 #endif
250         key->pkey=ret;
251         CRYPTO_add(&ret->references,1,CRYPTO_LOCK_EVP_PKEY);
252         return(ret);
253 err:
254         if (ret != NULL)
255                 EVP_PKEY_free(ret);
256         return(NULL);
257         }
258