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