]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * The contents of this file are subject to the Mozilla Public | |
3 | * License Version 1.1 (the "License"); you may not use this file | |
4 | * except in compliance with the License. You may obtain a copy of | |
5 | * the License at http://www.mozilla.org/MPL/ | |
6 | * | |
7 | * Software distributed under the License is distributed on an "AS | |
8 | * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or | |
9 | * implied. See the License for the specific language governing | |
10 | * rights and limitations under the License. | |
11 | * | |
12 | * The Original Code is the Netscape security libraries. | |
13 | * | |
14 | * The Initial Developer of the Original Code is Netscape | |
15 | * Communications Corporation. Portions created by Netscape are | |
16 | * Copyright (C) 1994-2000 Netscape Communications Corporation. All | |
17 | * Rights Reserved. | |
18 | * | |
19 | * Contributor(s): | |
20 | * | |
21 | * Alternatively, the contents of this file may be used under the | |
22 | * terms of the GNU General Public License Version 2 or later (the | |
23 | * "GPL"), in which case the provisions of the GPL are applicable | |
24 | * instead of those above. If you wish to allow use of your | |
25 | * version of this file only under the terms of the GPL and not to | |
26 | * allow others to use your version of this file under the MPL, | |
27 | * indicate your decision by deleting the provisions above and | |
28 | * replace them with the notice and other provisions required by | |
29 | * the GPL. If you do not delete the provisions above, a recipient | |
30 | * may use your version of this file under either the MPL or the | |
31 | * GPL. | |
32 | */ | |
33 | ||
34 | /* | |
35 | * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished | |
36 | * Encoding Rules). | |
37 | * | |
38 | * $Id: secasn1d.c,v 1.16 2004/05/13 15:29:13 dmitch Exp $ | |
39 | */ | |
e3d460c9 | 40 | #include <limits.h> |
b1ab9ed8 A |
41 | |
42 | #include "secasn1.h" | |
43 | #include "secerr.h" | |
44 | #include "assert.h" | |
45 | ||
46 | #ifdef NDEBUG | |
47 | #define DEBUG_DECASN1 0 | |
48 | #else | |
49 | #define DEBUG_DECASN1 1 | |
50 | #endif | |
51 | ||
52 | #if DEBUG_DECASN1 | |
53 | #include <stdio.h> | |
54 | #define dprintf(args...) printf(args) | |
55 | #else | |
56 | #define dprintf(args...) | |
57 | #endif /* DEBUG_DECASN1 */ | |
58 | ||
59 | typedef enum { | |
60 | beforeIdentifier, | |
61 | duringIdentifier, | |
62 | afterIdentifier, | |
63 | beforeLength, | |
64 | duringLength, | |
65 | afterLength, | |
66 | beforeBitString, | |
67 | duringBitString, | |
68 | duringConstructedString, | |
69 | duringGroup, | |
70 | duringLeaf, | |
71 | duringSaveEncoding, | |
72 | duringSequence, | |
73 | afterConstructedString, | |
74 | afterGroup, | |
75 | afterExplicit, | |
76 | afterImplicit, | |
77 | afterInline, | |
78 | afterPointer, | |
79 | afterSaveEncoding, | |
80 | beforeEndOfContents, | |
81 | duringEndOfContents, | |
82 | afterEndOfContents, | |
83 | beforeChoice, | |
84 | duringChoice, | |
85 | afterChoice, | |
86 | notInUse | |
87 | } sec_asn1d_parse_place; | |
88 | ||
89 | #ifndef NDEBUG | |
90 | #define DEBUG_ASN1D_STATES 1 | |
91 | /* tweakable by debugger, debug only */ | |
92 | int doDumpStates = 0; | |
93 | #else /* DEBUG_ASN1D_STATES 0 */ | |
94 | #endif /* DEBUG_ASN1D_STATES */ | |
95 | ||
96 | #if DEBUG_ASN1D_STATES | |
97 | static const char *place_names[] = { | |
98 | "beforeIdentifier", | |
99 | "duringIdentifier", | |
100 | "afterIdentifier", | |
101 | "beforeLength", | |
102 | "duringLength", | |
103 | "afterLength", | |
104 | "beforeBitString", | |
105 | "duringBitString", | |
106 | "duringConstructedString", | |
107 | "duringGroup", | |
108 | "duringLeaf", | |
109 | "duringSaveEncoding", | |
110 | "duringSequence", | |
111 | "afterConstructedString", | |
112 | "afterGroup", | |
113 | "afterExplicit", | |
114 | "afterImplicit", | |
115 | "afterInline", | |
116 | "afterPointer", | |
117 | "afterSaveEncoding", | |
118 | "beforeEndOfContents", | |
119 | "duringEndOfContents", | |
120 | "afterEndOfContents", | |
121 | "beforeChoice", | |
122 | "duringChoice", | |
123 | "afterChoice", | |
124 | "notInUse" | |
125 | }; | |
126 | ||
127 | static const char * const class_names[] = { | |
128 | "UNIVERSAL", | |
129 | "APPLICATION", | |
130 | "CONTEXT_SPECIFIC", | |
131 | "PRIVATE" | |
132 | }; | |
133 | ||
134 | static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" }; | |
135 | ||
136 | static const char * const type_names[] = { | |
137 | "END_OF_CONTENTS", | |
138 | "BOOLEAN", | |
139 | "INTEGER", | |
140 | "BIT_STRING", | |
141 | "OCTET_STRING", | |
142 | "NULL", | |
143 | "OBJECT_ID", | |
144 | "OBJECT_DESCRIPTOR", | |
145 | "(type 08)", | |
146 | "REAL", | |
147 | "ENUMERATED", | |
148 | "EMBEDDED", | |
149 | "UTF8_STRING", | |
150 | "(type 0d)", | |
151 | "(type 0e)", | |
152 | "(type 0f)", | |
153 | "SEQUENCE", | |
154 | "SET", | |
155 | "NUMERIC_STRING", | |
156 | "PRINTABLE_STRING", | |
157 | "T61_STRING", | |
158 | "VIDEOTEXT_STRING", | |
159 | "IA5_STRING", | |
160 | "UTC_TIME", | |
161 | "GENERALIZED_TIME", | |
162 | "GRAPHIC_STRING", | |
163 | "VISIBLE_STRING", | |
164 | "GENERAL_STRING", | |
165 | "UNIVERSAL_STRING", | |
166 | "(type 1d)", | |
167 | "BMP_STRING", | |
168 | "HIGH_TAG_VALUE" | |
169 | }; | |
170 | ||
171 | static const char * const flag_names[] = { /* flags, right to left */ | |
172 | "OPTIONAL", | |
173 | "EXPLICIT", | |
174 | "ANY", | |
175 | "INLINE", | |
176 | "POINTER", | |
177 | "GROUP", | |
178 | "DYNAMIC", | |
179 | "SKIP", | |
180 | "INNER", | |
181 | "SAVE", | |
182 | "", /* decoder ignores "MAY_STREAM", */ | |
183 | "SKIP_REST", | |
184 | "CHOICE", | |
185 | "NO_STREAM", | |
186 | "DEBUG_BREAK", | |
187 | "unknown 08", | |
188 | "unknown 10", | |
189 | "unknown 20", | |
190 | "unknown 40", | |
191 | "unknown 80" | |
192 | }; | |
193 | ||
194 | static int /* bool */ | |
195 | formatKind(unsigned long kind, char * buf) | |
196 | { | |
197 | int i; | |
198 | unsigned long k = kind & SEC_ASN1_TAGNUM_MASK; | |
199 | unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER | | |
200 | SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE); | |
201 | ||
202 | buf[0] = 0; | |
203 | if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) { | |
204 | sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] ); | |
205 | buf += strlen(buf); | |
206 | } | |
207 | if (kind & SEC_ASN1_METHOD_MASK) { | |
208 | sprintf(buf, " %s", method_names[1]); | |
209 | buf += strlen(buf); | |
210 | } | |
211 | if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) { | |
212 | if (k || !notag) { | |
213 | sprintf(buf, " %s", type_names[k] ); | |
214 | if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) && | |
215 | (kind & SEC_ASN1_GROUP)) { | |
216 | buf += strlen(buf); | |
217 | sprintf(buf, "_OF"); | |
218 | } | |
219 | } | |
220 | } else { | |
221 | sprintf(buf, " [%lu]", k); | |
222 | } | |
223 | buf += strlen(buf); | |
224 | ||
225 | for (k = kind >> 8, i = 0; k; k >>= 1, ++i) { | |
226 | if (k & 1) { | |
227 | sprintf(buf, " %s", flag_names[i]); | |
228 | buf += strlen(buf); | |
229 | } | |
230 | } | |
231 | return notag != 0; | |
232 | } | |
233 | ||
234 | #endif /* DEBUG_ASN1D_STATES */ | |
235 | ||
236 | typedef enum { | |
237 | allDone, | |
238 | decodeError, | |
239 | keepGoing, | |
240 | needBytes | |
241 | } sec_asn1d_parse_status; | |
242 | ||
243 | struct subitem { | |
244 | const void *data; | |
245 | unsigned long len; /* only used for substrings */ | |
246 | struct subitem *next; | |
247 | }; | |
248 | ||
249 | typedef struct sec_asn1d_state_struct { | |
250 | SEC_ASN1DecoderContext *top; | |
251 | const SecAsn1Template *theTemplate; | |
252 | void *dest; | |
253 | ||
254 | void *our_mark; /* free on completion */ | |
255 | ||
256 | struct sec_asn1d_state_struct *parent; /* aka prev */ | |
257 | struct sec_asn1d_state_struct *child; /* aka next */ | |
258 | ||
259 | sec_asn1d_parse_place place; | |
260 | ||
261 | /* | |
262 | * XXX explain the next fields as clearly as possible... | |
263 | */ | |
264 | unsigned char found_tag_modifiers; | |
265 | unsigned char expect_tag_modifiers; | |
266 | unsigned long check_tag_mask; | |
267 | unsigned long found_tag_number; | |
268 | unsigned long expect_tag_number; | |
269 | unsigned long underlying_kind; | |
270 | ||
271 | unsigned long contents_length; | |
272 | unsigned long pending; | |
273 | unsigned long consumed; | |
274 | ||
275 | int depth; | |
276 | ||
277 | /* | |
278 | * Bit strings have their length adjusted -- the first octet of the | |
279 | * contents contains a value between 0 and 7 which says how many bits | |
280 | * at the end of the octets are not actually part of the bit string; | |
281 | * when parsing bit strings we put that value here because we need it | |
282 | * later, for adjustment of the length (when the whole string is done). | |
283 | */ | |
284 | unsigned int bit_string_unused_bits; | |
285 | ||
286 | /* | |
287 | * The following are used for indefinite-length constructed strings. | |
288 | */ | |
289 | struct subitem *subitems_head; | |
290 | struct subitem *subitems_tail; | |
291 | ||
292 | PRPackedBool | |
293 | allocate, /* when true, need to allocate the destination */ | |
294 | endofcontents, /* this state ended up parsing end-of-contents octets */ | |
295 | explicit, /* we are handling an explicit header */ | |
296 | indefinite, /* the current item has indefinite-length encoding */ | |
297 | missing, /* an optional field that was not present */ | |
298 | optional, /* the template says this field may be omitted */ | |
299 | substring; /* this is a substring of a constructed string */ | |
300 | } sec_asn1d_state; | |
301 | ||
302 | #define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER) | |
303 | #define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0) | |
304 | #define TAG_NUMBER_BITS 7 | |
305 | #define TAG_NUMBER_MASK 0x7f | |
306 | ||
307 | #define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0) | |
308 | #define LONG_FORM_LENGTH(b) ((b) & 0x7f) | |
309 | ||
310 | #define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt))) | |
311 | ||
312 | ||
313 | /* | |
314 | * An "outsider" will have an opaque pointer to this, created by calling | |
315 | * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent | |
316 | * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to | |
317 | * SEC_ASN1DecoderFinish(). | |
318 | */ | |
319 | struct sec_DecoderContext_struct { | |
320 | PRArenaPool *our_pool; /* for our internal allocs */ | |
321 | PRArenaPool *their_pool; /* for destination structure allocs */ | |
322 | #ifdef SEC_ASN1D_FREE_ON_ERROR /* | |
323 | * XXX see comment below (by same | |
324 | * ifdef) that explains why this | |
325 | * does not work (need more smarts | |
326 | * in order to free back to mark) | |
327 | */ | |
328 | /* | |
329 | * XXX how to make their_mark work in the case where they do NOT | |
330 | * give us a pool pointer? | |
331 | */ | |
332 | void *their_mark; /* free on error */ | |
333 | #endif | |
334 | ||
335 | sec_asn1d_state *current; | |
336 | sec_asn1d_parse_status status; | |
337 | ||
338 | SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */ | |
339 | void *notify_arg; /* argument to notify_proc */ | |
340 | PRBool during_notify; /* true during call to notify_proc */ | |
341 | ||
342 | SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */ | |
343 | void *filter_arg; /* argument to that function */ | |
344 | PRBool filter_only; /* do not allocate/store fields */ | |
345 | }; | |
346 | ||
347 | ||
348 | /* | |
349 | * XXX this is a fairly generic function that may belong elsewhere | |
350 | */ | |
351 | static void * | |
352 | sec_asn1d_alloc (PRArenaPool *poolp, unsigned long len) | |
353 | { | |
354 | void *thing; | |
355 | ||
356 | if (poolp != NULL) { | |
357 | /* | |
358 | * Allocate from the pool. | |
359 | */ | |
360 | thing = PORT_ArenaAlloc (poolp, len); | |
361 | } else { | |
362 | /* | |
363 | * Allocate generically. | |
364 | */ | |
365 | thing = PORT_Alloc (len); | |
366 | } | |
367 | ||
368 | return thing; | |
369 | } | |
370 | ||
371 | ||
372 | /* | |
373 | * XXX this is a fairly generic function that may belong elsewhere | |
374 | */ | |
375 | static void * | |
376 | sec_asn1d_zalloc (PRArenaPool *poolp, unsigned long len) | |
377 | { | |
378 | void *thing; | |
379 | ||
380 | thing = sec_asn1d_alloc (poolp, len); | |
381 | if (thing != NULL) | |
382 | PORT_Memset (thing, 0, len); | |
383 | return thing; | |
384 | } | |
385 | ||
386 | ||
387 | static sec_asn1d_state * | |
388 | sec_asn1d_push_state (SEC_ASN1DecoderContext *cx, | |
389 | const SecAsn1Template *theTemplate, | |
390 | void *dest, PRBool new_depth) | |
391 | { | |
6b200bc3 | 392 | sec_asn1d_state *state, *new_state = NULL; |
b1ab9ed8 A |
393 | |
394 | state = cx->current; | |
395 | ||
396 | PORT_Assert (state == NULL || state->child == NULL); | |
397 | ||
398 | if (state != NULL) { | |
399 | PORT_Assert (state->our_mark == NULL); | |
400 | state->our_mark = PORT_ArenaMark (cx->our_pool); | |
401 | } | |
402 | ||
403 | new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool, | |
404 | sizeof(*new_state)); | |
405 | if (new_state == NULL) { | |
406 | dprintf("decodeError: zalloc failure\n"); | |
407 | goto loser; | |
408 | } | |
409 | ||
410 | new_state->top = cx; | |
411 | new_state->parent = state; | |
412 | new_state->theTemplate = theTemplate; | |
413 | new_state->place = notInUse; | |
414 | if (dest != NULL) | |
415 | new_state->dest = (char *)dest + theTemplate->offset; | |
416 | ||
417 | if (state != NULL) { | |
418 | new_state->depth = state->depth; | |
419 | if (new_depth) { | |
420 | if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) { | |
421 | PORT_SetError (SEC_ERROR_BAD_DER); | |
422 | goto loser; | |
423 | } | |
424 | } | |
425 | state->child = new_state; | |
426 | } | |
427 | ||
428 | cx->current = new_state; | |
429 | return new_state; | |
430 | ||
431 | loser: | |
432 | cx->status = decodeError; | |
433 | if (state != NULL) { | |
434 | PORT_ArenaRelease(cx->our_pool, state->our_mark); | |
435 | state->our_mark = NULL; | |
436 | } | |
6b200bc3 A |
437 | if (new_state != NULL) { |
438 | PORT_Free(new_state); | |
439 | } | |
b1ab9ed8 A |
440 | return NULL; |
441 | } | |
442 | ||
443 | ||
444 | static void | |
445 | sec_asn1d_scrub_state (sec_asn1d_state *state) | |
446 | { | |
447 | /* | |
448 | * Some default "scrubbing". | |
449 | * XXX right set of initializations? | |
450 | */ | |
451 | state->place = beforeIdentifier; | |
452 | state->endofcontents = PR_FALSE; | |
453 | state->indefinite = PR_FALSE; | |
454 | state->missing = PR_FALSE; | |
455 | ||
456 | PORT_Assert (state->consumed == 0); | |
457 | } | |
458 | ||
459 | ||
460 | static sec_asn1d_state * | |
461 | sec_asn1d_get_enclosing_construct(sec_asn1d_state *state) | |
462 | { | |
463 | for (state = state->parent; state; state = state->parent) { | |
464 | sec_asn1d_parse_place place = state->place; | |
465 | if (place != afterImplicit && | |
466 | place != afterPointer && | |
467 | place != afterInline && | |
468 | place != afterSaveEncoding && | |
469 | place != duringSaveEncoding && | |
470 | place != duringChoice) { | |
471 | ||
472 | /* we've walked up the stack to a state that represents | |
473 | ** the enclosing construct. | |
474 | */ | |
475 | break; | |
476 | } | |
477 | } | |
478 | return state; | |
479 | } | |
480 | ||
481 | ||
482 | static PRBool | |
483 | sec_asn1d_parent_allows_EOC(sec_asn1d_state *state) | |
484 | { | |
485 | /* get state of enclosing construct. */ | |
486 | state = sec_asn1d_get_enclosing_construct(state); | |
487 | if (state) { | |
488 | sec_asn1d_parse_place place = state->place; | |
489 | /* Is it one of the types that permits an unexpected EOC? */ | |
490 | int eoc_permitted = | |
491 | (place == duringGroup || | |
492 | place == duringConstructedString || | |
493 | state->child->optional); | |
494 | return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE; | |
495 | } | |
496 | return PR_FALSE; | |
497 | } | |
498 | ||
499 | ||
500 | static void | |
501 | sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth) | |
502 | { | |
503 | if (cx->notify_proc == NULL) | |
504 | return; | |
505 | ||
506 | cx->during_notify = PR_TRUE; | |
507 | (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth); | |
508 | cx->during_notify = PR_FALSE; | |
509 | } | |
510 | ||
511 | ||
512 | static void | |
513 | sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth) | |
514 | { | |
515 | if (cx->notify_proc == NULL) | |
516 | return; | |
517 | ||
518 | cx->during_notify = PR_TRUE; | |
519 | (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth); | |
520 | cx->during_notify = PR_FALSE; | |
521 | } | |
522 | ||
523 | ||
524 | static sec_asn1d_state * | |
525 | sec_asn1d_init_state_based_on_template (sec_asn1d_state *state, | |
526 | #ifdef __APPLE__ | |
822b670c A |
527 | const char *buf, /* for SEC_ASN1GetSubtemplate() */ |
528 | size_t len | |
b1ab9ed8 A |
529 | #endif |
530 | ) | |
531 | { | |
532 | PRBool explicit, optional, universal; | |
533 | unsigned char expect_tag_modifiers; | |
534 | unsigned long encode_kind, under_kind; | |
535 | unsigned long check_tag_mask, expect_tag_number; | |
536 | #ifdef __APPLE__ | |
537 | unsigned long dynamic; | |
538 | #endif | |
539 | ||
540 | ||
541 | /* XXX Check that both of these tests are really needed/appropriate. */ | |
d8f41ccd | 542 | if (state == NULL || state->top->status == decodeError || state->theTemplate == NULL) |
b1ab9ed8 A |
543 | return state; |
544 | ||
545 | encode_kind = state->theTemplate->kind; | |
546 | ||
547 | if (encode_kind & SEC_ASN1_SAVE) { | |
548 | /* | |
549 | * This is a "magic" field that saves away all bytes, allowing | |
550 | * the immediately following field to still be decoded from this | |
551 | * same spot -- sort of a fork. | |
552 | */ | |
553 | /* check that there are no extraneous bits */ | |
554 | PORT_Assert (encode_kind == SEC_ASN1_SAVE); | |
555 | if (state->top->filter_only) { | |
556 | /* | |
557 | * If we are not storing, then we do not do the SAVE field | |
558 | * at all. Just move ahead to the "real" field instead, | |
559 | * doing the appropriate notify calls before and after. | |
560 | */ | |
561 | sec_asn1d_notify_after (state->top, state->dest, state->depth); | |
562 | /* | |
563 | * Since we are not storing, allow for our current dest value | |
564 | * to be NULL. (This might not actually occur, but right now I | |
565 | * cannot convince myself one way or the other.) If it is NULL, | |
566 | * assume that our parent dest can help us out. | |
567 | */ | |
568 | if (state->dest == NULL) | |
569 | state->dest = state->parent->dest; | |
570 | else | |
571 | state->dest = | |
572 | (char *)state->dest - state->theTemplate->offset; | |
573 | state->theTemplate++; | |
574 | if (state->dest != NULL) | |
575 | state->dest = | |
576 | (char *)state->dest + state->theTemplate->offset; | |
577 | sec_asn1d_notify_before (state->top, state->dest, state->depth); | |
578 | encode_kind = state->theTemplate->kind; | |
579 | PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0); | |
580 | } else { | |
581 | sec_asn1d_scrub_state (state); | |
582 | state->place = duringSaveEncoding; | |
583 | state = sec_asn1d_push_state (state->top, kSecAsn1AnyTemplate, | |
584 | state->dest, PR_FALSE); | |
585 | if (state != NULL) | |
586 | state = sec_asn1d_init_state_based_on_template (state, | |
822b670c | 587 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
588 | return state; |
589 | } | |
590 | } | |
591 | ||
592 | ||
593 | universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) | |
594 | ? PR_TRUE : PR_FALSE; | |
595 | ||
596 | explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE; | |
597 | encode_kind &= ~SEC_ASN1_EXPLICIT; | |
598 | ||
599 | optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE; | |
600 | encode_kind &= ~SEC_ASN1_OPTIONAL; | |
601 | ||
602 | #ifdef __APPLE__ | |
603 | dynamic = (encode_kind & SEC_ASN1_DYNAMIC) ? PR_TRUE : PR_FALSE; | |
604 | encode_kind &= ~SEC_ASN1_DYNAMIC; | |
605 | #endif | |
606 | ||
607 | PORT_Assert (!(explicit && universal)); /* bad templates */ | |
608 | ||
609 | encode_kind &= ~SEC_ASN1_DYNAMIC; | |
610 | encode_kind &= ~SEC_ASN1_MAY_STREAM; | |
611 | ||
612 | if( encode_kind & SEC_ASN1_CHOICE ) { | |
613 | #if 0 /* XXX remove? */ | |
614 | sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE); | |
615 | if( (sec_asn1d_state *)NULL == child ) { | |
616 | return (sec_asn1d_state *)NULL; | |
617 | } | |
618 | ||
619 | child->allocate = state->allocate; | |
620 | child->place = beforeChoice; | |
621 | return child; | |
622 | #else | |
623 | state->place = beforeChoice; | |
624 | return state; | |
625 | #endif | |
626 | } | |
627 | ||
628 | if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal | |
629 | && !explicit)) { | |
630 | const SecAsn1Template *subt; | |
631 | void *dest; | |
632 | PRBool child_allocate; | |
633 | void *subDest; | |
634 | ||
635 | PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); | |
636 | ||
637 | sec_asn1d_scrub_state (state); | |
638 | child_allocate = PR_FALSE; | |
639 | ||
640 | if (encode_kind & SEC_ASN1_POINTER) { | |
641 | /* | |
642 | * A POINTER means we need to allocate the destination for | |
643 | * this field. But, since it may also be an optional field, | |
644 | * we defer the allocation until later; we just record that | |
645 | * it needs to be done. | |
646 | * | |
647 | * There are two possible scenarios here -- one is just a | |
648 | * plain POINTER (kind of like INLINE, except with allocation) | |
649 | * and the other is an implicitly-tagged POINTER. We don't | |
650 | * need to do anything special here for the two cases, but | |
651 | * since the template definition can be tricky, we do check | |
652 | * that there are no extraneous bits set in encode_kind. | |
653 | * | |
654 | * XXX The same conditions which assert should set an error. | |
655 | */ | |
656 | if (universal) { | |
657 | /* | |
658 | * "universal" means this entry is a standalone POINTER; | |
659 | * there should be no other bits set in encode_kind. | |
660 | */ | |
661 | PORT_Assert (encode_kind == SEC_ASN1_POINTER); | |
662 | } else { | |
663 | /* | |
664 | * If we get here we have an implicitly-tagged field | |
665 | * that needs to be put into a POINTER. The subtemplate | |
666 | * will determine how to decode the field, but encode_kind | |
667 | * describes the (implicit) tag we are looking for. | |
668 | * The non-tag bits of encode_kind will be ignored by | |
669 | * the code below; none of them should be set, however, | |
670 | * except for the POINTER bit itself -- so check that. | |
671 | */ | |
672 | PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK) | |
673 | == SEC_ASN1_POINTER); | |
674 | } | |
675 | if (!state->top->filter_only) | |
676 | child_allocate = PR_TRUE; | |
677 | dest = NULL; | |
678 | state->place = afterPointer; | |
679 | } else { | |
680 | dest = state->dest; | |
681 | if (encode_kind & SEC_ASN1_INLINE) { | |
682 | /* check that there are no extraneous bits */ | |
683 | /* FIXME - why are optional and inline mutually | |
684 | * exclusive? Delete this assert and see what happens... | |
685 | PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); | |
686 | */ | |
687 | state->place = afterInline; | |
688 | } else { | |
689 | state->place = afterImplicit; | |
690 | } | |
691 | } | |
692 | ||
693 | state->optional = optional; | |
694 | ||
695 | subDest = state->dest; | |
696 | #if defined(__APPLE__) | |
697 | /* | |
698 | * We might be starting the processing of a group or a | |
699 | * set, in which case state->dest is NULL. Get parent's dest, | |
700 | * or grandparent's, etc... just for the use by | |
701 | * SEC_ASN1GetSubtemplate (specifically, by dynamic | |
702 | * choosers) | |
703 | */ | |
704 | sec_asn1d_state *tempState = state; | |
705 | while(subDest == NULL) { | |
706 | sec_asn1d_state *parent = tempState->parent; | |
707 | if(parent == NULL) { | |
708 | /* Oh well. Not going to work for this template. */ | |
709 | break; | |
710 | } | |
711 | subDest = parent->dest; | |
712 | tempState = parent; | |
713 | } | |
714 | #endif /* __APPLE__ */ | |
715 | subt = SEC_ASN1GetSubtemplate (state->theTemplate, subDest, | |
822b670c | 716 | PR_FALSE, buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
717 | state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE); |
718 | if (state == NULL) | |
719 | return NULL; | |
720 | ||
721 | state->allocate = child_allocate; | |
722 | ||
723 | if (universal | |
724 | #ifdef __APPLE__ | |
725 | /* Dynamic: restart with new template */ | |
726 | || dynamic | |
727 | #endif | |
728 | ) { | |
729 | state = sec_asn1d_init_state_based_on_template (state, | |
822b670c | 730 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
731 | if (state != NULL) { |
732 | /* | |
733 | * If this field is optional, we need to record that on | |
734 | * the pushed child so it won't fail if the field isn't | |
735 | * found. I can't think of a way that this new state | |
736 | * could already have optional set (which we would wipe | |
737 | * out below if our local optional is not set) -- but | |
738 | * just to be sure, assert that it isn't set. | |
739 | */ | |
740 | PORT_Assert (!state->optional); | |
741 | state->optional = optional; | |
742 | } | |
743 | return state; | |
744 | } | |
745 | ||
746 | under_kind = state->theTemplate->kind; | |
747 | under_kind &= ~SEC_ASN1_MAY_STREAM; | |
748 | } else if (explicit) { | |
749 | /* | |
750 | * For explicit, we only need to match the encoding tag next, | |
751 | * then we will push another state to handle the entire inner | |
752 | * part. In this case, there is no underlying kind which plays | |
753 | * any part in the determination of the outer, explicit tag. | |
754 | * So we just set under_kind to 0, which is not a valid tag, | |
755 | * and the rest of the tag matching stuff should be okay. | |
756 | */ | |
757 | under_kind = 0; | |
758 | } else { | |
759 | /* | |
760 | * Nothing special; the underlying kind and the given encoding | |
761 | * information are the same. | |
762 | */ | |
763 | under_kind = encode_kind; | |
764 | } | |
765 | ||
766 | /* XXX is this the right set of bits to test here? */ | |
767 | PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | |
768 | | SEC_ASN1_MAY_STREAM | |
769 | | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0); | |
770 | ||
771 | if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) { | |
772 | PORT_Assert (encode_kind == under_kind); | |
773 | if (encode_kind & SEC_ASN1_SKIP) { | |
774 | PORT_Assert (!optional); | |
775 | PORT_Assert (encode_kind == SEC_ASN1_SKIP); | |
776 | state->dest = NULL; | |
777 | } | |
778 | check_tag_mask = 0; | |
779 | expect_tag_modifiers = 0; | |
780 | expect_tag_number = 0; | |
781 | } else { | |
782 | check_tag_mask = SEC_ASN1_TAG_MASK; | |
783 | expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK | |
784 | & ~SEC_ASN1_TAGNUM_MASK; | |
785 | /* | |
786 | * XXX This assumes only single-octet identifiers. To handle | |
787 | * the HIGH TAG form we would need to do some more work, especially | |
788 | * in how to specify them in the template, because right now we | |
789 | * do not provide a way to specify more *tag* bits in encode_kind. | |
790 | */ | |
791 | expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK; | |
792 | ||
793 | switch (under_kind & SEC_ASN1_TAGNUM_MASK) { | |
794 | case SEC_ASN1_SET: | |
795 | /* | |
796 | * XXX A plain old SET (as opposed to a SET OF) is not | |
797 | * implemented. | |
798 | * If it ever is, remove this assert... | |
799 | */ | |
800 | PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0); | |
801 | /* fallthru */ | |
802 | case SEC_ASN1_SEQUENCE: | |
803 | expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED; | |
804 | break; | |
805 | case SEC_ASN1_BIT_STRING: | |
806 | case SEC_ASN1_BMP_STRING: | |
807 | case SEC_ASN1_GENERALIZED_TIME: | |
808 | case SEC_ASN1_IA5_STRING: | |
809 | case SEC_ASN1_OCTET_STRING: | |
810 | case SEC_ASN1_PRINTABLE_STRING: | |
811 | case SEC_ASN1_T61_STRING: | |
812 | case SEC_ASN1_UNIVERSAL_STRING: | |
813 | case SEC_ASN1_UTC_TIME: | |
814 | case SEC_ASN1_UTF8_STRING: | |
815 | case SEC_ASN1_VISIBLE_STRING: | |
816 | check_tag_mask &= ~SEC_ASN1_CONSTRUCTED; | |
817 | break; | |
818 | } | |
819 | } | |
820 | ||
821 | state->check_tag_mask = check_tag_mask; | |
822 | state->expect_tag_modifiers = expect_tag_modifiers; | |
823 | state->expect_tag_number = expect_tag_number; | |
824 | state->underlying_kind = under_kind; | |
825 | state->explicit = explicit; | |
826 | state->optional = optional; | |
827 | sec_asn1d_scrub_state (state); | |
828 | ||
829 | return state; | |
830 | } | |
831 | ||
832 | ||
833 | static unsigned long | |
834 | sec_asn1d_parse_identifier (sec_asn1d_state *state, | |
835 | const char *buf, unsigned long len) | |
836 | { | |
837 | unsigned char byte; | |
838 | unsigned char tag_number; | |
839 | ||
840 | PORT_Assert (state->place == beforeIdentifier); | |
841 | ||
842 | if (len == 0) { | |
843 | state->top->status = needBytes; | |
844 | return 0; | |
845 | } | |
846 | ||
847 | byte = (unsigned char) *buf; | |
848 | #ifdef DEBUG_ASN1D_STATES | |
849 | if (doDumpStates > 0) { | |
850 | char kindBuf[256]; | |
851 | formatKind(byte, kindBuf); | |
852 | printf("Found tag %02x %s\n", byte, kindBuf); | |
853 | } | |
854 | #endif | |
855 | tag_number = byte & SEC_ASN1_TAGNUM_MASK; | |
856 | ||
857 | if (IS_HIGH_TAG_NUMBER (tag_number)) { | |
858 | state->place = duringIdentifier; | |
859 | state->found_tag_number = 0; | |
860 | /* | |
861 | * Actually, we have no idea how many bytes are pending, but we | |
862 | * do know that it is at least 1. That is all we know; we have | |
863 | * to look at each byte to know if there is another, etc. | |
864 | */ | |
865 | state->pending = 1; | |
866 | } else { | |
867 | if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) { | |
868 | /* | |
869 | * Our parent has indefinite-length encoding, and the | |
870 | * entire tag found is 0, so it seems that we have hit the | |
871 | * end-of-contents octets. To handle this, we just change | |
872 | * our state to that which expects to get the bytes of the | |
873 | * end-of-contents octets and let that code re-read this byte | |
874 | * so that our categorization of field types is correct. | |
875 | * After that, our parent will then deal with everything else. | |
876 | */ | |
877 | state->place = duringEndOfContents; | |
878 | state->pending = 2; | |
879 | state->found_tag_number = 0; | |
880 | state->found_tag_modifiers = 0; | |
881 | /* | |
882 | * We might be an optional field that is, as we now find out, | |
883 | * missing. Give our parent a clue that this happened. | |
884 | */ | |
885 | if (state->optional) | |
886 | state->missing = PR_TRUE; | |
887 | return 0; | |
888 | } | |
889 | state->place = afterIdentifier; | |
890 | state->found_tag_number = tag_number; | |
891 | } | |
892 | state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK; | |
893 | ||
894 | return 1; | |
895 | } | |
896 | ||
897 | ||
898 | static unsigned long | |
899 | sec_asn1d_parse_more_identifier (sec_asn1d_state *state, | |
900 | const char *buf, unsigned long len) | |
901 | { | |
902 | unsigned char byte; | |
903 | int count; | |
904 | ||
905 | PORT_Assert (state->pending == 1); | |
906 | PORT_Assert (state->place == duringIdentifier); | |
907 | ||
908 | if (len == 0) { | |
909 | state->top->status = needBytes; | |
910 | return 0; | |
911 | } | |
912 | ||
913 | count = 0; | |
914 | ||
915 | while (len && state->pending) { | |
916 | if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) { | |
917 | /* | |
918 | * The given high tag number overflows our container; | |
919 | * just give up. This is not likely to *ever* happen. | |
920 | */ | |
921 | PORT_SetError (SEC_ERROR_BAD_DER); | |
922 | state->top->status = decodeError; | |
923 | dprintf("decodeError: parse_more_id high bits oflow\n"); | |
924 | return 0; | |
925 | } | |
926 | ||
927 | state->found_tag_number <<= TAG_NUMBER_BITS; | |
928 | ||
929 | byte = (unsigned char) buf[count++]; | |
930 | state->found_tag_number |= (byte & TAG_NUMBER_MASK); | |
931 | ||
932 | len--; | |
933 | if (LAST_TAG_NUMBER_BYTE (byte)) | |
934 | state->pending = 0; | |
935 | } | |
936 | ||
937 | if (state->pending == 0) | |
938 | state->place = afterIdentifier; | |
939 | ||
940 | return count; | |
941 | } | |
942 | ||
943 | ||
944 | static void | |
945 | sec_asn1d_confirm_identifier (sec_asn1d_state *state) | |
946 | { | |
947 | PRBool match; | |
948 | ||
949 | PORT_Assert (state->place == afterIdentifier); | |
950 | ||
951 | match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask) | |
952 | == state->expect_tag_modifiers) | |
953 | && ((state->found_tag_number & state->check_tag_mask) | |
954 | == state->expect_tag_number)); | |
955 | if (match) { | |
956 | state->place = beforeLength; | |
957 | } else { | |
958 | if (state->optional) { | |
959 | state->missing = PR_TRUE; | |
960 | state->place = afterEndOfContents; | |
961 | } else { | |
962 | PORT_SetError (SEC_ERROR_BAD_DER); | |
963 | state->top->status = decodeError; | |
964 | //dprintf("decodeError: sec_asn1d_confirm_identifier\n"); | |
965 | } | |
966 | } | |
967 | } | |
968 | ||
969 | ||
970 | static unsigned long | |
971 | sec_asn1d_parse_length (sec_asn1d_state *state, | |
972 | const char *buf, unsigned long len) | |
973 | { | |
974 | unsigned char byte; | |
975 | ||
976 | PORT_Assert (state->place == beforeLength); | |
977 | ||
978 | if (len == 0) { | |
979 | state->top->status = needBytes; | |
980 | return 0; | |
981 | } | |
982 | ||
983 | /* | |
984 | * The default/likely outcome. It may get adjusted below. | |
985 | */ | |
986 | state->place = afterLength; | |
987 | ||
988 | byte = (unsigned char) *buf; | |
989 | ||
990 | if (LENGTH_IS_SHORT_FORM (byte)) { | |
991 | state->contents_length = byte; | |
992 | } else { | |
993 | state->contents_length = 0; | |
994 | state->pending = LONG_FORM_LENGTH (byte); | |
995 | if (state->pending == 0) { | |
996 | state->indefinite = PR_TRUE; | |
997 | } else { | |
998 | state->place = duringLength; | |
999 | } | |
1000 | } | |
1001 | ||
1002 | /* If we're parsing an ANY, SKIP, or SAVE template, and | |
1003 | ** the object being saved is definite length encoded and constructed, | |
1004 | ** there's no point in decoding that construct's members. | |
1005 | ** So, just forget it's constructed and treat it as primitive. | |
1006 | ** (SAVE appears as an ANY at this point) | |
1007 | */ | |
1008 | if (!state->indefinite && | |
1009 | (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) { | |
1010 | state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED; | |
1011 | } | |
1012 | ||
1013 | return 1; | |
1014 | } | |
1015 | ||
1016 | ||
1017 | static unsigned long | |
1018 | sec_asn1d_parse_more_length (sec_asn1d_state *state, | |
1019 | const char *buf, unsigned long len) | |
1020 | { | |
1021 | int count; | |
1022 | ||
1023 | PORT_Assert (state->pending > 0); | |
1024 | PORT_Assert (state->place == duringLength); | |
1025 | ||
1026 | if (len == 0) { | |
1027 | state->top->status = needBytes; | |
1028 | return 0; | |
1029 | } | |
1030 | ||
1031 | count = 0; | |
1032 | ||
1033 | while (len && state->pending) { | |
1034 | if (HIGH_BITS (state->contents_length, 9) != 0) { | |
1035 | /* | |
1036 | * The given full content length overflows our container; | |
1037 | * just give up. | |
1038 | */ | |
1039 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1040 | state->top->status = decodeError; | |
1041 | dprintf("decodeError: sec_asn1d_parse_more_length\n"); | |
1042 | return 0; | |
1043 | } | |
1044 | ||
1045 | state->contents_length <<= 8; | |
1046 | state->contents_length |= (unsigned char) buf[count++]; | |
1047 | ||
1048 | len--; | |
1049 | state->pending--; | |
1050 | } | |
1051 | ||
1052 | if (state->pending == 0) | |
1053 | state->place = afterLength; | |
1054 | ||
1055 | return count; | |
1056 | } | |
1057 | ||
1058 | ||
e0e0d90e A |
1059 | /* |
1060 | * Helper function for sec_asn1d_prepare_for_contents. | |
1061 | * Checks that a value representing a number of bytes consumed can be | |
1062 | * subtracted from a remaining length. If so, returns PR_TRUE. | |
1063 | * Otherwise, sets the error SEC_ERROR_BAD_DER, indicates that there was a | |
1064 | * decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE. | |
1065 | */ | |
1066 | static PRBool | |
1067 | sec_asn1d_check_and_subtract_length (unsigned long *remaining, | |
1068 | unsigned long consumed, | |
1069 | SEC_ASN1DecoderContext *cx) | |
1070 | { | |
1071 | PORT_Assert(remaining); | |
1072 | PORT_Assert(cx); | |
1073 | if (!remaining || !cx) { | |
1074 | PORT_SetError (SEC_ERROR_INVALID_ARGS); | |
fa7225c8 A |
1075 | if(cx) { |
1076 | cx->status = decodeError; | |
1077 | } | |
e0e0d90e A |
1078 | return PR_FALSE; |
1079 | } | |
1080 | if (*remaining < consumed) { | |
1081 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1082 | cx->status = decodeError; | |
1083 | return PR_FALSE; | |
1084 | } | |
1085 | *remaining -= consumed; | |
1086 | return PR_TRUE; | |
1087 | } | |
1088 | ||
1089 | ||
b1ab9ed8 A |
1090 | static void |
1091 | sec_asn1d_prepare_for_contents (sec_asn1d_state *state, | |
1092 | #ifdef __APPLE__ | |
822b670c A |
1093 | const char *buf, /* needed for SEC_ASN1GetSubtemplate */ |
1094 | size_t len | |
b1ab9ed8 A |
1095 | #endif |
1096 | ) | |
1097 | { | |
d8f41ccd | 1098 | SecAsn1Item *item=NULL; |
b1ab9ed8 A |
1099 | PRArenaPool *poolp; |
1100 | unsigned long alloc_len; | |
1101 | ||
1102 | #ifdef DEBUG_ASN1D_STATES | |
1103 | if (doDumpStates > 0) { | |
1104 | printf("Found Length %lu %s\n", state->contents_length, | |
1105 | state->indefinite ? "indefinite" : ""); | |
1106 | } | |
1107 | #endif | |
1108 | ||
e0e0d90e A |
1109 | /** |
1110 | * The maximum length for a child element should be constrained to the | |
1111 | * length remaining in the first definite length element in the ancestor | |
1112 | * stack. If there is no definite length element in the ancestor stack, | |
1113 | * there's nothing to constrain the length of the child, so there's no | |
1114 | * further processing necessary. | |
1115 | * | |
1116 | * It's necessary to walk the ancestor stack, because it's possible to have | |
1117 | * definite length children that are part of an indefinite length element, | |
1118 | * which is itself part of an indefinite length element, and which is | |
1119 | * ultimately part of a definite length element. A simple example of this | |
1120 | * would be the handling of constructed OCTET STRINGs in BER encoding. | |
1121 | * | |
1122 | * This algorithm finds the first definite length element in the ancestor | |
1123 | * stack, if any, and if so, ensures that the length of the child element | |
1124 | * is consistent with the number of bytes remaining in the constraining | |
1125 | * ancestor element (that is, after accounting for any other sibling | |
1126 | * elements that may have been read). | |
1127 | * | |
1128 | * It's slightly complicated by the need to account both for integer | |
1129 | * underflow and overflow, as well as ensure that for indefinite length | |
1130 | * encodings, there's also enough space for the End-of-Contents (EOC) | |
1131 | * octets (Tag = 0x00, Length = 0x00, or two bytes). | |
1132 | */ | |
1133 | ||
1134 | /* Determine the maximum length available for this element by finding the | |
1135 | * first definite length ancestor, if any. */ | |
1136 | sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state); | |
1137 | while (parent && parent->indefinite) { | |
1138 | parent = sec_asn1d_get_enclosing_construct(parent); | |
1139 | } | |
1140 | /* If parent is null, state is either the outermost state / at the top of | |
1141 | * the stack, or the outermost state uses indefinite length encoding. In | |
1142 | * these cases, there's nothing external to constrain this element, so | |
1143 | * there's nothing to check. */ | |
1144 | if (parent) { | |
1145 | unsigned long remaining = parent->pending; | |
1146 | parent = state; | |
1147 | do { | |
1148 | if (!sec_asn1d_check_and_subtract_length(&remaining, parent->consumed, state->top) || | |
1149 | /* If parent->indefinite is true, parent->contents_length is | |
1150 | * zero and this is a no-op. */ | |
1151 | !sec_asn1d_check_and_subtract_length(&remaining, parent->contents_length, state->top) || | |
1152 | /* If parent->indefinite is true, then ensure there is enough | |
1153 | * space for an EOC tag of 2 bytes. */ | |
1154 | (parent->indefinite && !sec_asn1d_check_and_subtract_length(&remaining, 2, state->top))) { | |
1155 | /* This element is larger than its enclosing element, which is | |
1156 | * invalid. */ | |
1157 | return; | |
1158 | } | |
1159 | } while ((parent = sec_asn1d_get_enclosing_construct(parent)) && | |
1160 | parent->indefinite); | |
1161 | } | |
1162 | ||
b1ab9ed8 A |
1163 | /* |
1164 | * XXX I cannot decide if this allocation should exclude the case | |
1165 | * where state->endofcontents is true -- figure it out! | |
1166 | */ | |
1167 | if (state->allocate) { | |
1168 | void *dest; | |
1169 | ||
1170 | PORT_Assert (state->dest == NULL); | |
1171 | /* | |
1172 | * We are handling a POINTER or a member of a GROUP, and need to | |
1173 | * allocate for the data structure. | |
1174 | */ | |
1175 | dest = sec_asn1d_zalloc (state->top->their_pool, | |
1176 | state->theTemplate->size); | |
1177 | if (dest == NULL) { | |
1178 | dprintf("decodeError: sec_asn1d_prepare_for_contents zalloc\n"); | |
1179 | state->top->status = decodeError; | |
1180 | return; | |
1181 | } | |
1182 | /* FIXME _ we're losing the dest pointer after this! */ | |
1183 | state->dest = (char *)dest + state->theTemplate->offset; | |
1184 | ||
1185 | /* | |
1186 | * For a member of a GROUP, our parent will later put the | |
1187 | * pointer wherever it belongs. But for a POINTER, we need | |
1188 | * to record the destination now, in case notify or filter | |
1189 | * procs need access to it -- they cannot find it otherwise, | |
1190 | * until it is too late (for one-pass processing). | |
1191 | */ | |
1192 | if (state->parent->place == afterPointer) { | |
1193 | void **placep; | |
1194 | ||
1195 | placep = state->parent->dest; | |
1196 | *placep = dest; | |
1197 | } | |
1198 | } | |
1199 | ||
1200 | /* | |
1201 | * Remember, length may be indefinite here! In that case, | |
1202 | * both contents_length and pending will be zero. | |
1203 | */ | |
1204 | state->pending = state->contents_length; | |
1205 | ||
b1ab9ed8 A |
1206 | /* |
1207 | * An EXPLICIT is nothing but an outer header, which we have | |
1208 | * already parsed and accepted. Now we need to do the inner | |
1209 | * header and its contents. | |
1210 | */ | |
1211 | if (state->explicit) { | |
1212 | state->place = afterExplicit; | |
1213 | state = sec_asn1d_push_state (state->top, | |
1214 | SEC_ASN1GetSubtemplate(state->theTemplate, | |
1215 | state->dest, | |
1216 | PR_FALSE, | |
822b670c A |
1217 | buf /* __APPLE__ */, |
1218 | len /* __APPLE__ */), | |
b1ab9ed8 A |
1219 | state->dest, PR_TRUE); |
1220 | if (state != NULL) | |
1221 | state = sec_asn1d_init_state_based_on_template (state, | |
822b670c | 1222 | buf /* __APPLE__ */, len /* __APPLE__ */); |
d8f41ccd | 1223 | (void) state; |
b1ab9ed8 A |
1224 | return; |
1225 | } | |
1226 | ||
1227 | /* | |
1228 | * For GROUP (SET OF, SEQUENCE OF), even if we know the length here | |
1229 | * we cannot tell how many items we will end up with ... so push a | |
1230 | * state that can keep track of "children" (the individual members | |
1231 | * of the group; we will allocate as we go and put them all together | |
1232 | * at the end. | |
1233 | */ | |
1234 | if (state->underlying_kind & SEC_ASN1_GROUP) { | |
1235 | /* XXX If this assertion holds (should be able to confirm it via | |
1236 | * inspection, too) then move this code into the switch statement | |
1237 | * below under cases SET_OF and SEQUENCE_OF; it will be cleaner. | |
1238 | */ | |
1239 | PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF | |
1240 | || state->underlying_kind == SEC_ASN1_SEQUENCE_OF | |
1241 | || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC) | |
1242 | || state->underlying_kind == (SEC_ASN1_SET_OF|SEC_ASN1_DYNAMIC) | |
1243 | ); | |
1244 | if (state->contents_length != 0 || state->indefinite) { | |
1245 | const SecAsn1Template *subt; | |
1246 | ||
1247 | state->place = duringGroup; | |
1248 | subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, | |
822b670c | 1249 | PR_FALSE, buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
1250 | state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE); |
1251 | if (state != NULL) { | |
1252 | if (!state->top->filter_only) | |
1253 | state->allocate = PR_TRUE; /* XXX propogate this? */ | |
1254 | /* | |
1255 | * Do the "before" field notification for next in group. | |
1256 | */ | |
1257 | sec_asn1d_notify_before (state->top, state->dest, state->depth); | |
1258 | state = sec_asn1d_init_state_based_on_template (state, | |
822b670c | 1259 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
1260 | } |
1261 | } else { | |
1262 | /* | |
1263 | * A group of zero; we are done. | |
1264 | * Set state to afterGroup and let that code plant the NULL. | |
1265 | */ | |
1266 | state->place = afterGroup; | |
1267 | } | |
d8f41ccd | 1268 | (void) state; |
b1ab9ed8 A |
1269 | return; |
1270 | } | |
1271 | ||
1272 | switch (state->underlying_kind) { | |
1273 | case SEC_ASN1_SEQUENCE: | |
1274 | /* | |
1275 | * We need to push a child to handle the individual fields. | |
1276 | */ | |
1277 | state->place = duringSequence; | |
1278 | state = sec_asn1d_push_state (state->top, state->theTemplate + 1, | |
1279 | state->dest, PR_TRUE); | |
1280 | if (state != NULL) { | |
1281 | /* | |
1282 | * Do the "before" field notification. | |
1283 | */ | |
1284 | sec_asn1d_notify_before (state->top, state->dest, state->depth); | |
1285 | state = sec_asn1d_init_state_based_on_template (state, | |
822b670c | 1286 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 | 1287 | } |
d8f41ccd | 1288 | (void) state; |
b1ab9ed8 A |
1289 | break; |
1290 | ||
1291 | case SEC_ASN1_SET: /* XXX SET is not really implemented */ | |
1292 | /* | |
1293 | * XXX A plain SET requires special handling; scanning of a | |
1294 | * template to see where a field should go (because by definition, | |
1295 | * they are not in any particular order, and you have to look at | |
1296 | * each tag to disambiguate what the field is). We may never | |
1297 | * implement this because in practice, it seems to be unused. | |
1298 | */ | |
1299 | dprintf("decodeError: prepare for contents SEC_ASN1_SET\n"); | |
1300 | PORT_Assert(0); | |
1301 | PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */ | |
1302 | state->top->status = decodeError; | |
1303 | break; | |
1304 | ||
1305 | case SEC_ASN1_NULL: | |
1306 | /* | |
1307 | * The NULL type, by definition, is "nothing", content length of zero. | |
1308 | * An indefinite-length encoding is not alloweed. | |
1309 | */ | |
1310 | if (state->contents_length || state->indefinite) { | |
1311 | dprintf("decodeError: prepare for contents indefinite NULL\n"); | |
1312 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1313 | state->top->status = decodeError; | |
1314 | break; | |
1315 | } | |
1316 | if (state->dest != NULL) { | |
1317 | item = (SecAsn1Item *)(state->dest); | |
1318 | item->Data = NULL; | |
1319 | item->Length = 0; | |
1320 | } | |
1321 | state->place = afterEndOfContents; | |
1322 | break; | |
1323 | ||
1324 | case SEC_ASN1_BMP_STRING: | |
1325 | /* Error if length is not divisable by 2 */ | |
1326 | if (state->contents_length % 2) { | |
1327 | dprintf("decodeError: prepare for contents odd length BMP_STRING\n"); | |
1328 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1329 | state->top->status = decodeError; | |
1330 | break; | |
1331 | } | |
1332 | /* otherwise, handle as other string types */ | |
1333 | goto regular_string_type; | |
1334 | ||
1335 | case SEC_ASN1_UNIVERSAL_STRING: | |
1336 | /* Error if length is not divisable by 4 */ | |
1337 | if (state->contents_length % 4) { | |
1338 | dprintf("decodeError: prepare for contents odd length UNIV_STRING\n"); | |
1339 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1340 | state->top->status = decodeError; | |
1341 | break; | |
1342 | } | |
1343 | /* otherwise, handle as other string types */ | |
1344 | goto regular_string_type; | |
1345 | ||
1346 | case SEC_ASN1_SKIP: | |
1347 | case SEC_ASN1_ANY: | |
1348 | case SEC_ASN1_ANY_CONTENTS: | |
1349 | /* | |
1350 | * These are not (necessarily) strings, but they need nearly | |
1351 | * identical handling (especially when we need to deal with | |
1352 | * constructed sub-pieces), so we pretend they are. | |
1353 | */ | |
1354 | /* fallthru */ | |
1355 | regular_string_type: | |
1356 | case SEC_ASN1_BIT_STRING: | |
1357 | case SEC_ASN1_IA5_STRING: | |
1358 | case SEC_ASN1_OCTET_STRING: | |
1359 | case SEC_ASN1_PRINTABLE_STRING: | |
1360 | case SEC_ASN1_T61_STRING: | |
1361 | case SEC_ASN1_UTC_TIME: | |
1362 | case SEC_ASN1_UTF8_STRING: | |
1363 | case SEC_ASN1_VISIBLE_STRING: | |
1364 | /* | |
1365 | * We are allocating for a primitive or a constructed string. | |
1366 | * If it is a constructed string, it may also be indefinite-length. | |
1367 | * If it is primitive, the length can (legally) be zero. | |
1368 | * Our first order of business is to allocate the memory for | |
1369 | * the string, if we can (if we know the length). | |
1370 | */ | |
1371 | item = (SecAsn1Item *)(state->dest); | |
1372 | ||
1373 | /* | |
1374 | * If the item is a definite-length constructed string, then | |
1375 | * the contents_length is actually larger than what we need | |
1376 | * (because it also counts each intermediate header which we | |
1377 | * will be throwing away as we go), but it is a perfectly good | |
1378 | * upper bound that we just allocate anyway, and then concat | |
1379 | * as we go; we end up wasting a few extra bytes but save a | |
1380 | * whole other copy. | |
1381 | */ | |
1382 | alloc_len = state->contents_length; | |
1383 | poolp = NULL; /* quiet compiler warnings about unused... */ | |
1384 | ||
1385 | if (item == NULL || state->top->filter_only) { | |
1386 | if (item != NULL) { | |
1387 | item->Data = NULL; | |
1388 | item->Length = 0; | |
1389 | } | |
1390 | alloc_len = 0; | |
1391 | } else if (state->substring) { | |
1392 | /* | |
1393 | * If we are a substring of a constructed string, then we may | |
1394 | * not have to allocate anything (because our parent, the | |
1395 | * actual constructed string, did it for us). If we are a | |
1396 | * substring and we *do* have to allocate, that means our | |
1397 | * parent is an indefinite-length, so we allocate from our pool; | |
1398 | * later our parent will copy our string into the aggregated | |
1399 | * whole and free our pool allocation. | |
1400 | */ | |
1401 | if (item->Data == NULL) { | |
1402 | PORT_Assert (item->Length == 0); | |
1403 | poolp = state->top->our_pool; | |
1404 | } else { | |
1405 | alloc_len = 0; | |
1406 | } | |
1407 | } else { | |
1408 | item->Length = 0; | |
1409 | item->Data = NULL; | |
1410 | poolp = state->top->their_pool; | |
1411 | } | |
1412 | ||
1413 | if (alloc_len || ((! state->indefinite) | |
1414 | && (state->subitems_head != NULL))) { | |
1415 | struct subitem *subitem; | |
1416 | unsigned long len; | |
1417 | ||
d8f41ccd A |
1418 | PORT_Assert (item!=NULL); |
1419 | if (item==NULL) { | |
1420 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1421 | state->top->status = decodeError; | |
1422 | return; | |
1423 | } | |
1424 | PORT_Assert (item->Length == 0 && item->Data == NULL); | |
b1ab9ed8 A |
1425 | /* |
1426 | * Check for and handle an ANY which has stashed aside the | |
1427 | * header (identifier and length) bytes for us to include | |
1428 | * in the saved contents. | |
1429 | */ | |
1430 | if (state->subitems_head != NULL) { | |
1431 | PORT_Assert (state->underlying_kind == SEC_ASN1_ANY); | |
1432 | for (subitem = state->subitems_head; | |
1433 | subitem != NULL; subitem = subitem->next) | |
1434 | alloc_len += subitem->len; | |
1435 | } | |
1436 | ||
6b200bc3 A |
1437 | if (item) { |
1438 | item->Data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len); | |
1439 | } | |
1440 | if (item == NULL || item->Data == NULL) { | |
b1ab9ed8 A |
1441 | dprintf("decodeError: prepare for contents zalloc\n"); |
1442 | state->top->status = decodeError; | |
1443 | break; | |
1444 | } | |
1445 | ||
1446 | len = 0; | |
1447 | for (subitem = state->subitems_head; | |
1448 | subitem != NULL; subitem = subitem->next) { | |
1449 | PORT_Memcpy (item->Data + len, subitem->data, subitem->len); | |
1450 | len += subitem->len; | |
1451 | } | |
1452 | item->Length = len; | |
1453 | ||
1454 | /* | |
1455 | * Because we use arenas and have a mark set, we later free | |
1456 | * everything we have allocated, so this does *not* present | |
1457 | * a memory leak (it is just temporarily left dangling). | |
1458 | */ | |
1459 | state->subitems_head = state->subitems_tail = NULL; | |
1460 | } | |
1461 | ||
1462 | if (state->contents_length == 0 && (! state->indefinite)) { | |
1463 | /* | |
1464 | * A zero-length simple or constructed string; we are done. | |
1465 | */ | |
1466 | state->place = afterEndOfContents; | |
1467 | } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) { | |
1468 | const SecAsn1Template *sub; | |
1469 | ||
1470 | switch (state->underlying_kind) { | |
1471 | case SEC_ASN1_ANY: | |
1472 | case SEC_ASN1_ANY_CONTENTS: | |
1473 | sub = kSecAsn1AnyTemplate; | |
1474 | break; | |
1475 | case SEC_ASN1_BIT_STRING: | |
1476 | sub = kSecAsn1BitStringTemplate; | |
1477 | break; | |
1478 | case SEC_ASN1_BMP_STRING: | |
1479 | sub = kSecAsn1BMPStringTemplate; | |
1480 | break; | |
1481 | case SEC_ASN1_GENERALIZED_TIME: | |
1482 | sub = kSecAsn1GeneralizedTimeTemplate; | |
1483 | break; | |
1484 | case SEC_ASN1_IA5_STRING: | |
1485 | sub = kSecAsn1IA5StringTemplate; | |
1486 | break; | |
1487 | case SEC_ASN1_OCTET_STRING: | |
1488 | sub = kSecAsn1OctetStringTemplate; | |
1489 | break; | |
1490 | case SEC_ASN1_PRINTABLE_STRING: | |
1491 | sub = kSecAsn1PrintableStringTemplate; | |
1492 | break; | |
1493 | case SEC_ASN1_T61_STRING: | |
1494 | sub = kSecAsn1T61StringTemplate; | |
1495 | break; | |
1496 | case SEC_ASN1_UNIVERSAL_STRING: | |
1497 | sub = kSecAsn1UniversalStringTemplate; | |
1498 | break; | |
1499 | case SEC_ASN1_UTC_TIME: | |
1500 | sub = kSecAsn1UTCTimeTemplate; | |
1501 | break; | |
1502 | case SEC_ASN1_UTF8_STRING: | |
1503 | sub = kSecAsn1UTF8StringTemplate; | |
1504 | break; | |
1505 | case SEC_ASN1_VISIBLE_STRING: | |
1506 | sub = kSecAsn1VisibleStringTemplate; | |
1507 | break; | |
1508 | case SEC_ASN1_SKIP: | |
1509 | sub = kSecAsn1SkipTemplate; | |
1510 | break; | |
1511 | default: /* redundant given outer switch cases, but */ | |
1512 | PORT_Assert(0); /* the compiler does not seem to know that, */ | |
1513 | sub = NULL; /* so just do enough to quiet it. */ | |
1514 | break; | |
1515 | } | |
1516 | ||
1517 | state->place = duringConstructedString; | |
1518 | state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE); | |
1519 | if (state != NULL) { | |
1520 | state->substring = PR_TRUE; /* XXX propogate? */ | |
1521 | state = sec_asn1d_init_state_based_on_template (state, | |
822b670c | 1522 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
1523 | } |
1524 | } else if (state->indefinite) { | |
1525 | /* | |
1526 | * An indefinite-length string *must* be constructed! | |
1527 | */ | |
1528 | dprintf("decodeError: prepare for contents indefinite not construncted\n"); | |
1529 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1530 | state->top->status = decodeError; | |
1531 | } else { | |
1532 | /* | |
1533 | * A non-zero-length simple string. | |
1534 | */ | |
1535 | if (state->underlying_kind == SEC_ASN1_BIT_STRING) | |
1536 | state->place = beforeBitString; | |
1537 | else | |
1538 | state->place = duringLeaf; | |
1539 | } | |
d8f41ccd | 1540 | (void) state; |
b1ab9ed8 A |
1541 | break; |
1542 | ||
1543 | default: | |
1544 | /* | |
1545 | * We are allocating for a simple leaf item. | |
1546 | */ | |
1547 | if (state->contents_length) { | |
1548 | if (state->dest != NULL) { | |
1549 | item = (SecAsn1Item *)(state->dest); | |
1550 | item->Length = 0; | |
1551 | if (state->top->filter_only) { | |
1552 | item->Data = NULL; | |
1553 | } else { | |
1554 | item->Data = (unsigned char*) | |
1555 | sec_asn1d_zalloc (state->top->their_pool, | |
1556 | state->contents_length); | |
1557 | if (item->Data == NULL) { | |
1558 | dprintf("decodeError: prepare for contents zalloc\n"); | |
1559 | state->top->status = decodeError; | |
1560 | return; | |
1561 | } | |
1562 | } | |
1563 | } | |
1564 | state->place = duringLeaf; | |
1565 | } else { | |
1566 | /* | |
1567 | * An indefinite-length or zero-length item is not allowed. | |
1568 | * (All legal cases of such were handled above.) | |
1569 | */ | |
1570 | dprintf("decodeError: prepare for contents indefinite zero len \n"); | |
1571 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1572 | state->top->status = decodeError; | |
1573 | } | |
1574 | } | |
1575 | } | |
1576 | ||
1577 | ||
1578 | static void | |
1579 | sec_asn1d_free_child (sec_asn1d_state *state, PRBool error) | |
1580 | { | |
1581 | if (state->child != NULL) { | |
1582 | PORT_Assert (error || state->child->consumed == 0); | |
1583 | PORT_Assert (state->our_mark != NULL); | |
1584 | PORT_ArenaRelease (state->top->our_pool, state->our_mark); | |
1585 | if (error && state->top->their_pool == NULL) { | |
1586 | /* | |
1587 | * XXX We need to free anything allocated. | |
1588 | * At this point, we failed in the middle of decoding. But we | |
1589 | * can't free the data we previously allocated with PR_Malloc | |
1590 | * unless we keep track of every pointer. So instead we have a | |
1591 | * memory leak when decoding fails half-way, unless an arena is | |
1592 | * used. See bug 95311 . | |
1593 | */ | |
1594 | } | |
1595 | state->child = NULL; | |
1596 | state->our_mark = NULL; | |
1597 | } else { | |
1598 | /* | |
1599 | * It is important that we do not leave a mark unreleased/unmarked. | |
1600 | * But I do not think we should ever have one set in this case, only | |
1601 | * if we had a child (handled above). So check for that. If this | |
1602 | * assertion should ever get hit, then we probably need to add code | |
1603 | * here to release back to our_mark (and then set our_mark to NULL). | |
1604 | */ | |
1605 | PORT_Assert (state->our_mark == NULL); | |
1606 | } | |
1607 | state->place = beforeEndOfContents; | |
1608 | } | |
1609 | ||
1610 | ||
1611 | /* We have just saved an entire encoded ASN.1 object (type) for a SAVE | |
1612 | ** template, and now in the next template, we are going to decode that | |
1613 | ** saved data by calling SEC_ASN1DecoderUpdate recursively. | |
1614 | ** If that recursive call fails with needBytes, it is a fatal error, | |
1615 | ** because the encoded object should have been complete. | |
1616 | ** If that recursive call fails with decodeError, it will have already | |
1617 | ** cleaned up the state stack, so we must bail out quickly. | |
1618 | ** | |
1619 | ** These checks of the status returned by the recursive call are now | |
1620 | ** done in the caller of this function, immediately after it returns. | |
1621 | */ | |
1622 | static void | |
1623 | sec_asn1d_reuse_encoding (sec_asn1d_state *state) | |
1624 | { | |
1625 | sec_asn1d_state *child; | |
1626 | unsigned long consumed; | |
1627 | SecAsn1Item *item; | |
1628 | void *dest; | |
1629 | ||
1630 | ||
1631 | child = state->child; | |
1632 | PORT_Assert (child != NULL); | |
1633 | ||
1634 | consumed = child->consumed; | |
1635 | child->consumed = 0; | |
1636 | ||
1637 | item = (SecAsn1Item *)(state->dest); | |
1638 | PORT_Assert (item != NULL); | |
1639 | ||
1640 | PORT_Assert (item->Length == consumed); | |
1641 | ||
1642 | /* | |
1643 | * Free any grandchild. | |
1644 | */ | |
1645 | sec_asn1d_free_child (child, PR_FALSE); | |
1646 | ||
1647 | /* | |
1648 | * Notify after the SAVE field. | |
1649 | */ | |
1650 | sec_asn1d_notify_after (state->top, state->dest, state->depth); | |
1651 | ||
1652 | /* | |
1653 | * Adjust to get new dest and move forward. | |
1654 | */ | |
1655 | dest = (char *)state->dest - state->theTemplate->offset; | |
1656 | state->theTemplate++; | |
1657 | child->dest = (char *)dest + state->theTemplate->offset; | |
1658 | child->theTemplate = state->theTemplate; | |
1659 | ||
1660 | /* | |
1661 | * Notify before the "real" field. | |
1662 | */ | |
1663 | PORT_Assert (state->depth == child->depth); | |
1664 | sec_asn1d_notify_before (state->top, child->dest, child->depth); | |
1665 | ||
1666 | /* | |
1667 | * This will tell DecoderUpdate to return when it is done. | |
1668 | */ | |
1669 | state->place = afterSaveEncoding; | |
1670 | ||
1671 | /* | |
1672 | * We already have a child; "push" it by making it current. | |
1673 | */ | |
1674 | state->top->current = child; | |
1675 | ||
1676 | /* | |
1677 | * And initialize it so it is ready to parse. | |
1678 | */ | |
1679 | (void) sec_asn1d_init_state_based_on_template(child, | |
822b670c A |
1680 | (char *) item->Data /* __APPLE__ */, |
1681 | item->Length /* __APPLE__ */); | |
b1ab9ed8 A |
1682 | |
1683 | /* | |
1684 | * Now parse that out of our data. | |
1685 | */ | |
1686 | if (SEC_ASN1DecoderUpdate (state->top, | |
1687 | (char *) item->Data, item->Length) != SECSuccess) | |
1688 | return; | |
1689 | if (state->top->status == needBytes) { | |
1690 | return; | |
1691 | } | |
1692 | ||
1693 | PORT_Assert (state->top->current == state); | |
1694 | PORT_Assert (state->child == child); | |
1695 | ||
1696 | /* | |
1697 | * That should have consumed what we consumed before. | |
1698 | */ | |
1699 | PORT_Assert (consumed == child->consumed); | |
1700 | child->consumed = 0; | |
1701 | ||
1702 | /* | |
1703 | * Done. | |
1704 | */ | |
1705 | state->consumed += consumed; | |
1706 | child->place = notInUse; | |
1707 | state->place = afterEndOfContents; | |
1708 | } | |
1709 | ||
1710 | ||
1711 | static unsigned long | |
1712 | sec_asn1d_parse_leaf (sec_asn1d_state *state, | |
1713 | const char *buf, unsigned long len) | |
1714 | { | |
1715 | SecAsn1Item *item; | |
1716 | unsigned long bufLen; | |
1717 | ||
1718 | if (len == 0) { | |
1719 | state->top->status = needBytes; | |
1720 | return 0; | |
1721 | } | |
1722 | ||
1723 | if (state->pending < len) | |
1724 | len = state->pending; | |
1725 | ||
1726 | bufLen = len; | |
1727 | ||
1728 | item = (SecAsn1Item *)(state->dest); | |
1729 | if (item != NULL && item->Data != NULL) { | |
1730 | /* Strip leading zeroes when target is unsigned integer */ | |
1731 | if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */ | |
1732 | item->Length == 0 && /* MSB */ | |
1733 | #ifdef __APPLE__ | |
1734 | !(state->underlying_kind & SEC_ASN1_SIGNED_INT)) | |
1735 | #else | |
1736 | item->type == siUnsignedInteger) /* unsigned */ | |
1737 | #endif | |
1738 | { | |
1739 | while (len > 1 && buf[0] == 0) { /* leading 0 */ | |
1740 | buf++; | |
1741 | len--; | |
1742 | } | |
1743 | } | |
e3d460c9 A |
1744 | unsigned long offset = item->Length; |
1745 | if (state->underlying_kind == SEC_ASN1_BIT_STRING) { | |
1746 | // The previous bit string must have no unused bits. | |
1747 | if (item->Length & 0x7) { | |
1748 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1749 | state->top->status = decodeError; | |
1750 | return 0; | |
1751 | } | |
1752 | // If this is a bit string, the length is bits, not bytes. | |
1753 | offset = item->Length >> 3; | |
1754 | } | |
1755 | if (state->underlying_kind == SEC_ASN1_BIT_STRING) { | |
1756 | // Protect against overflow during the bytes-to-bits conversion. | |
1757 | if (len >= (ULONG_MAX >> 3) + 1) { | |
1758 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1759 | state->top->status = decodeError; | |
1760 | return 0; | |
1761 | } | |
1762 | unsigned long len_in_bits = (len << 3) - state->bit_string_unused_bits; | |
1763 | // Protect against overflow when computing the total length in bits. | |
1764 | if (UINT_MAX - item->Length < len_in_bits) { | |
1765 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1766 | state->top->status = decodeError; | |
1767 | return 0; | |
1768 | } | |
1769 | item->Length += len_in_bits; | |
1770 | } else { | |
1771 | if (UINT_MAX - item->Length < len) { | |
1772 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1773 | state->top->status = decodeError; | |
1774 | return 0; | |
1775 | } | |
1776 | item->Length += len; | |
1777 | } | |
1778 | PORT_Memcpy (item->Data + offset, buf, len); | |
b1ab9ed8 A |
1779 | } |
1780 | state->pending -= bufLen; | |
1781 | if (state->pending == 0) | |
1782 | state->place = beforeEndOfContents; | |
1783 | ||
1784 | return bufLen; | |
1785 | } | |
1786 | ||
1787 | ||
1788 | static unsigned long | |
1789 | sec_asn1d_parse_bit_string (sec_asn1d_state *state, | |
1790 | const char *buf, unsigned long len) | |
1791 | { | |
1792 | unsigned char byte; | |
1793 | ||
1794 | /*PORT_Assert (state->pending > 0); */ | |
1795 | PORT_Assert (state->place == beforeBitString); | |
1796 | ||
1797 | if ((state->pending == 0) || (state->contents_length == 1)) { | |
1798 | if (state->dest != NULL) { | |
1799 | SecAsn1Item *item = (SecAsn1Item *)(state->dest); | |
1800 | item->Data = NULL; | |
1801 | item->Length = 0; | |
1802 | state->place = beforeEndOfContents; | |
1803 | } | |
1804 | if(state->contents_length == 1) { | |
1805 | /* skip over (unused) remainder byte */ | |
1806 | return 1; | |
1807 | } | |
1808 | else { | |
1809 | return 0; | |
1810 | } | |
1811 | } | |
1812 | ||
1813 | if (len == 0) { | |
1814 | state->top->status = needBytes; | |
1815 | return 0; | |
1816 | } | |
1817 | ||
1818 | byte = (unsigned char) *buf; | |
1819 | if (byte > 7) { | |
1820 | dprintf("decodeError: parse_bit_string remainder oflow\n"); | |
1821 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1822 | state->top->status = decodeError; | |
1823 | return 0; | |
1824 | } | |
1825 | ||
1826 | state->bit_string_unused_bits = byte; | |
1827 | state->place = duringBitString; | |
1828 | state->pending -= 1; | |
1829 | ||
1830 | return 1; | |
1831 | } | |
1832 | ||
1833 | ||
1834 | static unsigned long | |
1835 | sec_asn1d_parse_more_bit_string (sec_asn1d_state *state, | |
1836 | const char *buf, unsigned long len) | |
1837 | { | |
1838 | PORT_Assert (state->place == duringBitString); | |
1839 | if (state->pending == 0) { | |
1840 | /* An empty bit string with some unused bits is invalid. */ | |
1841 | if (state->bit_string_unused_bits) { | |
1842 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1843 | state->top->status = decodeError; | |
1844 | } else { | |
1845 | /* An empty bit string with no unused bits is OK. */ | |
1846 | state->place = beforeEndOfContents; | |
1847 | } | |
1848 | return 0; | |
1849 | } | |
1850 | ||
1851 | len = sec_asn1d_parse_leaf (state, buf, len); | |
b1ab9ed8 A |
1852 | |
1853 | return len; | |
1854 | } | |
1855 | ||
1856 | ||
1857 | /* | |
1858 | * XXX All callers should be looking at return value to detect | |
1859 | * out-of-memory errors (and stop!). | |
1860 | */ | |
1861 | static struct subitem * | |
1862 | sec_asn1d_add_to_subitems (sec_asn1d_state *state, | |
1863 | const void *data, unsigned long len, | |
1864 | PRBool copy_data) | |
1865 | { | |
1866 | struct subitem *thing; | |
1867 | ||
1868 | thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool, | |
1869 | sizeof (struct subitem)); | |
1870 | if (thing == NULL) { | |
1871 | dprintf("decodeError: zalloc\n"); | |
1872 | state->top->status = decodeError; | |
1873 | return NULL; | |
1874 | } | |
1875 | ||
1876 | if (copy_data) { | |
1877 | void *copy; | |
1878 | copy = sec_asn1d_alloc (state->top->our_pool, len); | |
1879 | if (copy == NULL) { | |
1880 | dprintf("decodeError: alloc\n"); | |
1881 | state->top->status = decodeError; | |
d8f41ccd A |
1882 | if (!state->top->our_pool) |
1883 | PORT_Free(thing); | |
b1ab9ed8 A |
1884 | return NULL; |
1885 | } | |
1886 | PORT_Memcpy (copy, data, len); | |
1887 | thing->data = copy; | |
1888 | } else { | |
1889 | thing->data = data; | |
1890 | } | |
1891 | thing->len = len; | |
1892 | thing->next = NULL; | |
1893 | ||
1894 | if (state->subitems_head == NULL) { | |
1895 | PORT_Assert (state->subitems_tail == NULL); | |
1896 | state->subitems_head = state->subitems_tail = thing; | |
1897 | } else { | |
1898 | state->subitems_tail->next = thing; | |
1899 | state->subitems_tail = thing; | |
1900 | } | |
1901 | ||
1902 | return thing; | |
1903 | } | |
1904 | ||
1905 | ||
1906 | static void | |
1907 | sec_asn1d_record_any_header (sec_asn1d_state *state, | |
1908 | const char *buf, | |
1909 | unsigned long len) | |
1910 | { | |
1911 | SecAsn1Item *item; | |
1912 | ||
1913 | item = (SecAsn1Item *)(state->dest); | |
1914 | if (item != NULL && item->Data != NULL) { | |
1915 | PORT_Assert (state->substring); | |
1916 | PORT_Memcpy (item->Data + item->Length, buf, len); | |
1917 | item->Length += len; | |
1918 | } else { | |
1919 | sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE); | |
1920 | } | |
1921 | } | |
1922 | ||
1923 | ||
1924 | /* | |
1925 | * We are moving along through the substrings of a constructed string, | |
1926 | * and have just finished parsing one -- we need to save our child data | |
1927 | * (if the child was not already writing directly into the destination) | |
1928 | * and then move forward by one. | |
1929 | * | |
1930 | * We also have to detect when we are done: | |
1931 | * - a definite-length encoding stops when our pending value hits 0 | |
1932 | * - an indefinite-length encoding stops when our child is empty | |
1933 | * (which means it was the end-of-contents octets) | |
1934 | */ | |
1935 | static void | |
1936 | sec_asn1d_next_substring (sec_asn1d_state *state) | |
1937 | { | |
1938 | sec_asn1d_state *child; | |
1939 | SecAsn1Item *item; | |
1940 | unsigned long child_consumed; | |
1941 | PRBool done; | |
1942 | ||
1943 | PORT_Assert (state->place == duringConstructedString); | |
1944 | PORT_Assert (state->child != NULL); | |
1945 | ||
1946 | child = state->child; | |
1947 | ||
1948 | child_consumed = child->consumed; | |
1949 | child->consumed = 0; | |
1950 | state->consumed += child_consumed; | |
1951 | ||
1952 | done = PR_FALSE; | |
1953 | ||
1954 | if (state->pending) { | |
1955 | PORT_Assert (!state->indefinite); | |
1956 | if( child_consumed > state->pending ) { | |
1957 | dprintf("decodeError: next_substring consumed > pend\n"); | |
1958 | PORT_SetError (SEC_ERROR_BAD_DER); | |
1959 | state->top->status = decodeError; | |
1960 | return; | |
1961 | } | |
1962 | ||
1963 | state->pending -= child_consumed; | |
1964 | if (state->pending == 0) | |
1965 | done = PR_TRUE; | |
1966 | } else { | |
1967 | PORT_Assert (state->indefinite); | |
1968 | ||
1969 | item = (SecAsn1Item *)(child->dest); | |
e0e0d90e A |
1970 | /* |
1971 | * Iterate over ancestors to determine if any have definite length. If so, | |
1972 | * space has already been allocated for the substrings and we don't need to | |
1973 | * save them for concatenation. | |
1974 | */ | |
1975 | PRBool copying_in_place = PR_FALSE; | |
1976 | sec_asn1d_state *temp_state = state; | |
1977 | while (temp_state && item == temp_state->dest && temp_state->indefinite) { | |
1978 | sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state); | |
1979 | if (!parent || parent->underlying_kind != temp_state->underlying_kind) { | |
1980 | break; | |
1981 | } | |
1982 | if (!parent->indefinite) { | |
1983 | copying_in_place = PR_TRUE; | |
1984 | break; | |
1985 | } | |
1986 | temp_state = parent; | |
1987 | } | |
1988 | if (item != NULL && item->Data != NULL && !copying_in_place) { | |
b1ab9ed8 A |
1989 | /* |
1990 | * Save the string away for later concatenation. | |
1991 | */ | |
1992 | PORT_Assert (item->Data != NULL); | |
1993 | sec_asn1d_add_to_subitems (state, item->Data, item->Length, PR_FALSE); | |
1994 | /* | |
1995 | * Clear the child item for the next round. | |
1996 | */ | |
1997 | item->Data = NULL; | |
1998 | item->Length = 0; | |
1999 | } | |
2000 | ||
2001 | /* | |
2002 | * If our child was just our end-of-contents octets, we are done. | |
2003 | */ | |
2004 | if (child->endofcontents) | |
2005 | done = PR_TRUE; | |
2006 | } | |
2007 | ||
2008 | /* | |
2009 | * Stop or do the next one. | |
2010 | */ | |
2011 | if (done) { | |
2012 | child->place = notInUse; | |
2013 | state->place = afterConstructedString; | |
2014 | } else { | |
2015 | sec_asn1d_scrub_state (child); | |
2016 | state->top->current = child; | |
2017 | } | |
2018 | } | |
2019 | ||
2020 | ||
2021 | /* | |
2022 | * We are doing a SET OF or SEQUENCE OF, and have just finished an item. | |
2023 | */ | |
2024 | static void | |
2025 | sec_asn1d_next_in_group (sec_asn1d_state *state, | |
822b670c A |
2026 | const char *buf, /* __APPLE__ */ |
2027 | size_t len /* __APPLE__ */) | |
b1ab9ed8 A |
2028 | { |
2029 | sec_asn1d_state *child; | |
2030 | unsigned long child_consumed; | |
2031 | ||
2032 | PORT_Assert (state->place == duringGroup); | |
2033 | PORT_Assert (state->child != NULL); | |
2034 | ||
2035 | child = state->child; | |
2036 | ||
2037 | child_consumed = child->consumed; | |
2038 | child->consumed = 0; | |
2039 | state->consumed += child_consumed; | |
2040 | ||
2041 | /* | |
2042 | * If our child was just our end-of-contents octets, we are done. | |
2043 | */ | |
2044 | #ifdef __APPLE__ | |
2045 | /* | |
2046 | * Without the check for !child->indefinite, this path could | |
2047 | * be taken erroneously if the child is indefinite! | |
2048 | */ | |
2049 | if(child->endofcontents && !child->indefinite) { | |
2050 | #else | |
2051 | if (child->endofcontents) { | |
2052 | #endif /* __APPLE__ */ | |
2053 | /* XXX I removed the PORT_Assert (child->dest == NULL) because there | |
2054 | * was a bug in that a template that was a sequence of which also had | |
2055 | * a child of a sequence of, in an indefinite group was not working | |
2056 | * properly. This fix seems to work, (added the if statement below), | |
2057 | * and nothing appears broken, but I am putting this note here just | |
2058 | * in case. */ | |
2059 | /* | |
2060 | * XXX No matter how many times I read that comment, | |
2061 | * I cannot figure out what case he was fixing. I believe what he | |
2062 | * did was deliberate, so I am loathe to touch it. I need to | |
2063 | * understand how it could ever be that child->dest != NULL but | |
2064 | * child->endofcontents is true, and why it is important to check | |
2065 | * that state->subitems_head is NULL. This really needs to be | |
2066 | * figured out, as I am not sure if the following code should be | |
2067 | * compensating for "offset", as is done a little farther below | |
2068 | * in the more normal case. | |
2069 | */ | |
2070 | PORT_Assert (state->indefinite); | |
2071 | PORT_Assert (state->pending == 0); | |
2072 | if(child->dest && !state->subitems_head) { | |
2073 | sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE); | |
2074 | child->dest = NULL; | |
2075 | } | |
2076 | ||
2077 | child->place = notInUse; | |
2078 | state->place = afterGroup; | |
2079 | return; | |
2080 | } | |
2081 | ||
2082 | /* | |
2083 | * Do the "after" field notification for next in group. | |
2084 | */ | |
2085 | sec_asn1d_notify_after (state->top, child->dest, child->depth); | |
2086 | ||
2087 | /* | |
2088 | * Save it away (unless we are not storing). | |
2089 | */ | |
2090 | if (child->dest != NULL) { | |
2091 | void *dest; | |
2092 | ||
2093 | dest = child->dest; | |
2094 | dest = (char *)dest - child->theTemplate->offset; | |
2095 | sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE); | |
2096 | child->dest = NULL; | |
2097 | } | |
2098 | ||
2099 | /* | |
2100 | * Account for those bytes; see if we are done. | |
2101 | */ | |
2102 | if (state->pending) { | |
2103 | PORT_Assert (!state->indefinite); | |
2104 | if( child_consumed > state->pending ) { | |
2105 | dprintf("decodeError: next_in_group consumed > pend\n"); | |
2106 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2107 | state->top->status = decodeError; | |
2108 | return; | |
2109 | } | |
2110 | ||
2111 | state->pending -= child_consumed; | |
2112 | if (state->pending == 0) { | |
2113 | child->place = notInUse; | |
2114 | state->place = afterGroup; | |
2115 | return; | |
2116 | } | |
2117 | } | |
2118 | ||
2119 | /* | |
2120 | * Do the "before" field notification for next item in group. | |
2121 | */ | |
2122 | sec_asn1d_notify_before (state->top, child->dest, child->depth); | |
2123 | ||
2124 | /* | |
2125 | * Now we do the next one. | |
2126 | */ | |
2127 | sec_asn1d_scrub_state (child); | |
2128 | ||
2129 | /* Initialize child state from the template */ | |
822b670c | 2130 | sec_asn1d_init_state_based_on_template(child, buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
2131 | |
2132 | state->top->current = child; | |
2133 | } | |
2134 | ||
2135 | ||
2136 | /* | |
2137 | * We are moving along through a sequence; move forward by one, | |
2138 | * (detecting end-of-sequence when it happens). | |
2139 | * XXX The handling of "missing" is ugly. Fix it. | |
2140 | */ | |
2141 | static void | |
2142 | sec_asn1d_next_in_sequence (sec_asn1d_state *state, | |
822b670c A |
2143 | const char *buf /* __APPLE__ */, |
2144 | size_t len /*__APPLE__*/) | |
b1ab9ed8 A |
2145 | { |
2146 | sec_asn1d_state *child; | |
2147 | unsigned long child_consumed; | |
2148 | PRBool child_missing; | |
2149 | ||
2150 | PORT_Assert (state->place == duringSequence); | |
2151 | PORT_Assert (state->child != NULL); | |
2152 | ||
2153 | child = state->child; | |
2154 | ||
2155 | /* | |
2156 | * Do the "after" field notification. | |
2157 | */ | |
2158 | sec_asn1d_notify_after (state->top, child->dest, child->depth); | |
2159 | ||
2160 | child_missing = (PRBool) child->missing; | |
2161 | child_consumed = child->consumed; | |
2162 | child->consumed = 0; | |
2163 | ||
2164 | /* | |
2165 | * Take care of accounting. | |
2166 | */ | |
2167 | if (child_missing) { | |
2168 | PORT_Assert (child->optional); | |
2169 | } else { | |
2170 | state->consumed += child_consumed; | |
2171 | /* | |
2172 | * Free any grandchild. | |
2173 | */ | |
2174 | sec_asn1d_free_child (child, PR_FALSE); | |
2175 | if (state->pending) { | |
2176 | PORT_Assert (!state->indefinite); | |
2177 | if( child_consumed > state->pending ) { | |
2178 | dprintf("decodeError: next_in_seq consumed > pend\n"); | |
2179 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2180 | state->top->status = decodeError; | |
2181 | return; | |
2182 | } | |
2183 | state->pending -= child_consumed; | |
2184 | if (state->pending == 0) { | |
2185 | child->theTemplate++; | |
2186 | while (child->theTemplate->kind != 0) { | |
2187 | if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) { | |
2188 | dprintf("decodeError: next_in_seq child not opt\n"); | |
2189 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2190 | state->top->status = decodeError; | |
2191 | return; | |
2192 | } | |
2193 | child->theTemplate++; | |
2194 | } | |
2195 | child->place = notInUse; | |
2196 | state->place = afterEndOfContents; | |
2197 | return; | |
2198 | } | |
2199 | } | |
2200 | } | |
2201 | ||
2202 | /* | |
2203 | * Move forward. | |
2204 | */ | |
2205 | child->theTemplate++; | |
2206 | if (child->theTemplate->kind == 0) { | |
2207 | /* | |
2208 | * We are done with this sequence. | |
2209 | */ | |
2210 | child->place = notInUse; | |
2211 | if (state->pending) { | |
2212 | dprintf("decodeError: next_in_seq notInUse still pending\n"); | |
2213 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2214 | state->top->status = decodeError; | |
2215 | } else if (child_missing) { | |
2216 | /* | |
2217 | * We got to the end, but have a child that started parsing | |
2218 | * and ended up "missing". The only legitimate reason for | |
2219 | * this is that we had one or more optional fields at the | |
2220 | * end of our sequence, and we were encoded indefinite-length, | |
2221 | * so when we went looking for those optional fields we | |
2222 | * found our end-of-contents octets instead. | |
2223 | * (Yes, this is ugly; dunno a better way to handle it.) | |
2224 | * So, first confirm the situation, and then mark that we | |
2225 | * are done. | |
2226 | */ | |
2227 | if (state->indefinite && child->endofcontents) { | |
2228 | PORT_Assert (child_consumed == 2); | |
2229 | if( child_consumed != 2 ) { | |
2230 | dprintf("decodeError: next_in_seq indef len != 2\n"); | |
2231 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2232 | state->top->status = decodeError; | |
2233 | } else { | |
2234 | state->consumed += child_consumed; | |
2235 | state->place = afterEndOfContents; | |
2236 | } | |
2237 | } else { | |
2238 | dprintf("decodeError: next_in_seq !indef, child missing\n"); | |
2239 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2240 | state->top->status = decodeError; | |
2241 | } | |
2242 | } else { | |
2243 | /* | |
2244 | * We have to finish out, maybe reading end-of-contents octets; | |
2245 | * let the normal logic do the right thing. | |
2246 | */ | |
2247 | state->place = beforeEndOfContents; | |
2248 | } | |
2249 | } else { | |
2250 | unsigned char child_found_tag_modifiers = 0; | |
2251 | unsigned long child_found_tag_number = 0; | |
2252 | ||
2253 | /* | |
2254 | * Reset state and push. | |
2255 | */ | |
2256 | if (state->dest != NULL) | |
2257 | child->dest = (char *)state->dest + child->theTemplate->offset; | |
2258 | ||
2259 | /* | |
2260 | * Do the "before" field notification. | |
2261 | */ | |
2262 | sec_asn1d_notify_before (state->top, child->dest, child->depth); | |
2263 | ||
2264 | if (child_missing) { /* if previous child was missing, copy the tag data we already have */ | |
2265 | child_found_tag_modifiers = child->found_tag_modifiers; | |
2266 | child_found_tag_number = child->found_tag_number; | |
2267 | } | |
2268 | state->top->current = child; | |
2269 | child = sec_asn1d_init_state_based_on_template (child, | |
822b670c A |
2270 | buf /* __APPLE__ */, |
2271 | len /* __APPLE__ */); | |
d8f41ccd | 2272 | if (child_missing && child) { |
b1ab9ed8 A |
2273 | child->place = afterIdentifier; |
2274 | child->found_tag_modifiers = child_found_tag_modifiers; | |
2275 | child->found_tag_number = child_found_tag_number; | |
2276 | child->consumed = child_consumed; | |
2277 | if (child->underlying_kind == SEC_ASN1_ANY | |
2278 | && !child->top->filter_only) { | |
2279 | /* | |
2280 | * If the new field is an ANY, and we are storing, then | |
2281 | * we need to save the tag out. We would have done this | |
2282 | * already in the normal case, but since we were looking | |
2283 | * for an optional field, and we did not find it, we only | |
2284 | * now realize we need to save the tag. | |
2285 | */ | |
2286 | unsigned char identifier; | |
2287 | ||
2288 | /* | |
2289 | * Check that we did not end up with a high tag; for that | |
2290 | * we need to re-encode the tag into multiple bytes in order | |
2291 | * to store it back to look like what we parsed originally. | |
2292 | * In practice this does not happen, but for completeness | |
2293 | * sake it should probably be made to work at some point. | |
2294 | */ | |
2295 | PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER); | |
2296 | identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number); | |
2297 | sec_asn1d_record_any_header (child, (char *) &identifier, 1); | |
2298 | } | |
2299 | } | |
2300 | } | |
2301 | } | |
2302 | ||
2303 | ||
2304 | static void | |
2305 | sec_asn1d_concat_substrings (sec_asn1d_state *state) | |
2306 | { | |
2307 | PORT_Assert (state->place == afterConstructedString); | |
2308 | ||
2309 | if (state->subitems_head != NULL) { | |
2310 | struct subitem *substring; | |
2311 | unsigned long alloc_len, item_len; | |
2312 | unsigned char *where; | |
2313 | SecAsn1Item *item; | |
2314 | PRBool is_bit_string; | |
2315 | ||
2316 | item_len = 0; | |
2317 | is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING) | |
2318 | ? PR_TRUE : PR_FALSE; | |
2319 | ||
2320 | substring = state->subitems_head; | |
2321 | while (substring != NULL) { | |
2322 | /* | |
2323 | * All bit-string substrings except the last one should be | |
2324 | * a clean multiple of 8 bits. | |
2325 | */ | |
e3d460c9 | 2326 | if (is_bit_string && (substring->next != NULL) |
b1ab9ed8 A |
2327 | && (substring->len & 0x7)) { |
2328 | dprintf("decodeError: sec_asn1d_concat_substrings align\n"); | |
2329 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2330 | state->top->status = decodeError; | |
2331 | return; | |
2332 | } | |
2333 | item_len += substring->len; | |
2334 | substring = substring->next; | |
2335 | } | |
2336 | ||
2337 | if (is_bit_string) { | |
2338 | #ifdef XP_WIN16 /* win16 compiler gets an internal error otherwise */ | |
2339 | alloc_len = (((long)item_len + 7) / 8); | |
2340 | #else | |
2341 | alloc_len = ((item_len + 7) >> 3); | |
2342 | #endif | |
2343 | } else { | |
2344 | /* | |
2345 | * Add 2 for the end-of-contents octets of an indefinite-length | |
2346 | * ANY that is *not* also an INNER. Because we zero-allocate | |
2347 | * below, all we need to do is increase the length here. | |
2348 | */ | |
2349 | if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite) | |
2350 | item_len += 2; | |
2351 | alloc_len = item_len; | |
2352 | } | |
2353 | ||
2354 | item = (SecAsn1Item *)(state->dest); | |
2355 | PORT_Assert (item != NULL); | |
2356 | PORT_Assert (item->Data == NULL); | |
2357 | item->Data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool, | |
2358 | alloc_len); | |
2359 | if (item->Data == NULL) { | |
2360 | dprintf("decodeError: zalloc\n"); | |
2361 | state->top->status = decodeError; | |
2362 | return; | |
2363 | } | |
2364 | item->Length = item_len; | |
2365 | ||
2366 | where = item->Data; | |
2367 | substring = state->subitems_head; | |
2368 | while (substring != NULL) { | |
2369 | if (is_bit_string) | |
2370 | item_len = (substring->len + 7) >> 3; | |
2371 | else | |
2372 | item_len = substring->len; | |
2373 | PORT_Memcpy (where, substring->data, item_len); | |
2374 | where += item_len; | |
2375 | substring = substring->next; | |
2376 | } | |
2377 | ||
2378 | /* | |
2379 | * Because we use arenas and have a mark set, we later free | |
2380 | * everything we have allocated, so this does *not* present | |
2381 | * a memory leak (it is just temporarily left dangling). | |
2382 | */ | |
2383 | state->subitems_head = state->subitems_tail = NULL; | |
2384 | } | |
2385 | ||
2386 | state->place = afterEndOfContents; | |
2387 | } | |
2388 | ||
2389 | ||
2390 | static void | |
2391 | sec_asn1d_concat_group (sec_asn1d_state *state) | |
2392 | { | |
2393 | const void ***placep; | |
2394 | ||
2395 | PORT_Assert (state->place == afterGroup); | |
2396 | ||
2397 | placep = (const void***)state->dest; | |
2398 | PORT_Assert(state->subitems_head == NULL || placep != NULL); | |
2399 | if (placep != NULL) { | |
2400 | struct subitem *item; | |
2401 | const void **group; | |
2402 | int count; | |
2403 | ||
2404 | count = 0; | |
2405 | item = state->subitems_head; | |
2406 | while (item != NULL) { | |
2407 | PORT_Assert (item->next != NULL || item == state->subitems_tail); | |
2408 | count++; | |
2409 | item = item->next; | |
2410 | } | |
2411 | ||
2412 | group = (const void**)sec_asn1d_zalloc (state->top->their_pool, | |
2413 | (count + 1) * (sizeof(void *))); | |
2414 | if (group == NULL) { | |
2415 | dprintf("decodeError: zalloc\n"); | |
2416 | state->top->status = decodeError; | |
2417 | return; | |
2418 | } | |
2419 | ||
2420 | *placep = group; | |
2421 | ||
2422 | item = state->subitems_head; | |
2423 | while (item != NULL) { | |
2424 | *group++ = item->data; | |
2425 | item = item->next; | |
2426 | } | |
2427 | *group = NULL; | |
2428 | ||
2429 | /* | |
2430 | * Because we use arenas and have a mark set, we later free | |
2431 | * everything we have allocated, so this does *not* present | |
2432 | * a memory leak (it is just temporarily left dangling). | |
2433 | */ | |
2434 | state->subitems_head = state->subitems_tail = NULL; | |
2435 | } | |
2436 | ||
2437 | state->place = afterEndOfContents; | |
2438 | } | |
2439 | ||
2440 | /* | |
2441 | * For those states that push a child to handle a subtemplate, | |
2442 | * "absorb" that child (transfer necessary information). | |
2443 | */ | |
2444 | static void | |
2445 | sec_asn1d_absorb_child (sec_asn1d_state *state) | |
2446 | { | |
2447 | /* | |
2448 | * There is absolutely supposed to be a child there. | |
2449 | */ | |
2450 | PORT_Assert (state->child != NULL); | |
2451 | ||
2452 | /* | |
2453 | * Inherit the missing status of our child, and do the ugly | |
2454 | * backing-up if necessary. | |
2455 | */ | |
2456 | state->missing = state->child->missing; | |
2457 | if (state->missing) { | |
2458 | state->found_tag_number = state->child->found_tag_number; | |
2459 | state->found_tag_modifiers = state->child->found_tag_modifiers; | |
2460 | state->endofcontents = state->child->endofcontents; | |
2461 | } | |
2462 | ||
2463 | /* | |
2464 | * Add in number of bytes consumed by child. | |
2465 | * (Only EXPLICIT should have already consumed bytes itself.) | |
2466 | */ | |
2467 | PORT_Assert (state->place == afterExplicit || state->consumed == 0); | |
2468 | state->consumed += state->child->consumed; | |
2469 | ||
2470 | /* | |
2471 | * Subtract from bytes pending; this only applies to a definite-length | |
2472 | * EXPLICIT field. | |
2473 | */ | |
2474 | if (state->pending) { | |
2475 | PORT_Assert (!state->indefinite); | |
2476 | PORT_Assert (state->place == afterExplicit); | |
2477 | ||
2478 | /* | |
2479 | * If we had a definite-length explicit, then what the child | |
2480 | * consumed should be what was left pending. | |
2481 | */ | |
2482 | if (state->pending != state->child->consumed) { | |
2483 | if (state->pending < state->child->consumed) { | |
2484 | dprintf("decodeError: absorb_child pending < consumed\n"); | |
2485 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2486 | state->top->status = decodeError; | |
2487 | return; | |
2488 | } | |
2489 | /* | |
2490 | * Okay, this is a hack. It *should* be an error whether | |
2491 | * pending is too big or too small, but it turns out that | |
2492 | * we had a bug in our *old* DER encoder that ended up | |
2493 | * counting an explicit header twice in the case where | |
2494 | * the underlying type was an ANY. So, because we cannot | |
2495 | * prevent receiving these (our own certificate server can | |
2496 | * send them to us), we need to be lenient and accept them. | |
2497 | * To do so, we need to pretend as if we read all of the | |
2498 | * bytes that the header said we would find, even though | |
2499 | * we actually came up short. | |
2500 | */ | |
2501 | state->consumed += (state->pending - state->child->consumed); | |
2502 | } | |
2503 | state->pending = 0; | |
2504 | } | |
2505 | ||
2506 | /* | |
2507 | * Indicate that we are done with child. | |
2508 | */ | |
2509 | state->child->consumed = 0; | |
2510 | ||
2511 | /* | |
2512 | * And move on to final state. | |
2513 | * (Technically everybody could move to afterEndOfContents except | |
2514 | * for an indefinite-length EXPLICIT; for simplicity though we assert | |
2515 | * that but let the end-of-contents code do the real determination.) | |
2516 | */ | |
2517 | PORT_Assert (state->place == afterExplicit || (! state->indefinite)); | |
2518 | state->place = beforeEndOfContents; | |
2519 | } | |
2520 | ||
2521 | ||
2522 | static void | |
2523 | sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state) | |
2524 | { | |
2525 | PORT_Assert (state->place == beforeEndOfContents); | |
2526 | ||
2527 | if (state->indefinite) { | |
2528 | state->place = duringEndOfContents; | |
2529 | state->pending = 2; | |
2530 | } else { | |
2531 | state->place = afterEndOfContents; | |
2532 | } | |
2533 | } | |
2534 | ||
2535 | ||
2536 | static unsigned long | |
2537 | sec_asn1d_parse_end_of_contents (sec_asn1d_state *state, | |
2538 | const char *buf, unsigned long len) | |
2539 | { | |
2540 | unsigned int i; | |
2541 | ||
2542 | PORT_Assert (state->pending <= 2); | |
2543 | PORT_Assert (state->place == duringEndOfContents); | |
2544 | ||
2545 | if (len == 0) { | |
2546 | state->top->status = needBytes; | |
2547 | return 0; | |
2548 | } | |
2549 | ||
2550 | if (state->pending < len) | |
2551 | len = state->pending; | |
2552 | ||
2553 | for (i = 0; i < len; i++) { | |
2554 | if (buf[i] != 0) { | |
2555 | /* | |
2556 | * We expect to find only zeros; if not, just give up. | |
2557 | */ | |
2558 | dprintf("decodeError: end of contents non zero\n"); | |
2559 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2560 | state->top->status = decodeError; | |
2561 | return 0; | |
2562 | } | |
2563 | } | |
2564 | ||
2565 | state->pending -= len; | |
2566 | ||
2567 | if (state->pending == 0) { | |
2568 | state->place = afterEndOfContents; | |
2569 | state->endofcontents = PR_TRUE; | |
2570 | } | |
2571 | ||
2572 | return len; | |
2573 | } | |
2574 | ||
2575 | ||
2576 | static void | |
2577 | sec_asn1d_pop_state (sec_asn1d_state *state) | |
2578 | { | |
2579 | #if 0 /* XXX I think this should always be handled explicitly by parent? */ | |
2580 | /* | |
2581 | * Account for our child. | |
2582 | */ | |
2583 | if (state->child != NULL) { | |
2584 | state->consumed += state->child->consumed; | |
2585 | if (state->pending) { | |
2586 | PORT_Assert (!state->indefinite); | |
2587 | if( state->child->consumed > state->pending ) { | |
2588 | dprintf("decodeError: pop_state pending < consumed\n"); | |
2589 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2590 | state->top->status = decodeError; | |
2591 | } else { | |
2592 | state->pending -= state->child->consumed; | |
2593 | } | |
2594 | } | |
2595 | state->child->consumed = 0; | |
2596 | } | |
2597 | #endif /* XXX */ | |
2598 | ||
2599 | /* | |
2600 | * Free our child. | |
2601 | */ | |
2602 | sec_asn1d_free_child (state, PR_FALSE); | |
2603 | ||
2604 | /* | |
2605 | * Just make my parent be the current state. It will then clean | |
2606 | * up after me and free me (or reuse me). | |
2607 | */ | |
2608 | state->top->current = state->parent; | |
2609 | } | |
2610 | ||
2611 | static sec_asn1d_state * | |
822b670c A |
2612 | sec_asn1d_before_choice (sec_asn1d_state *state, |
2613 | const char *buf /* __APPLE__ */, | |
2614 | size_t len /* __APPLE__ */) | |
b1ab9ed8 A |
2615 | { |
2616 | sec_asn1d_state *child; | |
2617 | ||
2618 | if( state->allocate ) { | |
2619 | void *dest; | |
2620 | ||
2621 | dest = sec_asn1d_zalloc(state->top->their_pool, | |
2622 | state->theTemplate->size); | |
2623 | if( (void *)NULL == dest ) { | |
2624 | dprintf("decodeError: zalloc\n"); | |
2625 | state->top->status = decodeError; | |
2626 | return (sec_asn1d_state *)NULL; | |
2627 | } | |
2628 | ||
2629 | state->dest = (char *)dest + state->theTemplate->offset; | |
2630 | } | |
2631 | ||
2632 | child = sec_asn1d_push_state(state->top, state->theTemplate + 1, | |
2633 | (char *)state->dest - state->theTemplate->offset, | |
2634 | PR_FALSE); | |
2635 | if( (sec_asn1d_state *)NULL == child ) { | |
2636 | return (sec_asn1d_state *)NULL; | |
2637 | } | |
2638 | ||
2639 | sec_asn1d_scrub_state(child); | |
2640 | child = sec_asn1d_init_state_based_on_template(child, | |
822b670c | 2641 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
2642 | if( (sec_asn1d_state *)NULL == child ) { |
2643 | return (sec_asn1d_state *)NULL; | |
2644 | } | |
2645 | ||
2646 | child->optional = PR_TRUE; | |
2647 | ||
2648 | state->place = duringChoice; | |
2649 | ||
2650 | return child; | |
2651 | } | |
2652 | ||
2653 | static sec_asn1d_state * | |
822b670c A |
2654 | sec_asn1d_during_choice (sec_asn1d_state *state, |
2655 | const char *buf, /* __APPLE__ */ | |
2656 | size_t len /* __APPLE__ */) | |
b1ab9ed8 A |
2657 | { |
2658 | sec_asn1d_state *child = state->child; | |
2659 | ||
2660 | PORT_Assert((sec_asn1d_state *)NULL != child); | |
2661 | ||
2662 | if( child->missing ) { | |
2663 | unsigned char child_found_tag_modifiers = 0; | |
2664 | unsigned long child_found_tag_number = 0; | |
2665 | void * dest; | |
2666 | ||
2667 | state->consumed += child->consumed; | |
2668 | ||
2669 | if (child->endofcontents) { | |
2670 | /* This choice is probably the first item in a GROUP | |
2671 | ** (e.g. SET_OF) that was indefinite-length encoded. | |
2672 | ** We're actually at the end of that GROUP. | |
2673 | ** We look up the stack to be sure that we find | |
2674 | ** a state with indefinite length encoding before we | |
2675 | ** find a state (like a SEQUENCE) that is definite. | |
2676 | */ | |
2677 | child->place = notInUse; | |
2678 | state->place = afterChoice; | |
2679 | state->endofcontents = PR_TRUE; /* propagate this up */ | |
2680 | if (sec_asn1d_parent_allows_EOC(state)) | |
2681 | return state; | |
2682 | dprintf("decodeError: during_choice child at EOC by parent does not allow EOC\n"); | |
2683 | PORT_SetError(SEC_ERROR_BAD_DER); | |
2684 | state->top->status = decodeError; | |
2685 | return NULL; | |
2686 | } | |
2687 | ||
2688 | dest = (char *)child->dest - child->theTemplate->offset; | |
2689 | child->theTemplate++; | |
2690 | ||
2691 | if( 0 == child->theTemplate->kind ) { | |
2692 | /* Ran out of choices */ | |
2693 | dprintf("decodeError: during_choice ran out of choice\n"); | |
2694 | PORT_SetError(SEC_ERROR_BAD_DER); | |
2695 | state->top->status = decodeError; | |
2696 | return (sec_asn1d_state *)NULL; | |
2697 | } | |
2698 | child->dest = (char *)dest + child->theTemplate->offset; | |
2699 | ||
2700 | /* cargo'd from next_in_sequence innards */ | |
2701 | if( state->pending ) { | |
2702 | PORT_Assert(!state->indefinite); | |
2703 | if( child->consumed > state->pending ) { | |
2704 | dprintf("decodeError: during_choice consumed > pending\n"); | |
2705 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2706 | state->top->status = decodeError; | |
2707 | return NULL; | |
2708 | } | |
2709 | state->pending -= child->consumed; | |
2710 | if( 0 == state->pending ) { | |
2711 | /* XXX uh.. not sure if I should have stopped this | |
2712 | * from happening before. */ | |
2713 | PORT_Assert(0); | |
2714 | PORT_SetError(SEC_ERROR_BAD_DER); | |
2715 | dprintf("decodeError: during_choice !pending\n"); | |
2716 | state->top->status = decodeError; | |
2717 | return (sec_asn1d_state *)NULL; | |
2718 | } | |
2719 | } | |
2720 | ||
2721 | child->consumed = 0; | |
2722 | sec_asn1d_scrub_state(child); | |
2723 | ||
2724 | /* move it on top again */ | |
2725 | state->top->current = child; | |
2726 | ||
2727 | child_found_tag_modifiers = child->found_tag_modifiers; | |
2728 | child_found_tag_number = child->found_tag_number; | |
2729 | ||
822b670c | 2730 | child = sec_asn1d_init_state_based_on_template(child, buf /* __APPLE__*/, len /* __APPLE__ */); |
b1ab9ed8 A |
2731 | if( (sec_asn1d_state *)NULL == child ) { |
2732 | return (sec_asn1d_state *)NULL; | |
2733 | } | |
2734 | ||
2735 | /* copy our findings to the new top */ | |
2736 | child->found_tag_modifiers = child_found_tag_modifiers; | |
2737 | child->found_tag_number = child_found_tag_number; | |
2738 | ||
2739 | child->optional = PR_TRUE; | |
2740 | child->place = afterIdentifier; | |
2741 | ||
2742 | return child; | |
2743 | } | |
2744 | if( (void *)NULL != state->dest ) { | |
2745 | /* Store the enum */ | |
2746 | int *which = (int *)state->dest; | |
2747 | *which = (int)child->theTemplate->size; | |
2748 | } | |
2749 | ||
2750 | child->place = notInUse; | |
2751 | ||
2752 | state->place = afterChoice; | |
2753 | return state; | |
2754 | } | |
2755 | ||
2756 | static void | |
2757 | sec_asn1d_after_choice (sec_asn1d_state *state) | |
2758 | { | |
2759 | state->consumed += state->child->consumed; | |
2760 | state->child->consumed = 0; | |
2761 | state->place = afterEndOfContents; | |
2762 | sec_asn1d_pop_state(state); | |
2763 | } | |
2764 | ||
2765 | #if 0 | |
2766 | unsigned long | |
2767 | sec_asn1d_uinteger(SecAsn1Item *src) | |
2768 | { | |
2769 | unsigned long value; | |
2770 | int len; | |
2771 | ||
2772 | if (src->Length > 5 || (src->Length > 4 && src->Data[0] == 0)) | |
2773 | return 0; | |
2774 | ||
2775 | value = 0; | |
2776 | len = src->Length; | |
2777 | while (len) { | |
2778 | value <<= 8; | |
2779 | value |= src->Data[--len]; | |
2780 | } | |
2781 | return value; | |
2782 | } | |
2783 | #endif | |
2784 | ||
2785 | SECStatus | |
2786 | SEC_ASN1DecodeInteger(SecAsn1Item *src, unsigned long *value) | |
2787 | { | |
2788 | unsigned long v; | |
2789 | unsigned int i; | |
2790 | ||
2791 | if (src == NULL) { | |
2792 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
2793 | return SECFailure; | |
2794 | } | |
2795 | ||
2796 | if (src->Length > sizeof(unsigned long)) { | |
2797 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
2798 | return SECFailure; | |
2799 | } | |
2800 | ||
2801 | if (src->Data == NULL) { | |
2802 | PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
2803 | return SECFailure; | |
2804 | } | |
2805 | ||
2806 | if (src->Data[0] & 0x80) | |
2807 | v = -1; /* signed and negative - start with all 1's */ | |
2808 | else | |
2809 | v = 0; | |
2810 | ||
2811 | for (i= 0; i < src->Length; i++) { | |
2812 | /* shift in next byte */ | |
2813 | v <<= 8; | |
2814 | v |= src->Data[i]; | |
2815 | } | |
2816 | *value = v; | |
2817 | return SECSuccess; | |
2818 | } | |
2819 | ||
2820 | #ifdef DEBUG_ASN1D_STATES | |
2821 | static void | |
2822 | dump_states(SEC_ASN1DecoderContext *cx) | |
2823 | { | |
2824 | sec_asn1d_state *state; | |
2825 | char kindBuf[256]; | |
2826 | ||
2827 | for (state = cx->current; state->parent; state = state->parent) { | |
2828 | ; | |
2829 | } | |
2830 | ||
2831 | for (; state; state = state->child) { | |
2832 | int i; | |
2833 | for (i = 0; i < state->depth; i++) { | |
2834 | printf(" "); | |
2835 | } | |
2836 | ||
2837 | i = formatKind(state->theTemplate->kind, kindBuf); | |
2838 | printf("%s: tmpl %p, kind%s", | |
2839 | (state == cx->current) ? "STATE" : "State", | |
2840 | state->theTemplate, | |
2841 | kindBuf); | |
2842 | printf(" %s", (state->place <= notInUse) | |
2843 | ? place_names[ state->place ] | |
2844 | : "(undefined)"); | |
2845 | if (!i) | |
2846 | printf(", expect 0x%02lx", | |
2847 | state->expect_tag_number | state->expect_tag_modifiers); | |
2848 | ||
2849 | printf("%s%s%s %lu\n", | |
2850 | state->indefinite ? ", indef" : "", | |
2851 | state->missing ? ", miss" : "", | |
2852 | state->endofcontents ? ", EOC" : "", | |
2853 | state->pending | |
2854 | ); | |
2855 | } | |
2856 | ||
2857 | return; | |
2858 | } | |
2859 | #endif /* DEBUG_ASN1D_STATES */ | |
2860 | ||
2861 | SECStatus | |
2862 | SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx, | |
2863 | const char *buf, size_t len) | |
2864 | { | |
2865 | sec_asn1d_state *state = NULL; | |
2866 | unsigned long consumed; | |
2867 | SEC_ASN1EncodingPart what; | |
2868 | sec_asn1d_state *stateEnd = cx->current; | |
2869 | ||
2870 | if (cx->status == needBytes) | |
2871 | cx->status = keepGoing; | |
2872 | ||
2873 | while (cx->status == keepGoing) { | |
2874 | state = cx->current; | |
2875 | what = SEC_ASN1_Contents; | |
2876 | consumed = 0; | |
2877 | #if DEBUG_ASN1D_STATES | |
2878 | if (doDumpStates > 1) { | |
2879 | printf("\nPLACE = %s, next byte = 0x%02x, %p[%lu]\n", | |
2880 | (state->place <= notInUse) ? | |
2881 | place_names[ state->place ] : "(undefined)", | |
2882 | (unsigned int)((unsigned char *)buf)[ consumed ], | |
2883 | buf, consumed); | |
2884 | dump_states(cx); | |
2885 | } | |
2886 | #endif /* DEBUG_ASN1D_STATES */ | |
2887 | switch (state->place) { | |
2888 | case beforeIdentifier: | |
2889 | consumed = sec_asn1d_parse_identifier (state, buf, len); | |
2890 | what = SEC_ASN1_Identifier; | |
2891 | break; | |
2892 | case duringIdentifier: | |
2893 | consumed = sec_asn1d_parse_more_identifier (state, buf, len); | |
2894 | what = SEC_ASN1_Identifier; | |
2895 | break; | |
2896 | case afterIdentifier: | |
2897 | sec_asn1d_confirm_identifier (state); | |
2898 | break; | |
2899 | case beforeLength: | |
2900 | consumed = sec_asn1d_parse_length (state, buf, len); | |
2901 | what = SEC_ASN1_Length; | |
2902 | break; | |
2903 | case duringLength: | |
2904 | consumed = sec_asn1d_parse_more_length (state, buf, len); | |
2905 | what = SEC_ASN1_Length; | |
2906 | break; | |
2907 | case afterLength: | |
822b670c | 2908 | sec_asn1d_prepare_for_contents (state, buf, len); |
b1ab9ed8 A |
2909 | break; |
2910 | case beforeBitString: | |
2911 | consumed = sec_asn1d_parse_bit_string (state, buf, len); | |
2912 | break; | |
2913 | case duringBitString: | |
2914 | consumed = sec_asn1d_parse_more_bit_string (state, buf, len); | |
2915 | break; | |
2916 | case duringConstructedString: | |
2917 | sec_asn1d_next_substring (state); | |
2918 | break; | |
2919 | case duringGroup: | |
822b670c | 2920 | sec_asn1d_next_in_group (state, buf, len); |
b1ab9ed8 A |
2921 | break; |
2922 | case duringLeaf: | |
2923 | consumed = sec_asn1d_parse_leaf (state, buf, len); | |
2924 | break; | |
2925 | case duringSaveEncoding: | |
2926 | sec_asn1d_reuse_encoding (state); | |
2927 | if (cx->status == decodeError) { | |
2928 | /* recursive call has already popped all states from stack. | |
2929 | ** Bail out quickly. | |
2930 | */ | |
2931 | return SECFailure; | |
2932 | } | |
2933 | if (cx->status == needBytes) { | |
2934 | /* recursive call wanted more data. Fatal. Clean up below. */ | |
2935 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2936 | cx->status = decodeError; | |
2937 | } | |
2938 | break; | |
2939 | case duringSequence: | |
822b670c | 2940 | sec_asn1d_next_in_sequence (state, buf, len); |
b1ab9ed8 A |
2941 | break; |
2942 | case afterConstructedString: | |
2943 | sec_asn1d_concat_substrings (state); | |
2944 | break; | |
2945 | case afterExplicit: | |
2946 | case afterImplicit: | |
2947 | case afterInline: | |
2948 | case afterPointer: | |
2949 | sec_asn1d_absorb_child (state); | |
2950 | break; | |
2951 | case afterGroup: | |
2952 | sec_asn1d_concat_group (state); | |
2953 | break; | |
2954 | case afterSaveEncoding: | |
2955 | /* SEC_ASN1DecoderUpdate has called itself recursively to | |
2956 | ** decode SAVEd encoded data, and now is done decoding that. | |
2957 | ** Return to the calling copy of SEC_ASN1DecoderUpdate. | |
2958 | */ | |
2959 | return SECSuccess; | |
2960 | case beforeEndOfContents: | |
2961 | sec_asn1d_prepare_for_end_of_contents (state); | |
2962 | break; | |
2963 | case duringEndOfContents: | |
2964 | consumed = sec_asn1d_parse_end_of_contents (state, buf, len); | |
2965 | what = SEC_ASN1_EndOfContents; | |
2966 | break; | |
2967 | case afterEndOfContents: | |
2968 | sec_asn1d_pop_state (state); | |
2969 | break; | |
2970 | case beforeChoice: | |
822b670c | 2971 | state = sec_asn1d_before_choice(state, buf, len); |
b1ab9ed8 A |
2972 | break; |
2973 | case duringChoice: | |
822b670c | 2974 | state = sec_asn1d_during_choice(state, buf, len); |
b1ab9ed8 A |
2975 | break; |
2976 | case afterChoice: | |
2977 | sec_asn1d_after_choice(state); | |
2978 | break; | |
2979 | case notInUse: | |
2980 | default: | |
2981 | /* This is not an error, but rather a plain old BUG! */ | |
2982 | PORT_Assert (0); | |
2983 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2984 | dprintf("decodeError: decoder update bad state->place\n"); | |
2985 | cx->status = decodeError; | |
2986 | break; | |
2987 | } | |
2988 | ||
2989 | if (cx->status == decodeError) | |
2990 | break; | |
2991 | ||
2992 | /* We should not consume more than we have. */ | |
2993 | PORT_Assert (consumed <= len); | |
2994 | if( consumed > len ) { | |
2995 | dprintf("decodeError: decoder update consumed > len\n"); | |
2996 | PORT_SetError (SEC_ERROR_BAD_DER); | |
2997 | cx->status = decodeError; | |
2998 | break; | |
2999 | } | |
3000 | ||
3001 | /* It might have changed, so we have to update our local copy. */ | |
3002 | state = cx->current; | |
3003 | ||
3004 | /* If it is NULL, we have popped all the way to the top. */ | |
3005 | if (state == NULL) { | |
3006 | PORT_Assert (consumed == 0); | |
3007 | #if 0 | |
3008 | /* XXX I want this here, but it seems that we have situations (like | |
3009 | * downloading a pkcs7 cert chain from some issuers) that give us a | |
3010 | * length which is greater than the entire encoding. So, we cannot | |
3011 | * have this be an error. | |
3012 | */ | |
3013 | if (len > 0) { | |
3014 | dprintf("decodeError: decoder update nonzero len\n"); | |
3015 | PORT_SetError (SEC_ERROR_BAD_DER); | |
3016 | cx->status = decodeError; | |
3017 | } | |
3018 | else | |
3019 | #endif | |
3020 | cx->status = allDone; | |
3021 | break; | |
3022 | } | |
3023 | else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) { | |
3024 | cx->status = allDone; | |
3025 | break; | |
3026 | } | |
3027 | ||
3028 | if (consumed == 0) | |
3029 | continue; | |
3030 | ||
3031 | /* | |
3032 | * The following check is specifically looking for an ANY | |
3033 | * that is *not* also an INNER, because we need to save aside | |
3034 | * all bytes in that case -- the contents parts will get | |
3035 | * handled like all other contents, and the end-of-contents | |
3036 | * bytes are added by the concat code, but the outer header | |
3037 | * bytes need to get saved too, so we do them explicitly here. | |
3038 | */ | |
3039 | if (state->underlying_kind == SEC_ASN1_ANY | |
3040 | && !cx->filter_only && (what == SEC_ASN1_Identifier | |
3041 | || what == SEC_ASN1_Length)) { | |
3042 | sec_asn1d_record_any_header (state, buf, consumed); | |
3043 | } | |
3044 | ||
3045 | /* | |
3046 | * We had some number of good, accepted bytes. If the caller | |
3047 | * has registered to see them, pass them along. | |
3048 | */ | |
3049 | if (state->top->filter_proc != NULL) { | |
3050 | int depth; | |
3051 | ||
3052 | depth = state->depth; | |
3053 | if (what == SEC_ASN1_EndOfContents && !state->indefinite) { | |
3054 | PORT_Assert (state->parent != NULL | |
3055 | && state->parent->indefinite); | |
3056 | depth--; | |
3057 | PORT_Assert (depth == state->parent->depth); | |
3058 | } | |
3059 | (* state->top->filter_proc) (state->top->filter_arg, | |
3060 | buf, consumed, depth, what); | |
3061 | } | |
3062 | ||
3063 | state->consumed += consumed; | |
3064 | buf += consumed; | |
3065 | len -= consumed; | |
3066 | } /* main decode loop */ | |
3067 | ||
3068 | if (cx->status == decodeError) { | |
3069 | while (state != NULL && stateEnd->parent!=state) { | |
3070 | sec_asn1d_free_child (state, PR_TRUE); | |
3071 | state = state->parent; | |
3072 | } | |
3073 | #ifdef SEC_ASN1D_FREE_ON_ERROR /* | |
3074 | * XXX This does not work because we can | |
3075 | * end up leaving behind dangling pointers | |
3076 | * to stuff that was allocated. In order | |
3077 | * to make this really work (which would | |
3078 | * be a good thing, I think), we need to | |
3079 | * keep track of every place/pointer that | |
3080 | * was allocated and make sure to NULL it | |
3081 | * out before we then free back to the mark. | |
3082 | */ | |
3083 | if (cx->their_pool != NULL) { | |
3084 | PORT_Assert (cx->their_mark != NULL); | |
3085 | PORT_ArenaRelease (cx->their_pool, cx->their_mark); | |
3086 | } | |
3087 | #endif | |
3088 | return SECFailure; | |
3089 | } | |
3090 | ||
3091 | #if 0 | |
3092 | /* XXX This is what I want, but cannot have because it seems we | |
3093 | * have situations (like when downloading a pkcs7 cert chain from | |
3094 | * some issuers) that give us a total length which is greater than | |
3095 | * the entire encoding. So, we have to allow allDone to have a | |
3096 | * remaining length greater than zero. I wanted to catch internal | |
3097 | * bugs with this, noticing when we do not have the right length. | |
3098 | * Oh well. | |
3099 | */ | |
3100 | PORT_Assert (len == 0 | |
3101 | && (cx->status == needBytes || cx->status == allDone)); | |
3102 | #else | |
3103 | PORT_Assert ((len == 0 && cx->status == needBytes) | |
3104 | || cx->status == allDone); | |
3105 | #endif | |
3106 | return SECSuccess; | |
3107 | } | |
3108 | ||
3109 | ||
3110 | SECStatus | |
3111 | SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx) | |
3112 | { | |
3113 | SECStatus rv; | |
3114 | ||
3115 | if (cx->status == needBytes) { | |
3116 | #ifdef __APPLE__ | |
3117 | /* | |
3118 | * Special case: need more bytes, but this field and all | |
3119 | * subsequent fields are optional. I'm surprised this case is | |
3120 | * not handled in the original NSS code, and this workaround | |
3121 | * is a bit of a hack... | |
3122 | */ | |
3123 | sec_asn1d_state *state = cx->current; | |
3124 | assert(state != NULL); | |
3125 | if(state->place == beforeIdentifier) { | |
3126 | int allOptional = 1; | |
3127 | const SecAsn1Template *templ = state->theTemplate; | |
3128 | while(templ->kind != 0) { | |
3129 | if(!(templ->kind & SEC_ASN1_OPTIONAL)) { | |
3130 | allOptional = 0; | |
3131 | break; | |
3132 | } | |
3133 | templ++; | |
3134 | } | |
3135 | if(allOptional) { | |
3136 | /* letting this one slide */ | |
3137 | rv = SECSuccess; | |
3138 | } | |
3139 | else { | |
3140 | PORT_SetError (SEC_ERROR_BAD_DER); | |
3141 | rv = SECFailure; | |
3142 | } | |
3143 | } | |
3144 | else { | |
3145 | PORT_SetError (SEC_ERROR_BAD_DER); | |
3146 | rv = SECFailure; | |
3147 | } | |
3148 | #else | |
3149 | PORT_SetError (SEC_ERROR_BAD_DER); | |
3150 | rv = SECFailure; | |
3151 | #endif /* __APPLE__ */ | |
3152 | } else { | |
3153 | rv = SECSuccess; | |
3154 | } | |
3155 | ||
3156 | /* | |
3157 | * XXX anything else that needs to be finished? | |
3158 | */ | |
3159 | ||
3160 | PORT_FreeArena (cx->our_pool, PR_FALSE); | |
3161 | ||
3162 | return rv; | |
3163 | } | |
3164 | ||
3165 | ||
3166 | SEC_ASN1DecoderContext * | |
3167 | SEC_ASN1DecoderStart (PRArenaPool *their_pool, void *dest, | |
3168 | const SecAsn1Template *theTemplate | |
3169 | #ifdef __APPLE__ | |
3170 | , | |
3171 | /* only needed if first element will be SEC_ASN1_DYNAMIC */ | |
822b670c A |
3172 | const char *buf, |
3173 | size_t len /* __APPLE__ */ | |
b1ab9ed8 A |
3174 | #endif |
3175 | ) | |
3176 | { | |
3177 | PRArenaPool *our_pool; | |
3178 | SEC_ASN1DecoderContext *cx; | |
3179 | ||
3180 | our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); | |
3181 | if (our_pool == NULL) | |
3182 | return NULL; | |
3183 | ||
3184 | cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx)); | |
3185 | if (cx == NULL) { | |
3186 | PORT_FreeArena (our_pool, PR_FALSE); | |
3187 | return NULL; | |
3188 | } | |
3189 | ||
3190 | cx->our_pool = our_pool; | |
3191 | if (their_pool != NULL) { | |
3192 | cx->their_pool = their_pool; | |
3193 | #ifdef SEC_ASN1D_FREE_ON_ERROR | |
3194 | cx->their_mark = PORT_ArenaMark (their_pool); | |
3195 | #endif | |
3196 | } | |
3197 | ||
3198 | cx->status = needBytes; | |
3199 | ||
3200 | if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL | |
3201 | || sec_asn1d_init_state_based_on_template (cx->current, | |
822b670c | 3202 | buf /* __APPLE__ */, len /* __APPLE__ */) == NULL) { |
b1ab9ed8 A |
3203 | /* |
3204 | * Trouble initializing (probably due to failed allocations) | |
3205 | * requires that we just give up. | |
3206 | */ | |
3207 | PORT_FreeArena (our_pool, PR_FALSE); | |
3208 | return NULL; | |
3209 | } | |
3210 | ||
3211 | return cx; | |
3212 | } | |
3213 | ||
3214 | ||
3215 | void | |
3216 | SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx, | |
3217 | SEC_ASN1WriteProc fn, void *arg, | |
3218 | PRBool only) | |
3219 | { | |
3220 | /* check that we are "between" fields here */ | |
3221 | PORT_Assert (cx->during_notify); | |
3222 | ||
3223 | cx->filter_proc = fn; | |
3224 | cx->filter_arg = arg; | |
3225 | cx->filter_only = only; | |
3226 | } | |
3227 | ||
3228 | ||
3229 | void | |
3230 | SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx) | |
3231 | { | |
3232 | /* check that we are "between" fields here */ | |
3233 | PORT_Assert (cx->during_notify); | |
3234 | ||
3235 | cx->filter_proc = NULL; | |
3236 | cx->filter_arg = NULL; | |
3237 | cx->filter_only = PR_FALSE; | |
3238 | } | |
3239 | ||
3240 | ||
3241 | void | |
3242 | SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx, | |
3243 | SEC_ASN1NotifyProc fn, void *arg) | |
3244 | { | |
3245 | cx->notify_proc = fn; | |
3246 | cx->notify_arg = arg; | |
3247 | } | |
3248 | ||
3249 | ||
3250 | void | |
3251 | SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx) | |
3252 | { | |
3253 | cx->notify_proc = NULL; | |
3254 | cx->notify_arg = NULL; /* not necessary; just being clean */ | |
3255 | } | |
3256 | ||
3257 | ||
3258 | void | |
3259 | SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error) | |
3260 | { | |
3261 | PORT_Assert(cx); | |
3262 | PORT_SetError(error); | |
3263 | cx->status = decodeError; | |
3264 | } | |
3265 | ||
3266 | ||
3267 | SECStatus | |
3268 | SEC_ASN1Decode (PRArenaPool *poolp, void *dest, | |
3269 | const SecAsn1Template *theTemplate, | |
3270 | const char *buf, size_t len) | |
3271 | { | |
3272 | SEC_ASN1DecoderContext *dcx; | |
3273 | SECStatus urv, frv; | |
3274 | ||
3275 | dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate, | |
822b670c | 3276 | buf /* __APPLE__ */, len /* __APPLE__ */); |
b1ab9ed8 A |
3277 | if (dcx == NULL) |
3278 | return SECFailure; | |
3279 | ||
3280 | urv = SEC_ASN1DecoderUpdate (dcx, buf, len); | |
3281 | frv = SEC_ASN1DecoderFinish (dcx); | |
3282 | ||
3283 | if (urv != SECSuccess) | |
3284 | return urv; | |
3285 | ||
3286 | return frv; | |
3287 | } | |
3288 | ||
3289 | ||
3290 | SECStatus | |
3291 | SEC_ASN1DecodeItem (PRArenaPool *poolp, void *dest, | |
3292 | const SecAsn1Template *theTemplate, | |
3293 | const SecAsn1Item *item) | |
3294 | { | |
3295 | return SEC_ASN1Decode (poolp, dest, theTemplate, | |
3296 | (const char *) item->Data, item->Length); | |
3297 | } | |
3298 | ||
3299 |