Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(64)

Side by Side Diff: mozilla/security/nss/lib/util/secasn1d.c

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

Powered by Google App Engine
This is Rietveld 408576698