blob: a109749f41390d0aa78b9a04c82d9d4ffe547757 [file] [log] [blame]
Adam Langleyd9e397b2015-01-22 14:27:53 -08001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
57#include <openssl/asn1.h>
58
59#include <limits.h>
60#include <string.h>
61
62#include <openssl/asn1_mac.h>
63#include <openssl/err.h>
64#include <openssl/mem.h>
65
Adam Langleye9ada862015-05-11 17:20:37 -070066
67/* Used in asn1_mac.h.
68 * TODO(davidben): Remove this once asn1_mac.h is gone or trimmed. */
Adam Langleyd9e397b2015-01-22 14:27:53 -080069OPENSSL_DECLARE_ERROR_REASON(ASN1, MALLOC_FAILURE);
70
Adam Langleye9ada862015-05-11 17:20:37 -070071/* Cross-module errors from crypto/x509/i2d_pr.c */
Adam Langleye9ada862015-05-11 17:20:37 -070072OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE);
73
74/* Cross-module errors from crypto/x509/asn1_gen.c.
75 * TODO(davidben): Remove these once asn1_gen.c is gone. */
Adam Langleye9ada862015-05-11 17:20:37 -070076OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED);
77OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT);
78OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN);
79OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT);
80OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX);
81OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG);
82OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER);
83OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING);
84OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE);
85OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT);
86OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE);
87OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT);
88OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER);
89OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER);
90OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR);
91OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE);
92OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT);
93OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT);
94OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG);
95OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT);
96OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT);
97OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG);
98OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE);
Adam Langleyd9e397b2015-01-22 14:27:53 -080099
100static int asn1_get_length(const unsigned char **pp,int *inf,long *rl,int max);
101static void asn1_put_length(unsigned char **pp, int length);
102
103static int _asn1_check_infinite_end(const unsigned char **p, long len)
104 {
105 /* If there is 0 or 1 byte left, the length check should pick
106 * things up */
107 if (len <= 0)
108 return(1);
109 else if ((len >= 2) && ((*p)[0] == 0) && ((*p)[1] == 0))
110 {
111 (*p)+=2;
112 return(1);
113 }
114 return(0);
115 }
116
117int ASN1_check_infinite_end(unsigned char **p, long len)
118 {
119 return _asn1_check_infinite_end((const unsigned char **)p, len);
120 }
121
122int ASN1_const_check_infinite_end(const unsigned char **p, long len)
123 {
124 return _asn1_check_infinite_end(p, len);
125 }
126
127
128int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag,
129 int *pclass, long omax)
130 {
131 int i,ret;
132 long l;
133 const unsigned char *p= *pp;
134 int tag,xclass,inf;
135 long max=omax;
136
137 if (!max) goto err;
138 ret=(*p&V_ASN1_CONSTRUCTED);
139 xclass=(*p&V_ASN1_PRIVATE);
140 i= *p&V_ASN1_PRIMITIVE_TAG;
141 if (i == V_ASN1_PRIMITIVE_TAG)
142 { /* high-tag */
143 p++;
144 if (--max == 0) goto err;
145 l=0;
146 while (*p&0x80)
147 {
148 l<<=7L;
149 l|= *(p++)&0x7f;
150 if (--max == 0) goto err;
151 if (l > (INT_MAX >> 7L)) goto err;
152 }
153 l<<=7L;
154 l|= *(p++)&0x7f;
155 tag=(int)l;
156 if (--max == 0) goto err;
157 }
158 else
159 {
160 tag=i;
161 p++;
162 if (--max == 0) goto err;
163 }
164 *ptag=tag;
165 *pclass=xclass;
166 if (!asn1_get_length(&p,&inf,plength,(int)max)) goto err;
167
168 if (inf && !(ret & V_ASN1_CONSTRUCTED))
169 goto err;
170
171#if 0
172 fprintf(stderr,"p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n",
173 (int)p,*plength,omax,(int)*pp,(int)(p+ *plength),
174 (int)(omax+ *pp));
175
176#endif
177 if (*plength > (omax - (p - *pp)))
178 {
Kenny Rootb8494592015-09-25 02:29:14 +0000179 OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800180 /* Set this so that even if things are not long enough
181 * the values are set correctly */
182 ret|=0x80;
183 }
184 *pp=p;
185 return(ret|inf);
186err:
Kenny Rootb8494592015-09-25 02:29:14 +0000187 OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800188 return(0x80);
189 }
190
191static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, int max)
192 {
193 const unsigned char *p= *pp;
194 unsigned long ret=0;
195 unsigned int i;
196
197 if (max-- < 1) return(0);
198 if (*p == 0x80)
199 {
200 *inf=1;
201 ret=0;
202 p++;
203 }
204 else
205 {
206 *inf=0;
207 i= *p&0x7f;
208 if (*(p++) & 0x80)
209 {
210 if (i > sizeof(long))
211 return 0;
212 if (max-- == 0) return(0);
213 while (i-- > 0)
214 {
215 ret<<=8L;
216 ret|= *(p++);
217 if (max-- == 0) return(0);
218 }
219 }
220 else
221 ret=i;
222 }
223 if (ret > LONG_MAX)
224 return 0;
225 *pp=p;
226 *rl=(long)ret;
227 return(1);
228 }
229
230/* class 0 is constructed
231 * constructed == 2 for indefinite length constructed */
232void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag,
233 int xclass)
234 {
235 unsigned char *p= *pp;
236 int i, ttag;
237
238 i=(constructed)?V_ASN1_CONSTRUCTED:0;
239 i|=(xclass&V_ASN1_PRIVATE);
240 if (tag < 31)
241 *(p++)=i|(tag&V_ASN1_PRIMITIVE_TAG);
242 else
243 {
244 *(p++)=i|V_ASN1_PRIMITIVE_TAG;
245 for(i = 0, ttag = tag; ttag > 0; i++) ttag >>=7;
246 ttag = i;
247 while(i-- > 0)
248 {
249 p[i] = tag & 0x7f;
250 if(i != (ttag - 1)) p[i] |= 0x80;
251 tag >>= 7;
252 }
253 p += ttag;
254 }
255 if (constructed == 2)
256 *(p++)=0x80;
257 else
258 asn1_put_length(&p,length);
259 *pp=p;
260 }
261
262int ASN1_put_eoc(unsigned char **pp)
263 {
264 unsigned char *p = *pp;
265 *p++ = 0;
266 *p++ = 0;
267 *pp = p;
268 return 2;
269 }
270
271static void asn1_put_length(unsigned char **pp, int length)
272 {
273 unsigned char *p= *pp;
274 int i,l;
275 if (length <= 127)
276 *(p++)=(unsigned char)length;
277 else
278 {
279 l=length;
280 for (i=0; l > 0; i++)
281 l>>=8;
282 *(p++)=i|0x80;
283 l=i;
284 while (i-- > 0)
285 {
286 p[i]=length&0xff;
287 length>>=8;
288 }
289 p+=l;
290 }
291 *pp=p;
292 }
293
294int ASN1_object_size(int constructed, int length, int tag)
295 {
296 int ret;
297
298 ret=length;
299 ret++;
300 if (tag >= 31)
301 {
302 while (tag > 0)
303 {
304 tag>>=7;
305 ret++;
306 }
307 }
308 if (constructed == 2)
309 return ret + 3;
310 ret++;
311 if (length > 127)
312 {
313 while (length > 0)
314 {
315 length>>=8;
316 ret++;
317 }
318 }
319 return(ret);
320 }
321
322static int _asn1_Finish(ASN1_const_CTX *c)
323 {
324 if ((c->inf == (1|V_ASN1_CONSTRUCTED)) && (!c->eos))
325 {
326 if (!ASN1_const_check_infinite_end(&c->p,c->slen))
327 {
328 c->error=ASN1_R_MISSING_ASN1_EOS;
329 return(0);
330 }
331 }
332 if ( ((c->slen != 0) && !(c->inf & 1)) ||
333 ((c->slen < 0) && (c->inf & 1)))
334 {
335 c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
336 return(0);
337 }
338 return(1);
339 }
340
341int asn1_Finish(ASN1_CTX *c)
342 {
343 return _asn1_Finish((ASN1_const_CTX *)c);
344 }
345
346int asn1_const_Finish(ASN1_const_CTX *c)
347 {
348 return _asn1_Finish(c);
349 }
350
351int asn1_GetSequence(ASN1_const_CTX *c, long *length)
352 {
353 const unsigned char *q;
354
355 q=c->p;
356 c->inf=ASN1_get_object(&(c->p),&(c->slen),&(c->tag),&(c->xclass),
357 *length);
358 if (c->inf & 0x80)
359 {
360 c->error=ASN1_R_BAD_GET_ASN1_OBJECT_CALL;
361 return(0);
362 }
363 if (c->tag != V_ASN1_SEQUENCE)
364 {
365 c->error=ASN1_R_EXPECTING_AN_ASN1_SEQUENCE;
366 return(0);
367 }
368 (*length)-=(c->p-q);
369 if (c->max && (*length < 0))
370 {
371 c->error=ASN1_R_ASN1_LENGTH_MISMATCH;
372 return(0);
373 }
374 if (c->inf == (1|V_ASN1_CONSTRUCTED))
375 c->slen= *length+ *(c->pp)-c->p;
376 c->eos=0;
377 return(1);
378 }
379
380int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str)
381 {
382 if (str == NULL)
383 return 0;
384 dst->type = str->type;
385 if (!ASN1_STRING_set(dst,str->data,str->length))
386 return 0;
387 dst->flags = str->flags;
388 return 1;
389 }
390
391ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str)
392 {
393 ASN1_STRING *ret;
394 if (!str)
395 return NULL;
396 ret=ASN1_STRING_new();
397 if (!ret)
398 return NULL;
399 if (!ASN1_STRING_copy(ret,str))
400 {
401 ASN1_STRING_free(ret);
402 return NULL;
403 }
404 return ret;
405 }
406
407int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len)
408 {
409 unsigned char *c;
410 const char *data=_data;
411
412 if (len < 0)
413 {
414 if (data == NULL)
415 return(0);
416 else
417 len=strlen(data);
418 }
419 if ((str->length < len) || (str->data == NULL))
420 {
421 c=str->data;
422 if (c == NULL)
423 str->data=OPENSSL_malloc(len+1);
424 else
425 str->data=OPENSSL_realloc(c,len+1);
426
427 if (str->data == NULL)
428 {
Kenny Rootb8494592015-09-25 02:29:14 +0000429 OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800430 str->data=c;
431 return(0);
432 }
433 }
434 str->length=len;
435 if (data != NULL)
436 {
437 memcpy(str->data,data,len);
438 /* an allowance for strings :-) */
439 str->data[len]='\0';
440 }
441 return(1);
442 }
443
444void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len)
445 {
446 if (str->data)
447 OPENSSL_free(str->data);
448 str->data = data;
449 str->length = len;
450 }
451
452ASN1_STRING *ASN1_STRING_new(void)
453 {
454 return(ASN1_STRING_type_new(V_ASN1_OCTET_STRING));
455 }
456
457
458ASN1_STRING *ASN1_STRING_type_new(int type)
459 {
460 ASN1_STRING *ret;
461
462 ret=(ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING));
463 if (ret == NULL)
464 {
Kenny Rootb8494592015-09-25 02:29:14 +0000465 OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE);
Adam Langleyd9e397b2015-01-22 14:27:53 -0800466 return(NULL);
467 }
468 ret->length=0;
469 ret->type=type;
470 ret->data=NULL;
471 ret->flags=0;
472 return(ret);
473 }
474
475void ASN1_STRING_free(ASN1_STRING *a)
476 {
477 if (a == NULL) return;
478 if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF))
479 OPENSSL_free(a->data);
480 OPENSSL_free(a);
481 }
482
483int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b)
484 {
485 int i;
486
487 i=(a->length-b->length);
488 if (i == 0)
489 {
490 i=memcmp(a->data,b->data,a->length);
491 if (i == 0)
492 return(a->type-b->type);
493 else
494 return(i);
495 }
496 else
497 return(i);
498 }
499
Adam Langleyd9e397b2015-01-22 14:27:53 -0800500int ASN1_STRING_length(const ASN1_STRING *x)
501{ return M_ASN1_STRING_length(x); }
502
503void ASN1_STRING_length_set(ASN1_STRING *x, int len)
504{ M_ASN1_STRING_length_set(x, len); return; }
505
506int ASN1_STRING_type(ASN1_STRING *x)
507{ return M_ASN1_STRING_type(x); }
508
509unsigned char * ASN1_STRING_data(ASN1_STRING *x)
510{ return M_ASN1_STRING_data(x); }