More size_tification.
[openssl.git] / crypto / asn1 / a_object.c
1 /* crypto/asn1/a_object.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 <limits.h>
61 #include "cryptlib.h"
62 #include <openssl/buffer.h>
63 #include <openssl/asn1.h>
64 #include <openssl/objects.h>
65 #include <openssl/bn.h>
66
67 int i2d_ASN1_OBJECT(ASN1_OBJECT *a, unsigned char **pp)
68         {
69         unsigned char *p;
70         int objsize;
71
72         if ((a == NULL) || (a->data == NULL)) return(0);
73
74         objsize = ASN1_object_size(0,a->length,V_ASN1_OBJECT);
75         if (pp == NULL) return objsize;
76
77         p= *pp;
78         ASN1_put_object(&p,0,a->length,V_ASN1_OBJECT,V_ASN1_UNIVERSAL);
79         memcpy(p,a->data,a->length);
80         p+=a->length;
81
82         *pp=p;
83         return(objsize);
84         }
85
86 size_t a2d_ASN1_OBJECT(unsigned char *out, size_t olen, const char *buf,
87                        int num)
88         {
89         int i,len=0,c, use_bn;
90         unsigned first;
91         char ftmp[24], *tmp = ftmp;
92         size_t tmpsize = sizeof ftmp;
93         const char *p;
94         unsigned long l;
95         BIGNUM *bl = NULL;
96
97         if (num == 0)
98                 return(0);
99         else if (num == -1)
100                 num=strlen(buf);
101
102         p=buf;
103         c= *(p++);
104         num--;
105         if ((c >= '0') && (c <= '2'))
106                 {
107                 first= c-'0';
108                 }
109         else
110                 {
111                 ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_FIRST_NUM_TOO_LARGE);
112                 goto err;
113                 }
114
115         if (num <= 0)
116                 {
117                 ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_MISSING_SECOND_NUMBER);
118                 goto err;
119                 }
120         c= *(p++);
121         num--;
122         for (;;)
123                 {
124                 if (num <= 0) break;
125                 if ((c != '.') && (c != ' '))
126                         {
127                         ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_INVALID_SEPARATOR);
128                         goto err;
129                         }
130                 l=0;
131                 use_bn = 0;
132                 for (;;)
133                         {
134                         if (num <= 0) break;
135                         num--;
136                         c= *(p++);
137                         if ((c == ' ') || (c == '.'))
138                                 break;
139                         if ((c < '0') || (c > '9'))
140                                 {
141                                 ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_INVALID_DIGIT);
142                                 goto err;
143                                 }
144                         if (!use_bn && l > (ULONG_MAX / 10L))
145                                 {
146                                 use_bn = 1;
147                                 if (!bl)
148                                         bl = BN_new();
149                                 if (!bl || !BN_set_word(bl, l))
150                                         goto err;
151                                 }
152                         if (use_bn)
153                                 {
154                                 if (!BN_mul_word(bl, 10L)
155                                     || !BN_add_signed_word(bl, c-'0'))
156                                         goto err;
157                                 }
158                         else
159                                 l=l*10L+(c-'0');
160                         }
161                 if (len == 0)
162                         {
163                         if ((first < 2) && (l >= 40))
164                                 {
165                                 ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_SECOND_NUMBER_TOO_LARGE);
166                                 goto err;
167                                 }
168                         if (use_bn)
169                                 {
170                                 if (!BN_add_word(bl, first * 40))
171                                         goto err;
172                                 }
173                         else
174                                 l+=(long)first*40;
175                         }
176                 i=0;
177                 if (use_bn)
178                         {
179                         int blsize;
180                         blsize = BN_num_bits(bl);
181                         blsize = (blsize + 6)/7;
182                         if (blsize > tmpsize)
183                                 {
184                                 if (tmp != ftmp)
185                                         OPENSSL_free(tmp);
186                                 tmpsize = blsize + 32;
187                                 tmp = OPENSSL_malloc(tmpsize);
188                                 if (!tmp)
189                                         goto err;
190                                 }
191                         while(blsize--)
192                                 tmp[i++] = (unsigned char)BN_div_word(bl, 0x80L);
193                         }
194                 else
195                         {
196                                         
197                         for (;;)
198                                 {
199                                 tmp[i++]=(unsigned char)l&0x7f;
200                                 l>>=7L;
201                                 if (l == 0L) break;
202                                 }
203
204                         }
205                 if (out != NULL)
206                         {
207                         if (len+i > olen)
208                                 {
209                                 ASN1err(ASN1_F_A2D_ASN1_OBJECT,ASN1_R_BUFFER_TOO_SMALL);
210                                 goto err;
211                                 }
212                         while (--i > 0)
213                                 out[len++]=tmp[i]|0x80;
214                         out[len++]=tmp[0];
215                         }
216                 else
217                         len+=i;
218                 }
219         if (tmp != ftmp)
220                 OPENSSL_free(tmp);
221         if (bl)
222                 BN_free(bl);
223         return(len);
224 err:
225         if (tmp != ftmp)
226                 OPENSSL_free(tmp);
227         if (bl)
228                 BN_free(bl);
229         return(0);
230         }
231
232 int i2t_ASN1_OBJECT(char *buf, size_t buf_len, ASN1_OBJECT *a)
233 {
234         return OBJ_obj2txt(buf, buf_len, a, 0);
235 }
236
237 int i2a_ASN1_OBJECT(BIO *bp, ASN1_OBJECT *a)
238         {
239         char buf[80], *p = buf;
240         size_t i;
241
242         if ((a == NULL) || (a->data == NULL))
243                 return(BIO_write(bp,"NULL",4));
244         i=i2t_ASN1_OBJECT(buf,sizeof buf,a);
245         if (i > (int)(sizeof(buf) - 1))
246                 {
247                 p = OPENSSL_malloc(i + 1);
248                 if (!p)
249                         return -1;
250                 i2t_ASN1_OBJECT(p,i + 1,a);
251                 }
252         if (i <= 0)
253                 return BIO_write(bp, "<INVALID>", 9);
254         BIO_write(bp,p,i);
255         if (p != buf)
256                 OPENSSL_free(p);
257         return(i);
258         }
259
260 ASN1_OBJECT *d2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
261                              size_t length)
262 {
263         const unsigned char *p;
264         size_t len;
265         int tag,xclass;
266         int inf,i;
267         ASN1_OBJECT *ret = NULL;
268
269         p= *pp;
270         inf=ASN1_get_object(&p,&len,&tag,&xclass,length);
271         if (inf & 0x80)
272                 {
273                 i=ASN1_R_BAD_OBJECT_HEADER;
274                 goto err;
275                 }
276
277         if (tag != V_ASN1_OBJECT)
278                 {
279                 i=ASN1_R_EXPECTING_AN_OBJECT;
280                 goto err;
281                 }
282         ret = c2i_ASN1_OBJECT(a, &p, len);
283         if(ret) *pp = p;
284         return ret;
285 err:
286         ASN1err(ASN1_F_D2I_ASN1_OBJECT,i);
287         return(NULL);
288 }
289 ASN1_OBJECT *c2i_ASN1_OBJECT(ASN1_OBJECT **a, const unsigned char **pp,
290                              size_t len)
291         {
292         ASN1_OBJECT *ret=NULL;
293         const unsigned char *p;
294         unsigned char *data;
295         int i;
296
297         /* only the ASN1_OBJECTs from the 'table' will have values
298          * for ->sn or ->ln */
299         if ((a == NULL) || ((*a) == NULL) ||
300                 !((*a)->flags & ASN1_OBJECT_FLAG_DYNAMIC))
301                 {
302                 if ((ret=ASN1_OBJECT_new()) == NULL) return(NULL);
303                 }
304         else    ret=(*a);
305
306         p= *pp;
307         /* detach data from object */
308         data = (unsigned char *)ret->data;
309         ret->data = NULL;
310         /* once detached we can change it */
311         if ((data == NULL) || (ret->length < len))
312                 {
313                 ret->length=0;
314                 if (data != NULL) OPENSSL_free(data);
315                 data=OPENSSL_malloc(len ? len : 1);
316                 if (data == NULL)
317                         { i=ERR_R_MALLOC_FAILURE; goto err; }
318                 ret->flags|=ASN1_OBJECT_FLAG_DYNAMIC_DATA;
319                 }
320         memcpy(data,p,len);
321         /* reattach data to object, after which it remains const */
322         ret->data=data;
323         ret->length=len;
324         ret->sn=NULL;
325         ret->ln=NULL;
326         /* ret->flags=ASN1_OBJECT_FLAG_DYNAMIC; we know it is dynamic */
327         p+=len;
328
329         if (a != NULL) (*a)=ret;
330         *pp=p;
331         return(ret);
332 err:
333         ASN1err(ASN1_F_C2I_ASN1_OBJECT,i);
334         if ((ret != NULL) && ((a == NULL) || (*a != ret)))
335                 ASN1_OBJECT_free(ret);
336         return(NULL);
337         }
338
339 ASN1_OBJECT *ASN1_OBJECT_new(void)
340         {
341         ASN1_OBJECT *ret;
342
343         ret=(ASN1_OBJECT *)OPENSSL_malloc(sizeof(ASN1_OBJECT));
344         if (ret == NULL)
345                 {
346                 ASN1err(ASN1_F_ASN1_OBJECT_NEW,ERR_R_MALLOC_FAILURE);
347                 return(NULL);
348                 }
349         ret->length=0;
350         ret->data=NULL;
351         ret->nid=0;
352         ret->sn=NULL;
353         ret->ln=NULL;
354         ret->flags=ASN1_OBJECT_FLAG_DYNAMIC;
355         return(ret);
356         }
357
358 void ASN1_OBJECT_free(ASN1_OBJECT *a)
359         {
360         if (a == NULL) return;
361         if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_STRINGS)
362                 {
363 #ifndef CONST_STRICT /* disable purely for compile-time strict const checking. Doing this on a "real" compile will cause memory leaks */
364                 if (a->sn != NULL) OPENSSL_free((void *)a->sn);
365                 if (a->ln != NULL) OPENSSL_free((void *)a->ln);
366 #endif
367                 a->sn=a->ln=NULL;
368                 }
369         if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC_DATA)
370                 {
371                 if (a->data != NULL) OPENSSL_free((void *)a->data);
372                 a->data=NULL;
373                 a->length=0;
374                 }
375         if (a->flags & ASN1_OBJECT_FLAG_DYNAMIC)
376                 OPENSSL_free(a);
377         }
378
379 ASN1_OBJECT *ASN1_OBJECT_create(int nid, unsigned char *data, size_t len,
380              const char *sn, const char *ln)
381         {
382         ASN1_OBJECT o;
383
384         o.sn=sn;
385         o.ln=ln;
386         o.data=data;
387         o.nid=nid;
388         o.length=len;
389         o.flags=ASN1_OBJECT_FLAG_DYNAMIC|ASN1_OBJECT_FLAG_DYNAMIC_STRINGS|
390                 ASN1_OBJECT_FLAG_DYNAMIC_DATA;
391         return(OBJ_dup(&o));
392         }
393
394 IMPLEMENT_STACK_OF(ASN1_OBJECT)
395 IMPLEMENT_ASN1_SET_OF(ASN1_OBJECT)