OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
asn1_lib.c
Go to the documentation of this file.
1 /* crypto/asn1/asn1_lib.c */
2 /* Copyright (C) 1995-1998 Eric Young ([email protected])
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young ([email protected]).
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 ([email protected]).
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 ([email protected])"
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 ([email protected])"
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/asn1.h>
63 #include <openssl/asn1_mac.h>
64 
65 static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
66 static void asn1_put_length(unsigned char **pp, int length);
67 const char ASN1_version[]="ASN.1" OPENSSL_VERSION_PTEXT;
68 
69 static int _asn1_check_infinite_end(const unsigned char **p, long len)
70  {
71  /* If there is 0 or 1 byte left, the length check should pick
72  * things up */
73  if (len <= 0)
74  return(1);
75  else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
76  {
77  (*p)+=2;
78  return(1);
79  }
80  return(0);
81  }
82 
83 int ASN1_check_infinite_end(unsigned char **p, long len)
84  {
85  return _asn1_check_infinite_end((const unsigned char **)p, len);
86  }
87 
88 int ASN1_const_check_infinite_end(const unsigned char **p, long len)
89  {
90  return _asn1_check_infinite_end(p, len);
91  }
92 
93 
94 int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
95  int *pclass, long omax)
96  {
97  int i,ret;
98  long l;
99  const unsigned char *p= *pp;
100  int tag,xclass,inf;
101  long max=omax;
102 
103  if (!max) goto err;
104  ret=(*p&V_ASN1_CONSTRUCTED);
105  xclass=(*p&V_ASN1_PRIVATE);
106  i= *p&V_ASN1_PRIMITIVE_TAG;
107  if (i == V_ASN1_PRIMITIVE_TAG)
108  { /* high-tag */
109  p++;
110  if (--max == 0) goto err;
111  l=0;
112  while (*p&0x80)
113  {
114  l<<=7L;
115  l|= *(p++)&0x7f;
116  if (--max == 0) goto err;
117  if (l > (INT_MAX >> 7L)) goto err;
118  }
119  l<<=7L;
120  l|= *(p++)&0x7f;
121  tag=(int)l;
122  if (--max == 0) goto err;
123  }
124  else
125  {
126  tag=i;
127  p++;
128  if (--max == 0) goto err;
129  }
130  *ptag=tag;
131  *pclass=xclass;
132  if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
133 
134 #if 0
135  fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
136  (int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
137  (int)(omax+ *pp));
138 
139 #endif
140  if (*plength > (omax - (p - *pp)))
141  {
143  /* Set this so that even if things are not long enough
144  * the values are set correctly */
145  ret|=0x80;
146  }
147  *pp=p;
148  return(ret|inf);
149 err:
151  return(0x80);
152  }
153 
154 static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
155  {
156  const unsigned char *p= *pp;
157  unsigned long ret=0;
158  unsigned int i;
159 
160  if (max-- < 1) return(0);
161  if (*p == 0x80)
162  {
163  *inf=1;
164  ret=0;
165  p++;
166  }
167  else
168  {
169  *inf=0;
170  i= *p&0x7f;
171  if (*(p++) & 0x80)
172  {
173  if (i > sizeof(long))
174  return 0;
175  if (max-- == 0) return(0);
176  while (i-- > 0)
177  {
178  ret<<=8L;
179  ret|= *(p++);
180  if (max-- == 0) return(0);
181  }
182  }
183  else
184  ret=i;
185  }
186  if (ret > LONG_MAX)
187  return 0;
188  *pp=p;
189  *rl=(long)ret;
190  return(1);
191  }
192 
193 /* class 0 is constructed
194  * constructed == 2 for indefinite length constructed */
195 void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
196  int xclass)
197  {
198  unsigned char *p= *pp;
199  int i, ttag;
200 
201  i=(constructed)?V_ASN1_CONSTRUCTED:0;
202  i|=(xclass&V_ASN1_PRIVATE);
203  if (tag < 31)
204  *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
205  else
206  {
207  *(p++)=i|V_ASN1_PRIMITIVE_TAG;
208  for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
209  ttag = i;
210  while(i-- > 0)
211  {
212  p[i] = tag & 0x7f;
213  if(i != (ttag - 1)) p[i] |= 0x80;
214  tag >>= 7;
215  }
216  p += ttag;
217  }
218  if (constructed == 2)
219  *(p++)=0x80;
220  else
221  asn1_put_length(&p,length);
222  *pp=p;
223  }
224 
225 int ASN1_put_eoc(unsigned char **pp)
226  {
227  unsigned char *p = *pp;
228  *p++ = 0;
229  *p++ = 0;
230  *pp = p;
231  return 2;
232  }
233 
234 static void asn1_put_length(unsigned char **pp, int length)
235  {
236  unsigned char *p= *pp;
237  int i,l;
238  if (length <= 127)
239  *(p++)=(unsigned char)length;
240  else
241  {
242  l=length;
243  for (i=0; l > 0; i++)
244  l>>=8;
245  *(p++)=i|0x80;
246  l=i;
247  while (i-- > 0)
248  {
249  p[i]=length&0xff;
250  length>>=8;
251  }
252  p+=l;
253  }
254  *pp=p;
255  }
256 
257 int ASN1_object_size(int constructed, int length, int tag)
258  {
259  int ret;
260 
261  ret=length;
262  ret++;
263  if (tag >= 31)
264  {
265  while (tag > 0)
266  {
267  tag>>=7;
268  ret++;
269  }
270  }
271  if (constructed == 2)
272  return ret + 3;
273  ret++;
274  if (length > 127)
275  {
276  while (length > 0)
277  {
278  length>>=8;
279  ret++;
280  }
281  }
282  return(ret);
283  }
284 
285 static int _asn1_Finish(ASN1_const_CTX *c)
286  {
287  if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
288  {
289  if (!ASN1_const_check_infinite_end(&c->p,c->slen))
290  {
292  return(0);
293  }
294  }
295  if ( ((c->slen != 0) && !(c->inf & 1)) ||
296  ((c->slen < 0) && (c->inf & 1)))
297  {
299  return(0);
300  }
301  return(1);
302  }
303 
305  {
306  return _asn1_Finish((ASN1_const_CTX *)c);
307  }
308 
310  {
311  return _asn1_Finish(c);
312  }
313 
314 int asn1_GetSequence(ASN1_const_CTX *c, long *length)
315  {
316  const unsigned char *q;
317 
318  q=c->p;
319  c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
320  *length);
321  if (c->inf & 0x80)
322  {
324  return(0);
325  }
326  if (c->tag != V_ASN1_SEQUENCE)
327  {
329  return(0);
330  }
331  (*length)-=(c->p-q);
332  if (c->max && (*length < 0))
333  {
335  return(0);
336  }
337  if (c->inf == (1|V_ASN1_CONSTRUCTED))
338  c->slen= *length+ *(c->pp)-c->p;
339  c->eos=0;
340  return(1);
341  }
342 
344  {
345  if (str == NULL)
346  return 0;
347  dst->type = str->type;
348  if (!ASN1_STRING_set(dst,str->data,str->length))
349  return 0;
350  dst->flags = str->flags;
351  return 1;
352  }
353 
355  {
356  ASN1_STRING *ret;
357  if (!str)
358  return NULL;
359  ret=ASN1_STRING_new();
360  if (!ret)
361  return NULL;
362  if (!ASN1_STRING_copy(ret,str))
363  {
364  ASN1_STRING_free(ret);
365  return NULL;
366  }
367  return ret;
368  }
369 
370 int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
371  {
372  unsigned char *c;
373  const char *data=_data;
374 
375  if (len < 0)
376  {
377  if (data == NULL)
378  return(0);
379  else
380  len=strlen(data);
381  }
382  if ((str->length < len) || (str->data == NULL))
383  {
384  c=str->data;
385  if (c == NULL)
386  str->data=OPENSSL_malloc(len+1);
387  else
388  str->data=OPENSSL_realloc(c,len+1);
389 
390  if (str->data == NULL)
391  {
393  str->data=c;
394  return(0);
395  }
396  }
397  str->length=len;
398  if (data != NULL)
399  {
400  memcpy(str->data,data,len);
401  /* an allowance for strings :-) */
402  str->data[len]='\0';
403  }
404  return(1);
405  }
406 
407 void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
408  {
409  if (str->data)
410  OPENSSL_free(str->data);
411  str->data = data;
412  str->length = len;
413  }
414 
416  {
418  }
419 
420 
422  {
423  ASN1_STRING *ret;
424 
425  ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
426  if (ret == NULL)
427  {
429  return(NULL);
430  }
431  ret->length=0;
432  ret->type=type;
433  ret->data=NULL;
434  ret->flags=0;
435  return(ret);
436  }
437 
439  {
440  if (a == NULL) return;
441  if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
442  OPENSSL_free(a->data);
443  OPENSSL_free(a);
444  }
445 
447  {
448  int i;
449 
450  i=(a->length-b->length);
451  if (i == 0)
452  {
453  i=memcmp(a->data,b->data,a->length);
454  if (i == 0)
455  return(a->type-b->type);
456  else
457  return(i);
458  }
459  else
460  return(i);
461  }
462 
463 void asn1_add_error(const unsigned char *address, int offset)
464  {
465  char buf1[DECIMAL_SIZE(address)+1],buf2[DECIMAL_SIZE(offset)+1];
466 
467  BIO_snprintf(buf1,sizeof buf1,"%lu",(unsigned long)address);
468  BIO_snprintf(buf2,sizeof buf2,"%d",offset);
469  ERR_add_error_data(4,"address=",buf1," offset=",buf2);
470  }
471 
473 { return M_ASN1_STRING_length(x); }
474 
476 { M_ASN1_STRING_length_set(x, len); return; }
477 
479 { return M_ASN1_STRING_type(x); }
480 
481 unsigned char * ASN1_STRING_data(ASN1_STRING *x)
482 { return M_ASN1_STRING_data(x); }