1 | /* 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 | |
66 | #include "../internal.h" |
67 | |
68 | |
69 | /* Cross-module errors from crypto/x509/i2d_pr.c. */ |
70 | OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_PUBLIC_KEY_TYPE) |
71 | |
72 | /* Cross-module errors from crypto/x509/algorithm.c. */ |
73 | OPENSSL_DECLARE_ERROR_REASON(ASN1, CONTEXT_NOT_INITIALISED) |
74 | OPENSSL_DECLARE_ERROR_REASON(ASN1, DIGEST_AND_KEY_TYPE_NOT_SUPPORTED) |
75 | OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_MESSAGE_DIGEST_ALGORITHM) |
76 | OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_SIGNATURE_ALGORITHM) |
77 | OPENSSL_DECLARE_ERROR_REASON(ASN1, WRONG_PUBLIC_KEY_TYPE) |
78 | /* |
79 | * Cross-module errors from crypto/x509/asn1_gen.c. TODO(davidben): Remove |
80 | * these once asn1_gen.c is gone. |
81 | */ |
82 | OPENSSL_DECLARE_ERROR_REASON(ASN1, DEPTH_EXCEEDED) |
83 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BITSTRING_FORMAT) |
84 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_BOOLEAN) |
85 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_FORMAT) |
86 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_HEX) |
87 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_IMPLICIT_TAG) |
88 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_INTEGER) |
89 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NESTED_TAGGING) |
90 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_NULL_VALUE) |
91 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_OBJECT) |
92 | OPENSSL_DECLARE_ERROR_REASON(ASN1, ILLEGAL_TIME_VALUE) |
93 | OPENSSL_DECLARE_ERROR_REASON(ASN1, INTEGER_NOT_ASCII_FORMAT) |
94 | OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_MODIFIER) |
95 | OPENSSL_DECLARE_ERROR_REASON(ASN1, INVALID_NUMBER) |
96 | OPENSSL_DECLARE_ERROR_REASON(ASN1, LIST_ERROR) |
97 | OPENSSL_DECLARE_ERROR_REASON(ASN1, MISSING_VALUE) |
98 | OPENSSL_DECLARE_ERROR_REASON(ASN1, NOT_ASCII_FORMAT) |
99 | OPENSSL_DECLARE_ERROR_REASON(ASN1, OBJECT_NOT_ASCII_FORMAT) |
100 | OPENSSL_DECLARE_ERROR_REASON(ASN1, SEQUENCE_OR_SET_NEEDS_CONFIG) |
101 | OPENSSL_DECLARE_ERROR_REASON(ASN1, TIME_NOT_ASCII_FORMAT) |
102 | OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_FORMAT) |
103 | OPENSSL_DECLARE_ERROR_REASON(ASN1, UNKNOWN_TAG) |
104 | OPENSSL_DECLARE_ERROR_REASON(ASN1, UNSUPPORTED_TYPE) |
105 | |
106 | static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, |
107 | long max); |
108 | static void asn1_put_length(unsigned char **pp, int length); |
109 | |
110 | int ASN1_get_object(const unsigned char **pp, long *plength, int *ptag, |
111 | int *pclass, long omax) |
112 | { |
113 | int i, ret; |
114 | long l; |
115 | const unsigned char *p = *pp; |
116 | int tag, xclass, inf; |
117 | long max = omax; |
118 | |
119 | if (!max) |
120 | goto err; |
121 | ret = (*p & V_ASN1_CONSTRUCTED); |
122 | xclass = (*p & V_ASN1_PRIVATE); |
123 | i = *p & V_ASN1_PRIMITIVE_TAG; |
124 | if (i == V_ASN1_PRIMITIVE_TAG) { /* high-tag */ |
125 | p++; |
126 | if (--max == 0) |
127 | goto err; |
128 | l = 0; |
129 | while (*p & 0x80) { |
130 | l <<= 7L; |
131 | l |= *(p++) & 0x7f; |
132 | if (--max == 0) |
133 | goto err; |
134 | if (l > (INT_MAX >> 7L)) |
135 | goto err; |
136 | } |
137 | l <<= 7L; |
138 | l |= *(p++) & 0x7f; |
139 | tag = (int)l; |
140 | if (--max == 0) |
141 | goto err; |
142 | } else { |
143 | tag = i; |
144 | p++; |
145 | if (--max == 0) |
146 | goto err; |
147 | } |
148 | |
149 | /* To avoid ambiguity with V_ASN1_NEG, impose a limit on universal tags. */ |
150 | if (xclass == V_ASN1_UNIVERSAL && tag > V_ASN1_MAX_UNIVERSAL) |
151 | goto err; |
152 | |
153 | *ptag = tag; |
154 | *pclass = xclass; |
155 | if (!asn1_get_length(&p, &inf, plength, max)) |
156 | goto err; |
157 | |
158 | if (inf && !(ret & V_ASN1_CONSTRUCTED)) |
159 | goto err; |
160 | |
161 | #if 0 |
162 | fprintf(stderr, "p=%d + *plength=%ld > omax=%ld + *pp=%d (%d > %d)\n" , |
163 | (int)p, *plength, omax, (int)*pp, (int)(p + *plength), |
164 | (int)(omax + *pp)); |
165 | |
166 | #endif |
167 | if (*plength > (omax - (p - *pp))) { |
168 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_TOO_LONG); |
169 | /* |
170 | * Set this so that even if things are not long enough the values are |
171 | * set correctly |
172 | */ |
173 | ret |= 0x80; |
174 | } |
175 | *pp = p; |
176 | return (ret | inf); |
177 | err: |
178 | OPENSSL_PUT_ERROR(ASN1, ASN1_R_HEADER_TOO_LONG); |
179 | return (0x80); |
180 | } |
181 | |
182 | static int asn1_get_length(const unsigned char **pp, int *inf, long *rl, |
183 | long max) |
184 | { |
185 | const unsigned char *p = *pp; |
186 | unsigned long ret = 0; |
187 | unsigned long i; |
188 | |
189 | if (max-- < 1) |
190 | return 0; |
191 | if (*p == 0x80) { |
192 | *inf = 1; |
193 | ret = 0; |
194 | p++; |
195 | } else { |
196 | *inf = 0; |
197 | i = *p & 0x7f; |
198 | if (*(p++) & 0x80) { |
199 | if (i > sizeof(ret) || max < (long)i) |
200 | return 0; |
201 | while (i-- > 0) { |
202 | ret <<= 8L; |
203 | ret |= *(p++); |
204 | } |
205 | } else |
206 | ret = i; |
207 | } |
208 | /* |
209 | * Bound the length to comfortably fit in an int. Lengths in this module |
210 | * often switch between int and long without overflow checks. |
211 | */ |
212 | if (ret > INT_MAX / 2) |
213 | return 0; |
214 | *pp = p; |
215 | *rl = (long)ret; |
216 | return 1; |
217 | } |
218 | |
219 | /* |
220 | * class 0 is constructed constructed == 2 for indefinite length constructed |
221 | */ |
222 | void ASN1_put_object(unsigned char **pp, int constructed, int length, int tag, |
223 | int xclass) |
224 | { |
225 | unsigned char *p = *pp; |
226 | int i, ttag; |
227 | |
228 | i = (constructed) ? V_ASN1_CONSTRUCTED : 0; |
229 | i |= (xclass & V_ASN1_PRIVATE); |
230 | if (tag < 31) |
231 | *(p++) = i | (tag & V_ASN1_PRIMITIVE_TAG); |
232 | else { |
233 | *(p++) = i | V_ASN1_PRIMITIVE_TAG; |
234 | for (i = 0, ttag = tag; ttag > 0; i++) |
235 | ttag >>= 7; |
236 | ttag = i; |
237 | while (i-- > 0) { |
238 | p[i] = tag & 0x7f; |
239 | if (i != (ttag - 1)) |
240 | p[i] |= 0x80; |
241 | tag >>= 7; |
242 | } |
243 | p += ttag; |
244 | } |
245 | if (constructed == 2) |
246 | *(p++) = 0x80; |
247 | else |
248 | asn1_put_length(&p, length); |
249 | *pp = p; |
250 | } |
251 | |
252 | int ASN1_put_eoc(unsigned char **pp) |
253 | { |
254 | unsigned char *p = *pp; |
255 | *p++ = 0; |
256 | *p++ = 0; |
257 | *pp = p; |
258 | return 2; |
259 | } |
260 | |
261 | static void asn1_put_length(unsigned char **pp, int length) |
262 | { |
263 | unsigned char *p = *pp; |
264 | int i, l; |
265 | if (length <= 127) |
266 | *(p++) = (unsigned char)length; |
267 | else { |
268 | l = length; |
269 | for (i = 0; l > 0; i++) |
270 | l >>= 8; |
271 | *(p++) = i | 0x80; |
272 | l = i; |
273 | while (i-- > 0) { |
274 | p[i] = length & 0xff; |
275 | length >>= 8; |
276 | } |
277 | p += l; |
278 | } |
279 | *pp = p; |
280 | } |
281 | |
282 | int ASN1_object_size(int constructed, int length, int tag) |
283 | { |
284 | int ret = 1; |
285 | if (length < 0) |
286 | return -1; |
287 | if (tag >= 31) { |
288 | while (tag > 0) { |
289 | tag >>= 7; |
290 | ret++; |
291 | } |
292 | } |
293 | if (constructed == 2) { |
294 | ret += 3; |
295 | } else { |
296 | ret++; |
297 | if (length > 127) { |
298 | int tmplen = length; |
299 | while (tmplen > 0) { |
300 | tmplen >>= 8; |
301 | ret++; |
302 | } |
303 | } |
304 | } |
305 | if (ret >= INT_MAX - length) |
306 | return -1; |
307 | return ret + length; |
308 | } |
309 | |
310 | int ASN1_STRING_copy(ASN1_STRING *dst, const ASN1_STRING *str) |
311 | { |
312 | if (str == NULL) |
313 | return 0; |
314 | dst->type = str->type; |
315 | if (!ASN1_STRING_set(dst, str->data, str->length)) |
316 | return 0; |
317 | dst->flags = str->flags; |
318 | return 1; |
319 | } |
320 | |
321 | ASN1_STRING *ASN1_STRING_dup(const ASN1_STRING *str) |
322 | { |
323 | ASN1_STRING *ret; |
324 | if (!str) |
325 | return NULL; |
326 | ret = ASN1_STRING_new(); |
327 | if (!ret) |
328 | return NULL; |
329 | if (!ASN1_STRING_copy(ret, str)) { |
330 | ASN1_STRING_free(ret); |
331 | return NULL; |
332 | } |
333 | return ret; |
334 | } |
335 | |
336 | int ASN1_STRING_set(ASN1_STRING *str, const void *_data, int len) |
337 | { |
338 | unsigned char *c; |
339 | const char *data = _data; |
340 | |
341 | if (len < 0) { |
342 | if (data == NULL) |
343 | return (0); |
344 | else |
345 | len = strlen(data); |
346 | } |
347 | if ((str->length <= len) || (str->data == NULL)) { |
348 | c = str->data; |
349 | if (c == NULL) |
350 | str->data = OPENSSL_malloc(len + 1); |
351 | else |
352 | str->data = OPENSSL_realloc(c, len + 1); |
353 | |
354 | if (str->data == NULL) { |
355 | OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
356 | str->data = c; |
357 | return (0); |
358 | } |
359 | } |
360 | str->length = len; |
361 | if (data != NULL) { |
362 | OPENSSL_memcpy(str->data, data, len); |
363 | /* an allowance for strings :-) */ |
364 | str->data[len] = '\0'; |
365 | } |
366 | return (1); |
367 | } |
368 | |
369 | void ASN1_STRING_set0(ASN1_STRING *str, void *data, int len) |
370 | { |
371 | if (str->data) |
372 | OPENSSL_free(str->data); |
373 | str->data = data; |
374 | str->length = len; |
375 | } |
376 | |
377 | ASN1_STRING *ASN1_STRING_new(void) |
378 | { |
379 | return (ASN1_STRING_type_new(V_ASN1_OCTET_STRING)); |
380 | } |
381 | |
382 | ASN1_STRING *ASN1_STRING_type_new(int type) |
383 | { |
384 | ASN1_STRING *ret; |
385 | |
386 | ret = (ASN1_STRING *)OPENSSL_malloc(sizeof(ASN1_STRING)); |
387 | if (ret == NULL) { |
388 | OPENSSL_PUT_ERROR(ASN1, ERR_R_MALLOC_FAILURE); |
389 | return (NULL); |
390 | } |
391 | ret->length = 0; |
392 | ret->type = type; |
393 | ret->data = NULL; |
394 | ret->flags = 0; |
395 | return (ret); |
396 | } |
397 | |
398 | void ASN1_STRING_free(ASN1_STRING *a) |
399 | { |
400 | if (a == NULL) |
401 | return; |
402 | if (a->data && !(a->flags & ASN1_STRING_FLAG_NDEF)) |
403 | OPENSSL_free(a->data); |
404 | OPENSSL_free(a); |
405 | } |
406 | |
407 | int ASN1_STRING_cmp(const ASN1_STRING *a, const ASN1_STRING *b) |
408 | { |
409 | int i; |
410 | |
411 | i = (a->length - b->length); |
412 | if (i == 0) { |
413 | i = OPENSSL_memcmp(a->data, b->data, a->length); |
414 | if (i == 0) |
415 | return (a->type - b->type); |
416 | else |
417 | return (i); |
418 | } else |
419 | return (i); |
420 | } |
421 | |
422 | int ASN1_STRING_length(const ASN1_STRING *x) |
423 | { |
424 | return M_ASN1_STRING_length(x); |
425 | } |
426 | |
427 | void ASN1_STRING_length_set(ASN1_STRING *x, int len) |
428 | { |
429 | M_ASN1_STRING_length_set(x, len); |
430 | return; |
431 | } |
432 | |
433 | int ASN1_STRING_type(ASN1_STRING *x) |
434 | { |
435 | return M_ASN1_STRING_type(x); |
436 | } |
437 | |
438 | unsigned char *ASN1_STRING_data(ASN1_STRING *x) |
439 | { |
440 | return M_ASN1_STRING_data(x); |
441 | } |
442 | |
443 | const unsigned char *ASN1_STRING_get0_data(const ASN1_STRING *x) |
444 | { |
445 | return x->data; |
446 | } |
447 | |