The C version of bn_sub_part_words is needed not only
[openssl.git] / crypto / asn1 / a_bytes.c
1 /* crypto/asn1/a_bytes.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.h>
62
63 static unsigned long tag2bit[32]={
64 0,      0,      0,      B_ASN1_BIT_STRING,      /* tags  0 -  3 */
65 B_ASN1_OCTET_STRING,    0,      0,              B_ASN1_UNKNOWN,/* tags  4- 7 */
66 B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN, B_ASN1_UNKNOWN,/* tags  8-11 */
67 B_ASN1_UTF8STRING,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,B_ASN1_UNKNOWN,/* tags 12-15 */
68 0,      0,      B_ASN1_NUMERICSTRING,B_ASN1_PRINTABLESTRING,   /* tags 16-19 */
69 B_ASN1_T61STRING,B_ASN1_VIDEOTEXSTRING,B_ASN1_IA5STRING,       /* tags 20-22 */
70 B_ASN1_UTCTIME, B_ASN1_GENERALIZEDTIME,                        /* tags 23-24 */ 
71 B_ASN1_GRAPHICSTRING,B_ASN1_ISO64STRING,B_ASN1_GENERALSTRING,  /* tags 25-27 */
72 B_ASN1_UNIVERSALSTRING,B_ASN1_UNKNOWN,B_ASN1_BMPSTRING,B_ASN1_UNKNOWN, /* tags 28-31 */
73         };
74
75 unsigned long ASN1_tag2bit(int tag)
76 {
77         if((tag < 0) || (tag > 30)) return 0;
78         return tag2bit[tag];
79 }
80
81 static int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c);
82 /* type is a 'bitmap' of acceptable string types.
83  */
84 ASN1_STRING *d2i_ASN1_type_bytes(ASN1_STRING **a, unsigned char **pp,
85              long length, int type)
86         {
87         ASN1_STRING *ret=NULL;
88         unsigned char *p,*s;
89         long len;
90         int inf,tag,xclass;
91         int i=0;
92
93         p= *pp;
94         inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
95         if (inf & 0x80) goto err;
96
97         if (tag >= 32)
98                 {
99                 i=ASN1_R_TAG_VALUE_TOO_HIGH;;
100                 goto err;
101                 }
102         if (!(tag2bit[tag] & type))
103                 {
104                 i=ASN1_R_WRONG_TYPE;
105                 goto err;
106                 }
107
108         /* If a bit-string, exit early */
109         if (tag == V_ASN1_BIT_STRING)
110                 return(d2i_ASN1_BIT_STRING(a,pp,length));
111
112         if ((a == NULL) || ((*a) == NULL))
113                 {
114                 if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
115                 }
116         else
117                 ret=(*a);
118
119         if (len != 0)
120                 {
121                 s=(unsigned char *)OPENSSL_malloc((int)len+1);
122                 if (s == NULL)
123                         {
124                         i=ERR_R_MALLOC_FAILURE;
125                         goto err;
126                         }
127                 memcpy(s,p,(int)len);
128                 s[len]='\0';
129                 p+=len;
130                 }
131         else
132                 s=NULL;
133
134         if (ret->data != NULL) OPENSSL_free(ret->data);
135         ret->length=(int)len;
136         ret->data=s;
137         ret->type=tag;
138         if (a != NULL) (*a)=ret;
139         *pp=p;
140         return(ret);
141 err:
142         ASN1err(ASN1_F_D2I_ASN1_TYPE_BYTES,i);
143         if ((ret != NULL) && ((a == NULL) || (*a != ret)))
144                 ASN1_STRING_free(ret);
145         return(NULL);
146         }
147
148 int i2d_ASN1_bytes(ASN1_STRING *a, unsigned char **pp, int tag, int xclass)
149         {
150         int ret,r,constructed;
151         unsigned char *p;
152
153         if (a == NULL)  return(0);
154
155         if (tag == V_ASN1_BIT_STRING)
156                 return(i2d_ASN1_BIT_STRING(a,pp));
157                 
158         ret=a->length;
159         r=ASN1_object_size(0,ret,tag);
160         if (pp == NULL) return(r);
161         p= *pp;
162
163         if ((tag == V_ASN1_SEQUENCE) || (tag == V_ASN1_SET))
164                 constructed=1;
165         else
166                 constructed=0;
167         ASN1_put_object(&p,constructed,ret,tag,xclass);
168         memcpy(p,a->data,a->length);
169         p+=a->length;
170         *pp= p;
171         return(r);
172         }
173
174 ASN1_STRING *d2i_ASN1_bytes(ASN1_STRING **a, unsigned char **pp, long length,
175              int Ptag, int Pclass)
176         {
177         ASN1_STRING *ret=NULL;
178         unsigned char *p,*s;
179         long len;
180         int inf,tag,xclass;
181         int i=0;
182
183         if ((a == NULL) || ((*a) == NULL))
184                 {
185                 if ((ret=ASN1_STRING_new()) == NULL) return(NULL);
186                 }
187         else
188                 ret=(*a);
189
190         p= *pp;
191         inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
192         if (inf & 0x80)
193                 {
194                 i=ASN1_R_BAD_OBJECT_HEADER;
195                 goto err;
196                 }
197
198         if (tag != Ptag)
199                 {
200                 i=ASN1_R_WRONG_TAG;
201                 goto err;
202                 }
203
204         if (inf & V_ASN1_CONSTRUCTED)
205                 {
206                 ASN1_CTX c;
207
208                 c.pp=pp;
209                 c.p=p;
210                 c.inf=inf;
211                 c.slen=len;
212                 c.tag=Ptag;
213                 c.xclass=Pclass;
214                 c.max=(length == 0)?0:(p+length);
215                 if (!asn1_collate_primitive(ret,&c)) 
216                         goto err; 
217                 else
218                         {
219                         p=c.p;
220                         }
221                 }
222         else
223                 {
224                 if (len != 0)
225                         {
226                         if ((ret->length < len) || (ret->data == NULL))
227                                 {
228                                 if (ret->data != NULL) OPENSSL_free(ret->data);
229                                 s=(unsigned char *)OPENSSL_malloc((int)len + 1);
230                                 if (s == NULL)
231                                         {
232                                         i=ERR_R_MALLOC_FAILURE;
233                                         goto err;
234                                         }
235                                 }
236                         else
237                                 s=ret->data;
238                         memcpy(s,p,(int)len);
239                         s[len] = '\0';
240                         p+=len;
241                         }
242                 else
243                         {
244                         s=NULL;
245                         if (ret->data != NULL) OPENSSL_free(ret->data);
246                         }
247
248                 ret->length=(int)len;
249                 ret->data=s;
250                 ret->type=Ptag;
251                 }
252
253         if (a != NULL) (*a)=ret;
254         *pp=p;
255         return(ret);
256 err:
257         if ((ret != NULL) && ((a == NULL) || (*a != ret)))
258                 ASN1_STRING_free(ret);
259         ASN1err(ASN1_F_D2I_ASN1_BYTES,i);
260         return(NULL);
261         }
262
263
264 /* We are about to parse 0..n d2i_ASN1_bytes objects, we are to collapse
265  * them into the one structure that is then returned */
266 /* There have been a few bug fixes for this function from
267  * Paul Keogh <paul.keogh@sse.ie>, many thanks to him */
268 static int asn1_collate_primitive(ASN1_STRING *a, ASN1_CTX *c)
269         {
270         ASN1_STRING *os=NULL;
271         BUF_MEM b;
272         int num;
273
274         b.length=0;
275         b.max=0;
276         b.data=NULL;
277
278         if (a == NULL)
279                 {
280                 c->error=ERR_R_PASSED_NULL_PARAMETER;
281                 goto err;
282                 }
283
284         num=0;
285         for (;;)
286                 {
287                 if (c->inf & 1)
288                         {
289                         c->eos=ASN1_check_infinite_end(&c->p,
290                                 (long)(c->max-c->p));
291                         if (c->eos) break;
292                         }
293                 else
294                         {
295                         if (c->slen <= 0) break;
296                         }
297
298                 c->q=c->p;
299                 if (d2i_ASN1_bytes(&os,&c->p,c->max-c->p,c->tag,c->xclass)
300                         == NULL)
301                         {
302                         c->error=ERR_R_ASN1_LIB;
303                         goto err;
304                         }
305
306                 if (!BUF_MEM_grow(&b,num+os->length))
307                         {
308                         c->error=ERR_R_BUF_LIB;
309                         goto err;
310                         }
311                 memcpy(&(b.data[num]),os->data,os->length);
312                 if (!(c->inf & 1))
313                         c->slen-=(c->p-c->q);
314                 num+=os->length;
315                 }
316
317         if (!asn1_Finish(c)) goto err;
318
319         a->length=num;
320         if (a->data != NULL) OPENSSL_free(a->data);
321         a->data=(unsigned char *)b.data;
322         if (os != NULL) ASN1_STRING_free(os);
323         return(1);
324 err:
325         ASN1err(ASN1_F_ASN1_COLLATE_PRIMITIVE,c->error);
326         if (os != NULL) ASN1_STRING_free(os);
327         if (b.data != NULL) OPENSSL_free(b.data);
328         return(0);
329         }
330