Import from 1.9a8 tarball
[mozilla-nss.git] / security / nss / lib / util / secasn1d.c
blob448b76d14bd553bf5eb018494bf89289ca63d087
1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 * The contents of this file are subject to the Mozilla Public License Version
5 * 1.1 (the "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 * http://www.mozilla.org/MPL/
9 * Software distributed under the License is distributed on an "AS IS" basis,
10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11 * for the specific language governing rights and limitations under the
12 * License.
14 * The Original Code is the Netscape security libraries.
16 * The Initial Developer of the Original Code is
17 * Netscape Communications Corporation.
18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
19 * the Initial Developer. All Rights Reserved.
21 * Contributor(s):
23 * Alternatively, the contents of this file may be used under the terms of
24 * either the GNU General Public License Version 2 or later (the "GPL"), or
25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26 * in which case the provisions of the GPL or the LGPL are applicable instead
27 * of those above. If you wish to allow use of your version of this file only
28 * under the terms of either the GPL or the LGPL, and not to allow others to
29 * use your version of this file under the terms of the MPL, indicate your
30 * decision by deleting the provisions above and replace them with the notice
31 * and other provisions required by the GPL or the LGPL. If you do not delete
32 * the provisions above, a recipient may use your version of this file under
33 * the terms of any one of the MPL, the GPL or the LGPL.
35 * ***** END LICENSE BLOCK ***** */
38 * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
39 * Encoding Rules).
41 * $Id: secasn1d.c,v 1.37 2007/01/03 12:57:41 nelson%bolyard.com Exp $
44 /* #define DEBUG_ASN1D_STATES 1 */
46 #ifdef DEBUG_ASN1D_STATES
47 #include <stdio.h>
48 #define PR_Assert sec_asn1d_Assert
49 #endif
51 #include "secasn1.h"
52 #include "secerr.h"
54 typedef enum {
55 beforeIdentifier,
56 duringIdentifier,
57 afterIdentifier,
58 beforeLength,
59 duringLength,
60 afterLength,
61 beforeBitString,
62 duringBitString,
63 duringConstructedString,
64 duringGroup,
65 duringLeaf,
66 duringSaveEncoding,
67 duringSequence,
68 afterConstructedString,
69 afterGroup,
70 afterExplicit,
71 afterImplicit,
72 afterInline,
73 afterPointer,
74 afterSaveEncoding,
75 beforeEndOfContents,
76 duringEndOfContents,
77 afterEndOfContents,
78 beforeChoice,
79 duringChoice,
80 afterChoice,
81 notInUse
82 } sec_asn1d_parse_place;
84 #ifdef DEBUG_ASN1D_STATES
85 static const char * const place_names[] = {
86 "beforeIdentifier",
87 "duringIdentifier",
88 "afterIdentifier",
89 "beforeLength",
90 "duringLength",
91 "afterLength",
92 "beforeBitString",
93 "duringBitString",
94 "duringConstructedString",
95 "duringGroup",
96 "duringLeaf",
97 "duringSaveEncoding",
98 "duringSequence",
99 "afterConstructedString",
100 "afterGroup",
101 "afterExplicit",
102 "afterImplicit",
103 "afterInline",
104 "afterPointer",
105 "afterSaveEncoding",
106 "beforeEndOfContents",
107 "duringEndOfContents",
108 "afterEndOfContents",
109 "beforeChoice",
110 "duringChoice",
111 "afterChoice",
112 "notInUse"
115 static const char * const class_names[] = {
116 "UNIVERSAL",
117 "APPLICATION",
118 "CONTEXT_SPECIFIC",
119 "PRIVATE"
122 static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
124 static const char * const type_names[] = {
125 "END_OF_CONTENTS",
126 "BOOLEAN",
127 "INTEGER",
128 "BIT_STRING",
129 "OCTET_STRING",
130 "NULL",
131 "OBJECT_ID",
132 "OBJECT_DESCRIPTOR",
133 "(type 08)",
134 "REAL",
135 "ENUMERATED",
136 "EMBEDDED",
137 "UTF8_STRING",
138 "(type 0d)",
139 "(type 0e)",
140 "(type 0f)",
141 "SEQUENCE",
142 "SET",
143 "NUMERIC_STRING",
144 "PRINTABLE_STRING",
145 "T61_STRING",
146 "VIDEOTEXT_STRING",
147 "IA5_STRING",
148 "UTC_TIME",
149 "GENERALIZED_TIME",
150 "GRAPHIC_STRING",
151 "VISIBLE_STRING",
152 "GENERAL_STRING",
153 "UNIVERSAL_STRING",
154 "(type 1d)",
155 "BMP_STRING",
156 "HIGH_TAG_VALUE"
159 static const char * const flag_names[] = { /* flags, right to left */
160 "OPTIONAL",
161 "EXPLICIT",
162 "ANY",
163 "INLINE",
164 "POINTER",
165 "GROUP",
166 "DYNAMIC",
167 "SKIP",
168 "INNER",
169 "SAVE",
170 "", /* decoder ignores "MAY_STREAM", */
171 "SKIP_REST",
172 "CHOICE",
173 "NO_STREAM",
174 "DEBUG_BREAK",
175 "unknown 08",
176 "unknown 10",
177 "unknown 20",
178 "unknown 40",
179 "unknown 80"
182 static int /* bool */
183 formatKind(unsigned long kind, char * buf)
185 int i;
186 unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
187 unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
188 SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
190 buf[0] = 0;
191 if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
192 sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] );
193 buf += strlen(buf);
195 if (kind & SEC_ASN1_METHOD_MASK) {
196 sprintf(buf, " %s", method_names[1]);
197 buf += strlen(buf);
199 if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
200 if (k || !notag) {
201 sprintf(buf, " %s", type_names[k] );
202 if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
203 (kind & SEC_ASN1_GROUP)) {
204 buf += strlen(buf);
205 sprintf(buf, "_OF");
208 } else {
209 sprintf(buf, " [%d]", k);
211 buf += strlen(buf);
213 for (k = kind >> 8, i = 0; k; k >>= 1, ++i) {
214 if (k & 1) {
215 sprintf(buf, " %s", flag_names[i]);
216 buf += strlen(buf);
219 return notag != 0;
222 #endif /* DEBUG_ASN1D_STATES */
224 typedef enum {
225 allDone,
226 decodeError,
227 keepGoing,
228 needBytes
229 } sec_asn1d_parse_status;
231 struct subitem {
232 const void *data;
233 unsigned long len; /* only used for substrings */
234 struct subitem *next;
237 typedef struct sec_asn1d_state_struct {
238 SEC_ASN1DecoderContext *top;
239 const SEC_ASN1Template *theTemplate;
240 void *dest;
242 void *our_mark; /* free on completion */
244 struct sec_asn1d_state_struct *parent; /* aka prev */
245 struct sec_asn1d_state_struct *child; /* aka next */
247 sec_asn1d_parse_place place;
250 * XXX explain the next fields as clearly as possible...
252 unsigned char found_tag_modifiers;
253 unsigned char expect_tag_modifiers;
254 unsigned long check_tag_mask;
255 unsigned long found_tag_number;
256 unsigned long expect_tag_number;
257 unsigned long underlying_kind;
259 unsigned long contents_length;
260 unsigned long pending;
261 unsigned long consumed;
263 int depth;
266 * Bit strings have their length adjusted -- the first octet of the
267 * contents contains a value between 0 and 7 which says how many bits
268 * at the end of the octets are not actually part of the bit string;
269 * when parsing bit strings we put that value here because we need it
270 * later, for adjustment of the length (when the whole string is done).
272 unsigned int bit_string_unused_bits;
275 * The following are used for indefinite-length constructed strings.
277 struct subitem *subitems_head;
278 struct subitem *subitems_tail;
280 PRPackedBool
281 allocate, /* when true, need to allocate the destination */
282 endofcontents, /* this state ended up parsing end-of-contents octets */
283 explicit, /* we are handling an explicit header */
284 indefinite, /* the current item has indefinite-length encoding */
285 missing, /* an optional field that was not present */
286 optional, /* the template says this field may be omitted */
287 substring; /* this is a substring of a constructed string */
289 } sec_asn1d_state;
291 #define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
292 #define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0)
293 #define TAG_NUMBER_BITS 7
294 #define TAG_NUMBER_MASK 0x7f
296 #define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0)
297 #define LONG_FORM_LENGTH(b) ((b) & 0x7f)
299 #define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
303 * An "outsider" will have an opaque pointer to this, created by calling
304 * SEC_ASN1DecoderStart(). It will be passed back in to all subsequent
305 * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
306 * SEC_ASN1DecoderFinish().
308 struct sec_DecoderContext_struct {
309 PRArenaPool *our_pool; /* for our internal allocs */
310 PRArenaPool *their_pool; /* for destination structure allocs */
311 #ifdef SEC_ASN1D_FREE_ON_ERROR /*
312 * XXX see comment below (by same
313 * ifdef) that explains why this
314 * does not work (need more smarts
315 * in order to free back to mark)
318 * XXX how to make their_mark work in the case where they do NOT
319 * give us a pool pointer?
321 void *their_mark; /* free on error */
322 #endif
324 sec_asn1d_state *current;
325 sec_asn1d_parse_status status;
327 SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
328 void *notify_arg; /* argument to notify_proc */
329 PRBool during_notify; /* true during call to notify_proc */
331 SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */
332 void *filter_arg; /* argument to that function */
333 PRBool filter_only; /* do not allocate/store fields */
338 * XXX this is a fairly generic function that may belong elsewhere
340 static void *
341 sec_asn1d_alloc (PRArenaPool *poolp, unsigned long len)
343 void *thing;
345 if (poolp != NULL) {
347 * Allocate from the pool.
349 thing = PORT_ArenaAlloc (poolp, len);
350 } else {
352 * Allocate generically.
354 thing = PORT_Alloc (len);
357 return thing;
362 * XXX this is a fairly generic function that may belong elsewhere
364 static void *
365 sec_asn1d_zalloc (PRArenaPool *poolp, unsigned long len)
367 void *thing;
369 thing = sec_asn1d_alloc (poolp, len);
370 if (thing != NULL)
371 PORT_Memset (thing, 0, len);
372 return thing;
376 static sec_asn1d_state *
377 sec_asn1d_push_state (SEC_ASN1DecoderContext *cx,
378 const SEC_ASN1Template *theTemplate,
379 void *dest, PRBool new_depth)
381 sec_asn1d_state *state, *new_state;
383 state = cx->current;
385 PORT_Assert (state == NULL || state->child == NULL);
387 if (state != NULL) {
388 PORT_Assert (state->our_mark == NULL);
389 state->our_mark = PORT_ArenaMark (cx->our_pool);
392 new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool,
393 sizeof(*new_state));
394 if (new_state == NULL) {
395 goto loser;
398 new_state->top = cx;
399 new_state->parent = state;
400 new_state->theTemplate = theTemplate;
401 new_state->place = notInUse;
402 if (dest != NULL)
403 new_state->dest = (char *)dest + theTemplate->offset;
405 if (state != NULL) {
406 new_state->depth = state->depth;
407 if (new_depth) {
408 if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
409 PORT_SetError (SEC_ERROR_BAD_DER);
410 goto loser;
413 state->child = new_state;
416 cx->current = new_state;
417 return new_state;
419 loser:
420 cx->status = decodeError;
421 if (state != NULL) {
422 PORT_ArenaRelease(cx->our_pool, state->our_mark);
423 state->our_mark = NULL;
425 return NULL;
429 static void
430 sec_asn1d_scrub_state (sec_asn1d_state *state)
433 * Some default "scrubbing".
434 * XXX right set of initializations?
436 state->place = beforeIdentifier;
437 state->endofcontents = PR_FALSE;
438 state->indefinite = PR_FALSE;
439 state->missing = PR_FALSE;
440 PORT_Assert (state->consumed == 0);
444 static void
445 sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth)
447 if (cx->notify_proc == NULL)
448 return;
450 cx->during_notify = PR_TRUE;
451 (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth);
452 cx->during_notify = PR_FALSE;
456 static void
457 sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth)
459 if (cx->notify_proc == NULL)
460 return;
462 cx->during_notify = PR_TRUE;
463 (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth);
464 cx->during_notify = PR_FALSE;
468 static sec_asn1d_state *
469 sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
471 PRBool explicit, optional, universal;
472 unsigned char expect_tag_modifiers;
473 unsigned long encode_kind, under_kind;
474 unsigned long check_tag_mask, expect_tag_number;
477 /* XXX Check that both of these tests are really needed/appropriate. */
478 if (state == NULL || state->top->status == decodeError)
479 return state;
481 encode_kind = state->theTemplate->kind;
483 if (encode_kind & SEC_ASN1_SAVE) {
485 * This is a "magic" field that saves away all bytes, allowing
486 * the immediately following field to still be decoded from this
487 * same spot -- sort of a fork.
489 /* check that there are no extraneous bits */
490 PORT_Assert (encode_kind == SEC_ASN1_SAVE);
491 if (state->top->filter_only) {
493 * If we are not storing, then we do not do the SAVE field
494 * at all. Just move ahead to the "real" field instead,
495 * doing the appropriate notify calls before and after.
497 sec_asn1d_notify_after (state->top, state->dest, state->depth);
499 * Since we are not storing, allow for our current dest value
500 * to be NULL. (This might not actually occur, but right now I
501 * cannot convince myself one way or the other.) If it is NULL,
502 * assume that our parent dest can help us out.
504 if (state->dest == NULL)
505 state->dest = state->parent->dest;
506 else
507 state->dest = (char *)state->dest - state->theTemplate->offset;
508 state->theTemplate++;
509 if (state->dest != NULL)
510 state->dest = (char *)state->dest + state->theTemplate->offset;
511 sec_asn1d_notify_before (state->top, state->dest, state->depth);
512 encode_kind = state->theTemplate->kind;
513 PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0);
514 } else {
515 sec_asn1d_scrub_state (state);
516 state->place = duringSaveEncoding;
517 state = sec_asn1d_push_state (state->top, SEC_AnyTemplate,
518 state->dest, PR_FALSE);
519 if (state != NULL)
520 state = sec_asn1d_init_state_based_on_template (state);
521 return state;
526 universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
527 ? PR_TRUE : PR_FALSE;
529 explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
530 encode_kind &= ~SEC_ASN1_EXPLICIT;
532 optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
533 encode_kind &= ~SEC_ASN1_OPTIONAL;
535 PORT_Assert (!(explicit && universal)); /* bad templates */
537 encode_kind &= ~SEC_ASN1_DYNAMIC;
538 encode_kind &= ~SEC_ASN1_MAY_STREAM;
540 if (encode_kind & SEC_ASN1_CHOICE) {
541 #if 0 /* XXX remove? */
542 sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
543 if ((sec_asn1d_state *)NULL == child) {
544 return (sec_asn1d_state *)NULL;
547 child->allocate = state->allocate;
548 child->place = beforeChoice;
549 return child;
550 #else
551 state->place = beforeChoice;
552 return state;
553 #endif
556 if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal
557 && !explicit)) {
558 const SEC_ASN1Template *subt;
559 void *dest;
560 PRBool child_allocate;
562 PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
564 sec_asn1d_scrub_state (state);
565 child_allocate = PR_FALSE;
567 if (encode_kind & SEC_ASN1_POINTER) {
569 * A POINTER means we need to allocate the destination for
570 * this field. But, since it may also be an optional field,
571 * we defer the allocation until later; we just record that
572 * it needs to be done.
574 * There are two possible scenarios here -- one is just a
575 * plain POINTER (kind of like INLINE, except with allocation)
576 * and the other is an implicitly-tagged POINTER. We don't
577 * need to do anything special here for the two cases, but
578 * since the template definition can be tricky, we do check
579 * that there are no extraneous bits set in encode_kind.
581 * XXX The same conditions which assert should set an error.
583 if (universal) {
585 * "universal" means this entry is a standalone POINTER;
586 * there should be no other bits set in encode_kind.
588 PORT_Assert (encode_kind == SEC_ASN1_POINTER);
589 } else {
591 * If we get here we have an implicitly-tagged field
592 * that needs to be put into a POINTER. The subtemplate
593 * will determine how to decode the field, but encode_kind
594 * describes the (implicit) tag we are looking for.
595 * The non-tag bits of encode_kind will be ignored by
596 * the code below; none of them should be set, however,
597 * except for the POINTER bit itself -- so check that.
599 PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK)
600 == SEC_ASN1_POINTER);
602 if (!state->top->filter_only)
603 child_allocate = PR_TRUE;
604 dest = NULL;
605 state->place = afterPointer;
606 } else {
607 dest = state->dest;
608 if (encode_kind & SEC_ASN1_INLINE) {
609 /* check that there are no extraneous bits */
610 PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional);
611 state->place = afterInline;
612 } else {
613 state->place = afterImplicit;
617 state->optional = optional;
618 subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, PR_FALSE);
619 state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE);
620 if (state == NULL)
621 return NULL;
623 state->allocate = child_allocate;
625 if (universal) {
626 state = sec_asn1d_init_state_based_on_template (state);
627 if (state != NULL) {
629 * If this field is optional, we need to record that on
630 * the pushed child so it won't fail if the field isn't
631 * found. I can't think of a way that this new state
632 * could already have optional set (which we would wipe
633 * out below if our local optional is not set) -- but
634 * just to be sure, assert that it isn't set.
636 PORT_Assert (!state->optional);
637 state->optional = optional;
639 return state;
642 under_kind = state->theTemplate->kind;
643 under_kind &= ~SEC_ASN1_MAY_STREAM;
644 } else if (explicit) {
646 * For explicit, we only need to match the encoding tag next,
647 * then we will push another state to handle the entire inner
648 * part. In this case, there is no underlying kind which plays
649 * any part in the determination of the outer, explicit tag.
650 * So we just set under_kind to 0, which is not a valid tag,
651 * and the rest of the tag matching stuff should be okay.
653 under_kind = 0;
654 } else {
656 * Nothing special; the underlying kind and the given encoding
657 * information are the same.
659 under_kind = encode_kind;
662 /* XXX is this the right set of bits to test here? */
663 PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL
664 | SEC_ASN1_MAY_STREAM
665 | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
667 if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
668 PORT_Assert (encode_kind == under_kind);
669 if (encode_kind & SEC_ASN1_SKIP) {
670 PORT_Assert (!optional);
671 PORT_Assert (encode_kind == SEC_ASN1_SKIP);
672 state->dest = NULL;
674 check_tag_mask = 0;
675 expect_tag_modifiers = 0;
676 expect_tag_number = 0;
677 } else {
678 check_tag_mask = SEC_ASN1_TAG_MASK;
679 expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK
680 & ~SEC_ASN1_TAGNUM_MASK;
682 * XXX This assumes only single-octet identifiers. To handle
683 * the HIGH TAG form we would need to do some more work, especially
684 * in how to specify them in the template, because right now we
685 * do not provide a way to specify more *tag* bits in encode_kind.
687 expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
689 switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
690 case SEC_ASN1_SET:
692 * XXX A plain old SET (as opposed to a SET OF) is not implemented.
693 * If it ever is, remove this assert...
695 PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0);
696 /* fallthru */
697 case SEC_ASN1_SEQUENCE:
698 expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
699 break;
700 case SEC_ASN1_BIT_STRING:
701 case SEC_ASN1_BMP_STRING:
702 case SEC_ASN1_GENERALIZED_TIME:
703 case SEC_ASN1_IA5_STRING:
704 case SEC_ASN1_OCTET_STRING:
705 case SEC_ASN1_PRINTABLE_STRING:
706 case SEC_ASN1_T61_STRING:
707 case SEC_ASN1_UNIVERSAL_STRING:
708 case SEC_ASN1_UTC_TIME:
709 case SEC_ASN1_UTF8_STRING:
710 case SEC_ASN1_VISIBLE_STRING:
711 check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
712 break;
716 state->check_tag_mask = check_tag_mask;
717 state->expect_tag_modifiers = expect_tag_modifiers;
718 state->expect_tag_number = expect_tag_number;
719 state->underlying_kind = under_kind;
720 state->explicit = explicit;
721 state->optional = optional;
723 sec_asn1d_scrub_state (state);
725 return state;
728 static sec_asn1d_state *
729 sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
731 for (state = state->parent; state; state = state->parent) {
732 sec_asn1d_parse_place place = state->place;
733 if (place != afterImplicit &&
734 place != afterPointer &&
735 place != afterInline &&
736 place != afterSaveEncoding &&
737 place != duringSaveEncoding &&
738 place != duringChoice) {
740 /* we've walked up the stack to a state that represents
741 ** the enclosing construct.
743 break;
746 return state;
749 static PRBool
750 sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
752 /* get state of enclosing construct. */
753 state = sec_asn1d_get_enclosing_construct(state);
754 if (state) {
755 sec_asn1d_parse_place place = state->place;
756 /* Is it one of the types that permits an unexpected EOC? */
757 int eoc_permitted =
758 (place == duringGroup ||
759 place == duringConstructedString ||
760 state->child->optional);
761 return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
763 return PR_FALSE;
766 static unsigned long
767 sec_asn1d_parse_identifier (sec_asn1d_state *state,
768 const char *buf, unsigned long len)
770 unsigned char byte;
771 unsigned char tag_number;
773 PORT_Assert (state->place == beforeIdentifier);
775 if (len == 0) {
776 state->top->status = needBytes;
777 return 0;
780 byte = (unsigned char) *buf;
781 #ifdef DEBUG_ASN1D_STATES
783 char kindBuf[256];
784 formatKind(byte, kindBuf);
785 printf("Found tag %02x %s\n", byte, kindBuf);
787 #endif
788 tag_number = byte & SEC_ASN1_TAGNUM_MASK;
790 if (IS_HIGH_TAG_NUMBER (tag_number)) {
791 state->place = duringIdentifier;
792 state->found_tag_number = 0;
794 * Actually, we have no idea how many bytes are pending, but we
795 * do know that it is at least 1. That is all we know; we have
796 * to look at each byte to know if there is another, etc.
798 state->pending = 1;
799 } else {
800 if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
802 * Our parent has indefinite-length encoding, and the
803 * entire tag found is 0, so it seems that we have hit the
804 * end-of-contents octets. To handle this, we just change
805 * our state to that which expects to get the bytes of the
806 * end-of-contents octets and let that code re-read this byte
807 * so that our categorization of field types is correct.
808 * After that, our parent will then deal with everything else.
810 state->place = duringEndOfContents;
811 state->pending = 2;
812 state->found_tag_number = 0;
813 state->found_tag_modifiers = 0;
815 * We might be an optional field that is, as we now find out,
816 * missing. Give our parent a clue that this happened.
818 if (state->optional)
819 state->missing = PR_TRUE;
820 return 0;
822 state->place = afterIdentifier;
823 state->found_tag_number = tag_number;
825 state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
827 return 1;
831 static unsigned long
832 sec_asn1d_parse_more_identifier (sec_asn1d_state *state,
833 const char *buf, unsigned long len)
835 unsigned char byte;
836 int count;
838 PORT_Assert (state->pending == 1);
839 PORT_Assert (state->place == duringIdentifier);
841 if (len == 0) {
842 state->top->status = needBytes;
843 return 0;
846 count = 0;
848 while (len && state->pending) {
849 if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) {
851 * The given high tag number overflows our container;
852 * just give up. This is not likely to *ever* happen.
854 PORT_SetError (SEC_ERROR_BAD_DER);
855 state->top->status = decodeError;
856 return 0;
859 state->found_tag_number <<= TAG_NUMBER_BITS;
861 byte = (unsigned char) buf[count++];
862 state->found_tag_number |= (byte & TAG_NUMBER_MASK);
864 len--;
865 if (LAST_TAG_NUMBER_BYTE (byte))
866 state->pending = 0;
869 if (state->pending == 0)
870 state->place = afterIdentifier;
872 return count;
876 static void
877 sec_asn1d_confirm_identifier (sec_asn1d_state *state)
879 PRBool match;
881 PORT_Assert (state->place == afterIdentifier);
883 match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask)
884 == state->expect_tag_modifiers)
885 && ((state->found_tag_number & state->check_tag_mask)
886 == state->expect_tag_number));
887 if (match) {
888 state->place = beforeLength;
889 } else {
890 if (state->optional) {
891 state->missing = PR_TRUE;
892 state->place = afterEndOfContents;
893 } else {
894 PORT_SetError (SEC_ERROR_BAD_DER);
895 state->top->status = decodeError;
901 static unsigned long
902 sec_asn1d_parse_length (sec_asn1d_state *state,
903 const char *buf, unsigned long len)
905 unsigned char byte;
907 PORT_Assert (state->place == beforeLength);
909 if (len == 0) {
910 state->top->status = needBytes;
911 return 0;
915 * The default/likely outcome. It may get adjusted below.
917 state->place = afterLength;
919 byte = (unsigned char) *buf;
921 if (LENGTH_IS_SHORT_FORM (byte)) {
922 state->contents_length = byte;
923 } else {
924 state->contents_length = 0;
925 state->pending = LONG_FORM_LENGTH (byte);
926 if (state->pending == 0) {
927 state->indefinite = PR_TRUE;
928 } else {
929 state->place = duringLength;
933 /* If we're parsing an ANY, SKIP, or SAVE template, and
934 ** the object being saved is definite length encoded and constructed,
935 ** there's no point in decoding that construct's members.
936 ** So, just forget it's constructed and treat it as primitive.
937 ** (SAVE appears as an ANY at this point)
939 if (!state->indefinite &&
940 (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
941 state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
944 return 1;
948 static unsigned long
949 sec_asn1d_parse_more_length (sec_asn1d_state *state,
950 const char *buf, unsigned long len)
952 int count;
954 PORT_Assert (state->pending > 0);
955 PORT_Assert (state->place == duringLength);
957 if (len == 0) {
958 state->top->status = needBytes;
959 return 0;
962 count = 0;
964 while (len && state->pending) {
965 if (HIGH_BITS (state->contents_length, 9) != 0) {
967 * The given full content length overflows our container;
968 * just give up.
970 PORT_SetError (SEC_ERROR_BAD_DER);
971 state->top->status = decodeError;
972 return 0;
975 state->contents_length <<= 8;
976 state->contents_length |= (unsigned char) buf[count++];
978 len--;
979 state->pending--;
982 if (state->pending == 0)
983 state->place = afterLength;
985 return count;
989 static void
990 sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
992 SECItem *item;
993 PRArenaPool *poolp;
994 unsigned long alloc_len;
996 #ifdef DEBUG_ASN1D_STATES
998 printf("Found Length %d %s\n", state->contents_length,
999 state->indefinite ? "indefinite" : "");
1001 #endif
1004 * XXX I cannot decide if this allocation should exclude the case
1005 * where state->endofcontents is true -- figure it out!
1007 if (state->allocate) {
1008 void *dest;
1010 PORT_Assert (state->dest == NULL);
1012 * We are handling a POINTER or a member of a GROUP, and need to
1013 * allocate for the data structure.
1015 dest = sec_asn1d_zalloc (state->top->their_pool,
1016 state->theTemplate->size);
1017 if (dest == NULL) {
1018 state->top->status = decodeError;
1019 return;
1021 state->dest = (char *)dest + state->theTemplate->offset;
1024 * For a member of a GROUP, our parent will later put the
1025 * pointer wherever it belongs. But for a POINTER, we need
1026 * to record the destination now, in case notify or filter
1027 * procs need access to it -- they cannot find it otherwise,
1028 * until it is too late (for one-pass processing).
1030 if (state->parent->place == afterPointer) {
1031 void **placep;
1033 placep = state->parent->dest;
1034 *placep = dest;
1039 * Remember, length may be indefinite here! In that case,
1040 * both contents_length and pending will be zero.
1042 state->pending = state->contents_length;
1044 /* If this item has definite length encoding, and
1045 ** is enclosed by a definite length constructed type,
1046 ** make sure it isn't longer than the remaining space in that
1047 ** constructed type.
1049 if (state->contents_length > 0) {
1050 sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
1051 if (parent && !parent->indefinite &&
1052 state->consumed + state->contents_length > parent->pending) {
1053 PORT_SetError (SEC_ERROR_BAD_DER);
1054 state->top->status = decodeError;
1055 return;
1060 * An EXPLICIT is nothing but an outer header, which we have
1061 * already parsed and accepted. Now we need to do the inner
1062 * header and its contents.
1064 if (state->explicit) {
1065 state->place = afterExplicit;
1066 state = sec_asn1d_push_state (state->top,
1067 SEC_ASN1GetSubtemplate(state->theTemplate,
1068 state->dest,
1069 PR_FALSE),
1070 state->dest, PR_TRUE);
1071 if (state != NULL)
1072 state = sec_asn1d_init_state_based_on_template (state);
1073 return;
1077 * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
1078 * we cannot tell how many items we will end up with ... so push a
1079 * state that can keep track of "children" (the individual members
1080 * of the group; we will allocate as we go and put them all together
1081 * at the end.
1083 if (state->underlying_kind & SEC_ASN1_GROUP) {
1084 /* XXX If this assertion holds (should be able to confirm it via
1085 * inspection, too) then move this code into the switch statement
1086 * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
1088 PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF
1089 || state->underlying_kind == SEC_ASN1_SEQUENCE_OF
1090 || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
1091 || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
1093 if (state->contents_length != 0 || state->indefinite) {
1094 const SEC_ASN1Template *subt;
1096 state->place = duringGroup;
1097 subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest,
1098 PR_FALSE);
1099 state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE);
1100 if (state != NULL) {
1101 if (!state->top->filter_only)
1102 state->allocate = PR_TRUE; /* XXX propogate this? */
1104 * Do the "before" field notification for next in group.
1106 sec_asn1d_notify_before (state->top, state->dest, state->depth);
1107 state = sec_asn1d_init_state_based_on_template (state);
1109 } else {
1111 * A group of zero; we are done.
1112 * Set state to afterGroup and let that code plant the NULL.
1114 state->place = afterGroup;
1116 return;
1119 switch (state->underlying_kind) {
1120 case SEC_ASN1_SEQUENCE:
1122 * We need to push a child to handle the individual fields.
1124 state->place = duringSequence;
1125 state = sec_asn1d_push_state (state->top, state->theTemplate + 1,
1126 state->dest, PR_TRUE);
1127 if (state != NULL) {
1129 * Do the "before" field notification.
1131 sec_asn1d_notify_before (state->top, state->dest, state->depth);
1132 state = sec_asn1d_init_state_based_on_template (state);
1134 break;
1136 case SEC_ASN1_SET: /* XXX SET is not really implemented */
1138 * XXX A plain SET requires special handling; scanning of a
1139 * template to see where a field should go (because by definition,
1140 * they are not in any particular order, and you have to look at
1141 * each tag to disambiguate what the field is). We may never
1142 * implement this because in practice, it seems to be unused.
1144 PORT_Assert(0);
1145 PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */
1146 state->top->status = decodeError;
1147 break;
1149 case SEC_ASN1_NULL:
1151 * The NULL type, by definition, is "nothing", content length of zero.
1152 * An indefinite-length encoding is not alloweed.
1154 if (state->contents_length || state->indefinite) {
1155 PORT_SetError (SEC_ERROR_BAD_DER);
1156 state->top->status = decodeError;
1157 break;
1159 if (state->dest != NULL) {
1160 item = (SECItem *)(state->dest);
1161 item->data = NULL;
1162 item->len = 0;
1164 state->place = afterEndOfContents;
1165 break;
1167 case SEC_ASN1_BMP_STRING:
1168 /* Error if length is not divisable by 2 */
1169 if (state->contents_length % 2) {
1170 PORT_SetError (SEC_ERROR_BAD_DER);
1171 state->top->status = decodeError;
1172 break;
1174 /* otherwise, handle as other string types */
1175 goto regular_string_type;
1177 case SEC_ASN1_UNIVERSAL_STRING:
1178 /* Error if length is not divisable by 4 */
1179 if (state->contents_length % 4) {
1180 PORT_SetError (SEC_ERROR_BAD_DER);
1181 state->top->status = decodeError;
1182 break;
1184 /* otherwise, handle as other string types */
1185 goto regular_string_type;
1187 case SEC_ASN1_SKIP:
1188 case SEC_ASN1_ANY:
1189 case SEC_ASN1_ANY_CONTENTS:
1191 * These are not (necessarily) strings, but they need nearly
1192 * identical handling (especially when we need to deal with
1193 * constructed sub-pieces), so we pretend they are.
1195 /* fallthru */
1196 regular_string_type:
1197 case SEC_ASN1_BIT_STRING:
1198 case SEC_ASN1_IA5_STRING:
1199 case SEC_ASN1_OCTET_STRING:
1200 case SEC_ASN1_PRINTABLE_STRING:
1201 case SEC_ASN1_T61_STRING:
1202 case SEC_ASN1_UTC_TIME:
1203 case SEC_ASN1_UTF8_STRING:
1204 case SEC_ASN1_VISIBLE_STRING:
1206 * We are allocating for a primitive or a constructed string.
1207 * If it is a constructed string, it may also be indefinite-length.
1208 * If it is primitive, the length can (legally) be zero.
1209 * Our first order of business is to allocate the memory for
1210 * the string, if we can (if we know the length).
1212 item = (SECItem *)(state->dest);
1215 * If the item is a definite-length constructed string, then
1216 * the contents_length is actually larger than what we need
1217 * (because it also counts each intermediate header which we
1218 * will be throwing away as we go), but it is a perfectly good
1219 * upper bound that we just allocate anyway, and then concat
1220 * as we go; we end up wasting a few extra bytes but save a
1221 * whole other copy.
1223 alloc_len = state->contents_length;
1224 poolp = NULL; /* quiet compiler warnings about unused... */
1226 if (item == NULL || state->top->filter_only) {
1227 if (item != NULL) {
1228 item->data = NULL;
1229 item->len = 0;
1231 alloc_len = 0;
1232 } else if (state->substring) {
1234 * If we are a substring of a constructed string, then we may
1235 * not have to allocate anything (because our parent, the
1236 * actual constructed string, did it for us). If we are a
1237 * substring and we *do* have to allocate, that means our
1238 * parent is an indefinite-length, so we allocate from our pool;
1239 * later our parent will copy our string into the aggregated
1240 * whole and free our pool allocation.
1242 if (item->data == NULL) {
1243 PORT_Assert (item->len == 0);
1244 poolp = state->top->our_pool;
1245 } else {
1246 alloc_len = 0;
1248 } else {
1249 item->len = 0;
1250 item->data = NULL;
1251 poolp = state->top->their_pool;
1254 if (alloc_len || ((! state->indefinite)
1255 && (state->subitems_head != NULL))) {
1256 struct subitem *subitem;
1257 int len;
1259 PORT_Assert (item);
1260 if (!item) {
1261 PORT_SetError (SEC_ERROR_BAD_DER);
1262 state->top->status = decodeError;
1263 return;
1265 PORT_Assert (item->len == 0 && item->data == NULL);
1267 * Check for and handle an ANY which has stashed aside the
1268 * header (identifier and length) bytes for us to include
1269 * in the saved contents.
1271 if (state->subitems_head != NULL) {
1272 PORT_Assert (state->underlying_kind == SEC_ASN1_ANY);
1273 for (subitem = state->subitems_head;
1274 subitem != NULL; subitem = subitem->next)
1275 alloc_len += subitem->len;
1278 item->data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len);
1279 if (item->data == NULL) {
1280 state->top->status = decodeError;
1281 break;
1284 len = 0;
1285 for (subitem = state->subitems_head;
1286 subitem != NULL; subitem = subitem->next) {
1287 PORT_Memcpy (item->data + len, subitem->data, subitem->len);
1288 len += subitem->len;
1290 item->len = len;
1293 * Because we use arenas and have a mark set, we later free
1294 * everything we have allocated, so this does *not* present
1295 * a memory leak (it is just temporarily left dangling).
1297 state->subitems_head = state->subitems_tail = NULL;
1300 if (state->contents_length == 0 && (! state->indefinite)) {
1302 * A zero-length simple or constructed string; we are done.
1304 state->place = afterEndOfContents;
1305 } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
1306 const SEC_ASN1Template *sub;
1308 switch (state->underlying_kind) {
1309 case SEC_ASN1_ANY:
1310 case SEC_ASN1_ANY_CONTENTS:
1311 sub = SEC_AnyTemplate;
1312 break;
1313 case SEC_ASN1_BIT_STRING:
1314 sub = SEC_BitStringTemplate;
1315 break;
1316 case SEC_ASN1_BMP_STRING:
1317 sub = SEC_BMPStringTemplate;
1318 break;
1319 case SEC_ASN1_GENERALIZED_TIME:
1320 sub = SEC_GeneralizedTimeTemplate;
1321 break;
1322 case SEC_ASN1_IA5_STRING:
1323 sub = SEC_IA5StringTemplate;
1324 break;
1325 case SEC_ASN1_OCTET_STRING:
1326 sub = SEC_OctetStringTemplate;
1327 break;
1328 case SEC_ASN1_PRINTABLE_STRING:
1329 sub = SEC_PrintableStringTemplate;
1330 break;
1331 case SEC_ASN1_T61_STRING:
1332 sub = SEC_T61StringTemplate;
1333 break;
1334 case SEC_ASN1_UNIVERSAL_STRING:
1335 sub = SEC_UniversalStringTemplate;
1336 break;
1337 case SEC_ASN1_UTC_TIME:
1338 sub = SEC_UTCTimeTemplate;
1339 break;
1340 case SEC_ASN1_UTF8_STRING:
1341 sub = SEC_UTF8StringTemplate;
1342 break;
1343 case SEC_ASN1_VISIBLE_STRING:
1344 sub = SEC_VisibleStringTemplate;
1345 break;
1346 case SEC_ASN1_SKIP:
1347 sub = SEC_SkipTemplate;
1348 break;
1349 default: /* redundant given outer switch cases, but */
1350 PORT_Assert(0); /* the compiler does not seem to know that, */
1351 sub = NULL; /* so just do enough to quiet it. */
1352 break;
1355 state->place = duringConstructedString;
1356 state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE);
1357 if (state != NULL) {
1358 state->substring = PR_TRUE; /* XXX propogate? */
1359 state = sec_asn1d_init_state_based_on_template (state);
1361 } else if (state->indefinite) {
1363 * An indefinite-length string *must* be constructed!
1365 PORT_SetError (SEC_ERROR_BAD_DER);
1366 state->top->status = decodeError;
1367 } else {
1369 * A non-zero-length simple string.
1371 if (state->underlying_kind == SEC_ASN1_BIT_STRING)
1372 state->place = beforeBitString;
1373 else
1374 state->place = duringLeaf;
1376 break;
1378 default:
1380 * We are allocating for a simple leaf item.
1382 if (state->contents_length) {
1383 if (state->dest != NULL) {
1384 item = (SECItem *)(state->dest);
1385 item->len = 0;
1386 if (state->top->filter_only) {
1387 item->data = NULL;
1388 } else {
1389 item->data = (unsigned char*)
1390 sec_asn1d_zalloc (state->top->their_pool,
1391 state->contents_length);
1392 if (item->data == NULL) {
1393 state->top->status = decodeError;
1394 return;
1398 state->place = duringLeaf;
1399 } else {
1401 * An indefinite-length or zero-length item is not allowed.
1402 * (All legal cases of such were handled above.)
1404 PORT_SetError (SEC_ERROR_BAD_DER);
1405 state->top->status = decodeError;
1411 static void
1412 sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
1414 if (state->child != NULL) {
1415 PORT_Assert (error || state->child->consumed == 0);
1416 PORT_Assert (state->our_mark != NULL);
1417 PORT_ArenaZRelease (state->top->our_pool, state->our_mark);
1418 if (error && state->top->their_pool == NULL) {
1420 * XXX We need to free anything allocated.
1421 * At this point, we failed in the middle of decoding. But we
1422 * can't free the data we previously allocated with PR_Malloc
1423 * unless we keep track of every pointer. So instead we have a
1424 * memory leak when decoding fails half-way, unless an arena is
1425 * used. See bug 95311 .
1428 state->child = NULL;
1429 state->our_mark = NULL;
1430 } else {
1432 * It is important that we do not leave a mark unreleased/unmarked.
1433 * But I do not think we should ever have one set in this case, only
1434 * if we had a child (handled above). So check for that. If this
1435 * assertion should ever get hit, then we probably need to add code
1436 * here to release back to our_mark (and then set our_mark to NULL).
1438 PORT_Assert (state->our_mark == NULL);
1440 state->place = beforeEndOfContents;
1443 /* We have just saved an entire encoded ASN.1 object (type) for a SAVE
1444 ** template, and now in the next template, we are going to decode that
1445 ** saved data by calling SEC_ASN1DecoderUpdate recursively.
1446 ** If that recursive call fails with needBytes, it is a fatal error,
1447 ** because the encoded object should have been complete.
1448 ** If that recursive call fails with decodeError, it will have already
1449 ** cleaned up the state stack, so we must bail out quickly.
1451 ** These checks of the status returned by the recursive call are now
1452 ** done in the caller of this function, immediately after it returns.
1454 static void
1455 sec_asn1d_reuse_encoding (sec_asn1d_state *state)
1457 sec_asn1d_state *child;
1458 unsigned long consumed;
1459 SECItem *item;
1460 void *dest;
1463 child = state->child;
1464 PORT_Assert (child != NULL);
1466 consumed = child->consumed;
1467 child->consumed = 0;
1469 item = (SECItem *)(state->dest);
1470 PORT_Assert (item != NULL);
1472 PORT_Assert (item->len == consumed);
1475 * Free any grandchild.
1477 sec_asn1d_free_child (child, PR_FALSE);
1480 * Notify after the SAVE field.
1482 sec_asn1d_notify_after (state->top, state->dest, state->depth);
1485 * Adjust to get new dest and move forward.
1487 dest = (char *)state->dest - state->theTemplate->offset;
1488 state->theTemplate++;
1489 child->dest = (char *)dest + state->theTemplate->offset;
1490 child->theTemplate = state->theTemplate;
1493 * Notify before the "real" field.
1495 PORT_Assert (state->depth == child->depth);
1496 sec_asn1d_notify_before (state->top, child->dest, child->depth);
1499 * This will tell DecoderUpdate to return when it is done.
1501 state->place = afterSaveEncoding;
1504 * We already have a child; "push" it by making it current.
1506 state->top->current = child;
1509 * And initialize it so it is ready to parse.
1511 (void) sec_asn1d_init_state_based_on_template(child);
1514 * Now parse that out of our data.
1516 if (SEC_ASN1DecoderUpdate (state->top,
1517 (char *) item->data, item->len) != SECSuccess)
1518 return;
1519 if (state->top->status == needBytes) {
1520 return;
1523 PORT_Assert (state->top->current == state);
1524 PORT_Assert (state->child == child);
1527 * That should have consumed what we consumed before.
1529 PORT_Assert (consumed == child->consumed);
1530 child->consumed = 0;
1533 * Done.
1535 state->consumed += consumed;
1536 child->place = notInUse;
1537 state->place = afterEndOfContents;
1541 static unsigned long
1542 sec_asn1d_parse_leaf (sec_asn1d_state *state,
1543 const char *buf, unsigned long len)
1545 SECItem *item;
1546 unsigned long bufLen;
1548 if (len == 0) {
1549 state->top->status = needBytes;
1550 return 0;
1553 if (state->pending < len)
1554 len = state->pending;
1556 bufLen = len;
1558 item = (SECItem *)(state->dest);
1559 if (item != NULL && item->data != NULL) {
1560 /* Strip leading zeroes when target is unsigned integer */
1561 if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
1562 item->len == 0 && /* MSB */
1563 item->type == siUnsignedInteger) /* unsigned */
1565 while (len > 1 && buf[0] == 0) { /* leading 0 */
1566 buf++;
1567 len--;
1570 PORT_Memcpy (item->data + item->len, buf, len);
1571 item->len += len;
1573 state->pending -= bufLen;
1574 if (state->pending == 0)
1575 state->place = beforeEndOfContents;
1577 return bufLen;
1581 static unsigned long
1582 sec_asn1d_parse_bit_string (sec_asn1d_state *state,
1583 const char *buf, unsigned long len)
1585 unsigned char byte;
1587 /*PORT_Assert (state->pending > 0); */
1588 PORT_Assert (state->place == beforeBitString);
1590 if (state->pending == 0) {
1591 if (state->dest != NULL) {
1592 SECItem *item = (SECItem *)(state->dest);
1593 item->data = NULL;
1594 item->len = 0;
1595 state->place = beforeEndOfContents;
1596 return 0;
1600 if (len == 0) {
1601 state->top->status = needBytes;
1602 return 0;
1605 byte = (unsigned char) *buf;
1606 if (byte > 7) {
1607 PORT_SetError (SEC_ERROR_BAD_DER);
1608 state->top->status = decodeError;
1609 return 0;
1612 state->bit_string_unused_bits = byte;
1613 state->place = duringBitString;
1614 state->pending -= 1;
1616 return 1;
1620 static unsigned long
1621 sec_asn1d_parse_more_bit_string (sec_asn1d_state *state,
1622 const char *buf, unsigned long len)
1624 PORT_Assert (state->place == duringBitString);
1625 if (state->pending == 0) {
1626 /* An empty bit string with some unused bits is invalid. */
1627 if (state->bit_string_unused_bits) {
1628 PORT_SetError (SEC_ERROR_BAD_DER);
1629 state->top->status = decodeError;
1630 } else {
1631 /* An empty bit string with no unused bits is OK. */
1632 state->place = beforeEndOfContents;
1634 return 0;
1637 len = sec_asn1d_parse_leaf (state, buf, len);
1638 if (state->place == beforeEndOfContents && state->dest != NULL) {
1639 SECItem *item;
1641 item = (SECItem *)(state->dest);
1642 if (item->len)
1643 item->len = (item->len << 3) - state->bit_string_unused_bits;
1646 return len;
1651 * XXX All callers should be looking at return value to detect
1652 * out-of-memory errors (and stop!).
1654 static struct subitem *
1655 sec_asn1d_add_to_subitems (sec_asn1d_state *state,
1656 const void *data, unsigned long len,
1657 PRBool copy_data)
1659 struct subitem *thing;
1661 thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool,
1662 sizeof (struct subitem));
1663 if (thing == NULL) {
1664 state->top->status = decodeError;
1665 return NULL;
1668 if (copy_data) {
1669 void *copy;
1670 copy = sec_asn1d_alloc (state->top->our_pool, len);
1671 if (copy == NULL) {
1672 state->top->status = decodeError;
1673 if (!state->top->our_pool)
1674 PORT_Free(thing);
1675 return NULL;
1677 PORT_Memcpy (copy, data, len);
1678 thing->data = copy;
1679 } else {
1680 thing->data = data;
1682 thing->len = len;
1683 thing->next = NULL;
1685 if (state->subitems_head == NULL) {
1686 PORT_Assert (state->subitems_tail == NULL);
1687 state->subitems_head = state->subitems_tail = thing;
1688 } else {
1689 state->subitems_tail->next = thing;
1690 state->subitems_tail = thing;
1693 return thing;
1697 static void
1698 sec_asn1d_record_any_header (sec_asn1d_state *state,
1699 const char *buf,
1700 unsigned long len)
1702 SECItem *item;
1704 item = (SECItem *)(state->dest);
1705 if (item != NULL && item->data != NULL) {
1706 PORT_Assert (state->substring);
1707 PORT_Memcpy (item->data + item->len, buf, len);
1708 item->len += len;
1709 } else {
1710 sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE);
1716 * We are moving along through the substrings of a constructed string,
1717 * and have just finished parsing one -- we need to save our child data
1718 * (if the child was not already writing directly into the destination)
1719 * and then move forward by one.
1721 * We also have to detect when we are done:
1722 * - a definite-length encoding stops when our pending value hits 0
1723 * - an indefinite-length encoding stops when our child is empty
1724 * (which means it was the end-of-contents octets)
1726 static void
1727 sec_asn1d_next_substring (sec_asn1d_state *state)
1729 sec_asn1d_state *child;
1730 SECItem *item;
1731 unsigned long child_consumed;
1732 PRBool done;
1734 PORT_Assert (state->place == duringConstructedString);
1735 PORT_Assert (state->child != NULL);
1737 child = state->child;
1739 child_consumed = child->consumed;
1740 child->consumed = 0;
1741 state->consumed += child_consumed;
1743 done = PR_FALSE;
1745 if (state->pending) {
1746 PORT_Assert (!state->indefinite);
1747 if (child_consumed > state->pending) {
1748 PORT_SetError (SEC_ERROR_BAD_DER);
1749 state->top->status = decodeError;
1750 return;
1753 state->pending -= child_consumed;
1754 if (state->pending == 0)
1755 done = PR_TRUE;
1756 } else {
1757 PORT_Assert (state->indefinite);
1759 item = (SECItem *)(child->dest);
1760 if (item != NULL && item->data != NULL) {
1762 * Save the string away for later concatenation.
1764 PORT_Assert (item->data != NULL);
1765 sec_asn1d_add_to_subitems (state, item->data, item->len, PR_FALSE);
1767 * Clear the child item for the next round.
1769 item->data = NULL;
1770 item->len = 0;
1774 * If our child was just our end-of-contents octets, we are done.
1776 if (child->endofcontents)
1777 done = PR_TRUE;
1781 * Stop or do the next one.
1783 if (done) {
1784 child->place = notInUse;
1785 state->place = afterConstructedString;
1786 } else {
1787 sec_asn1d_scrub_state (child);
1788 state->top->current = child;
1794 * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
1796 static void
1797 sec_asn1d_next_in_group (sec_asn1d_state *state)
1799 sec_asn1d_state *child;
1800 unsigned long child_consumed;
1802 PORT_Assert (state->place == duringGroup);
1803 PORT_Assert (state->child != NULL);
1805 child = state->child;
1807 child_consumed = child->consumed;
1808 child->consumed = 0;
1809 state->consumed += child_consumed;
1812 * If our child was just our end-of-contents octets, we are done.
1814 if (child->endofcontents) {
1815 /* XXX I removed the PORT_Assert (child->dest == NULL) because there
1816 * was a bug in that a template that was a sequence of which also had
1817 * a child of a sequence of, in an indefinite group was not working
1818 * properly. This fix seems to work, (added the if statement below),
1819 * and nothing appears broken, but I am putting this note here just
1820 * in case. */
1822 * XXX No matter how many times I read that comment,
1823 * I cannot figure out what case he was fixing. I believe what he
1824 * did was deliberate, so I am loathe to touch it. I need to
1825 * understand how it could ever be that child->dest != NULL but
1826 * child->endofcontents is true, and why it is important to check
1827 * that state->subitems_head is NULL. This really needs to be
1828 * figured out, as I am not sure if the following code should be
1829 * compensating for "offset", as is done a little farther below
1830 * in the more normal case.
1832 PORT_Assert (state->indefinite);
1833 PORT_Assert (state->pending == 0);
1834 if(child->dest && !state->subitems_head) {
1835 sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE);
1836 child->dest = NULL;
1839 child->place = notInUse;
1840 state->place = afterGroup;
1841 return;
1845 * Do the "after" field notification for next in group.
1847 sec_asn1d_notify_after (state->top, child->dest, child->depth);
1850 * Save it away (unless we are not storing).
1852 if (child->dest != NULL) {
1853 void *dest;
1855 dest = child->dest;
1856 dest = (char *)dest - child->theTemplate->offset;
1857 sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE);
1858 child->dest = NULL;
1862 * Account for those bytes; see if we are done.
1864 if (state->pending) {
1865 PORT_Assert (!state->indefinite);
1866 if (child_consumed > state->pending) {
1867 PORT_SetError (SEC_ERROR_BAD_DER);
1868 state->top->status = decodeError;
1869 return;
1872 state->pending -= child_consumed;
1873 if (state->pending == 0) {
1874 child->place = notInUse;
1875 state->place = afterGroup;
1876 return;
1881 * Do the "before" field notification for next item in group.
1883 sec_asn1d_notify_before (state->top, child->dest, child->depth);
1886 * Now we do the next one.
1888 sec_asn1d_scrub_state (child);
1890 /* Initialize child state from the template */
1891 sec_asn1d_init_state_based_on_template(child);
1893 state->top->current = child;
1898 * We are moving along through a sequence; move forward by one,
1899 * (detecting end-of-sequence when it happens).
1900 * XXX The handling of "missing" is ugly. Fix it.
1902 static void
1903 sec_asn1d_next_in_sequence (sec_asn1d_state *state)
1905 sec_asn1d_state *child;
1906 unsigned long child_consumed;
1907 PRBool child_missing;
1909 PORT_Assert (state->place == duringSequence);
1910 PORT_Assert (state->child != NULL);
1912 child = state->child;
1915 * Do the "after" field notification.
1917 sec_asn1d_notify_after (state->top, child->dest, child->depth);
1919 child_missing = (PRBool) child->missing;
1920 child_consumed = child->consumed;
1921 child->consumed = 0;
1924 * Take care of accounting.
1926 if (child_missing) {
1927 PORT_Assert (child->optional);
1928 } else {
1929 state->consumed += child_consumed;
1931 * Free any grandchild.
1933 sec_asn1d_free_child (child, PR_FALSE);
1934 if (state->pending) {
1935 PORT_Assert (!state->indefinite);
1936 if (child_consumed > state->pending) {
1937 PORT_SetError (SEC_ERROR_BAD_DER);
1938 state->top->status = decodeError;
1939 return;
1941 state->pending -= child_consumed;
1942 if (state->pending == 0) {
1943 child->theTemplate++;
1944 while (child->theTemplate->kind != 0) {
1945 if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
1946 PORT_SetError (SEC_ERROR_BAD_DER);
1947 state->top->status = decodeError;
1948 return;
1950 child->theTemplate++;
1952 child->place = notInUse;
1953 state->place = afterEndOfContents;
1954 return;
1960 * Move forward.
1962 child->theTemplate++;
1963 if (child->theTemplate->kind == 0) {
1965 * We are done with this sequence.
1967 child->place = notInUse;
1968 if (state->pending) {
1969 PORT_SetError (SEC_ERROR_BAD_DER);
1970 state->top->status = decodeError;
1971 } else if (child_missing) {
1973 * We got to the end, but have a child that started parsing
1974 * and ended up "missing". The only legitimate reason for
1975 * this is that we had one or more optional fields at the
1976 * end of our sequence, and we were encoded indefinite-length,
1977 * so when we went looking for those optional fields we
1978 * found our end-of-contents octets instead.
1979 * (Yes, this is ugly; dunno a better way to handle it.)
1980 * So, first confirm the situation, and then mark that we
1981 * are done.
1983 if (state->indefinite && child->endofcontents) {
1984 PORT_Assert (child_consumed == 2);
1985 if (child_consumed != 2) {
1986 PORT_SetError (SEC_ERROR_BAD_DER);
1987 state->top->status = decodeError;
1988 } else {
1989 state->consumed += child_consumed;
1990 state->place = afterEndOfContents;
1992 } else {
1993 PORT_SetError (SEC_ERROR_BAD_DER);
1994 state->top->status = decodeError;
1996 } else {
1998 * We have to finish out, maybe reading end-of-contents octets;
1999 * let the normal logic do the right thing.
2001 state->place = beforeEndOfContents;
2003 } else {
2004 unsigned char child_found_tag_modifiers = 0;
2005 unsigned long child_found_tag_number = 0;
2008 * Reset state and push.
2010 if (state->dest != NULL)
2011 child->dest = (char *)state->dest + child->theTemplate->offset;
2014 * Do the "before" field notification.
2016 sec_asn1d_notify_before (state->top, child->dest, child->depth);
2018 if (child_missing) { /* if previous child was missing, copy the tag data we already have */
2019 child_found_tag_modifiers = child->found_tag_modifiers;
2020 child_found_tag_number = child->found_tag_number;
2022 state->top->current = child;
2023 child = sec_asn1d_init_state_based_on_template (child);
2024 if (child_missing && child) {
2025 child->place = afterIdentifier;
2026 child->found_tag_modifiers = child_found_tag_modifiers;
2027 child->found_tag_number = child_found_tag_number;
2028 child->consumed = child_consumed;
2029 if (child->underlying_kind == SEC_ASN1_ANY
2030 && !child->top->filter_only) {
2032 * If the new field is an ANY, and we are storing, then
2033 * we need to save the tag out. We would have done this
2034 * already in the normal case, but since we were looking
2035 * for an optional field, and we did not find it, we only
2036 * now realize we need to save the tag.
2038 unsigned char identifier;
2041 * Check that we did not end up with a high tag; for that
2042 * we need to re-encode the tag into multiple bytes in order
2043 * to store it back to look like what we parsed originally.
2044 * In practice this does not happen, but for completeness
2045 * sake it should probably be made to work at some point.
2047 PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
2048 identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
2049 sec_asn1d_record_any_header (child, (char *) &identifier, 1);
2056 static void
2057 sec_asn1d_concat_substrings (sec_asn1d_state *state)
2059 PORT_Assert (state->place == afterConstructedString);
2061 if (state->subitems_head != NULL) {
2062 struct subitem *substring;
2063 unsigned long alloc_len, item_len;
2064 unsigned char *where;
2065 SECItem *item;
2066 PRBool is_bit_string;
2068 item_len = 0;
2069 is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
2070 ? PR_TRUE : PR_FALSE;
2072 substring = state->subitems_head;
2073 while (substring != NULL) {
2075 * All bit-string substrings except the last one should be
2076 * a clean multiple of 8 bits.
2078 if (is_bit_string && (substring->next == NULL)
2079 && (substring->len & 0x7)) {
2080 PORT_SetError (SEC_ERROR_BAD_DER);
2081 state->top->status = decodeError;
2082 return;
2084 item_len += substring->len;
2085 substring = substring->next;
2088 if (is_bit_string) {
2089 #ifdef XP_WIN16 /* win16 compiler gets an internal error otherwise */
2090 alloc_len = (((long)item_len + 7) / 8);
2091 #else
2092 alloc_len = ((item_len + 7) >> 3);
2093 #endif
2094 } else {
2096 * Add 2 for the end-of-contents octets of an indefinite-length
2097 * ANY that is *not* also an INNER. Because we zero-allocate
2098 * below, all we need to do is increase the length here.
2100 if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
2101 item_len += 2;
2102 alloc_len = item_len;
2105 item = (SECItem *)(state->dest);
2106 PORT_Assert (item != NULL);
2107 PORT_Assert (item->data == NULL);
2108 item->data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool,
2109 alloc_len);
2110 if (item->data == NULL) {
2111 state->top->status = decodeError;
2112 return;
2114 item->len = item_len;
2116 where = item->data;
2117 substring = state->subitems_head;
2118 while (substring != NULL) {
2119 if (is_bit_string)
2120 item_len = (substring->len + 7) >> 3;
2121 else
2122 item_len = substring->len;
2123 PORT_Memcpy (where, substring->data, item_len);
2124 where += item_len;
2125 substring = substring->next;
2129 * Because we use arenas and have a mark set, we later free
2130 * everything we have allocated, so this does *not* present
2131 * a memory leak (it is just temporarily left dangling).
2133 state->subitems_head = state->subitems_tail = NULL;
2136 state->place = afterEndOfContents;
2140 static void
2141 sec_asn1d_concat_group (sec_asn1d_state *state)
2143 const void ***placep;
2145 PORT_Assert (state->place == afterGroup);
2147 placep = (const void***)state->dest;
2148 PORT_Assert(state->subitems_head == NULL || placep != NULL);
2149 if (placep != NULL) {
2150 struct subitem *item;
2151 const void **group;
2152 int count;
2154 count = 0;
2155 item = state->subitems_head;
2156 while (item != NULL) {
2157 PORT_Assert (item->next != NULL || item == state->subitems_tail);
2158 count++;
2159 item = item->next;
2162 group = (const void**)sec_asn1d_zalloc (state->top->their_pool,
2163 (count + 1) * (sizeof(void *)));
2164 if (group == NULL) {
2165 state->top->status = decodeError;
2166 return;
2169 *placep = group;
2171 item = state->subitems_head;
2172 while (item != NULL) {
2173 *group++ = item->data;
2174 item = item->next;
2176 *group = NULL;
2179 * Because we use arenas and have a mark set, we later free
2180 * everything we have allocated, so this does *not* present
2181 * a memory leak (it is just temporarily left dangling).
2183 state->subitems_head = state->subitems_tail = NULL;
2186 state->place = afterEndOfContents;
2191 * For those states that push a child to handle a subtemplate,
2192 * "absorb" that child (transfer necessary information).
2194 static void
2195 sec_asn1d_absorb_child (sec_asn1d_state *state)
2198 * There is absolutely supposed to be a child there.
2200 PORT_Assert (state->child != NULL);
2203 * Inherit the missing status of our child, and do the ugly
2204 * backing-up if necessary.
2206 state->missing = state->child->missing;
2207 if (state->missing) {
2208 state->found_tag_number = state->child->found_tag_number;
2209 state->found_tag_modifiers = state->child->found_tag_modifiers;
2210 state->endofcontents = state->child->endofcontents;
2214 * Add in number of bytes consumed by child.
2215 * (Only EXPLICIT should have already consumed bytes itself.)
2217 PORT_Assert (state->place == afterExplicit || state->consumed == 0);
2218 state->consumed += state->child->consumed;
2221 * Subtract from bytes pending; this only applies to a definite-length
2222 * EXPLICIT field.
2224 if (state->pending) {
2225 PORT_Assert (!state->indefinite);
2226 PORT_Assert (state->place == afterExplicit);
2229 * If we had a definite-length explicit, then what the child
2230 * consumed should be what was left pending.
2232 if (state->pending != state->child->consumed) {
2233 if (state->pending < state->child->consumed) {
2234 PORT_SetError (SEC_ERROR_BAD_DER);
2235 state->top->status = decodeError;
2236 return;
2239 * Okay, this is a hack. It *should* be an error whether
2240 * pending is too big or too small, but it turns out that
2241 * we had a bug in our *old* DER encoder that ended up
2242 * counting an explicit header twice in the case where
2243 * the underlying type was an ANY. So, because we cannot
2244 * prevent receiving these (our own certificate server can
2245 * send them to us), we need to be lenient and accept them.
2246 * To do so, we need to pretend as if we read all of the
2247 * bytes that the header said we would find, even though
2248 * we actually came up short.
2250 state->consumed += (state->pending - state->child->consumed);
2252 state->pending = 0;
2256 * Indicate that we are done with child.
2258 state->child->consumed = 0;
2261 * And move on to final state.
2262 * (Technically everybody could move to afterEndOfContents except
2263 * for an indefinite-length EXPLICIT; for simplicity though we assert
2264 * that but let the end-of-contents code do the real determination.)
2266 PORT_Assert (state->place == afterExplicit || (! state->indefinite));
2267 state->place = beforeEndOfContents;
2271 static void
2272 sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state)
2274 PORT_Assert (state->place == beforeEndOfContents);
2276 if (state->indefinite) {
2277 state->place = duringEndOfContents;
2278 state->pending = 2;
2279 } else {
2280 state->place = afterEndOfContents;
2285 static unsigned long
2286 sec_asn1d_parse_end_of_contents (sec_asn1d_state *state,
2287 const char *buf, unsigned long len)
2289 unsigned int i;
2291 PORT_Assert (state->pending <= 2);
2292 PORT_Assert (state->place == duringEndOfContents);
2294 if (len == 0) {
2295 state->top->status = needBytes;
2296 return 0;
2299 if (state->pending < len)
2300 len = state->pending;
2302 for (i = 0; i < len; i++) {
2303 if (buf[i] != 0) {
2305 * We expect to find only zeros; if not, just give up.
2307 PORT_SetError (SEC_ERROR_BAD_DER);
2308 state->top->status = decodeError;
2309 return 0;
2313 state->pending -= len;
2315 if (state->pending == 0) {
2316 state->place = afterEndOfContents;
2317 state->endofcontents = PR_TRUE;
2320 return len;
2324 static void
2325 sec_asn1d_pop_state (sec_asn1d_state *state)
2327 #if 0 /* XXX I think this should always be handled explicitly by parent? */
2329 * Account for our child.
2331 if (state->child != NULL) {
2332 state->consumed += state->child->consumed;
2333 if (state->pending) {
2334 PORT_Assert (!state->indefinite);
2335 if (state->child->consumed > state->pending) {
2336 PORT_SetError (SEC_ERROR_BAD_DER);
2337 state->top->status = decodeError;
2338 } else {
2339 state->pending -= state->child->consumed;
2342 state->child->consumed = 0;
2344 #endif /* XXX */
2347 * Free our child.
2349 sec_asn1d_free_child (state, PR_FALSE);
2352 * Just make my parent be the current state. It will then clean
2353 * up after me and free me (or reuse me).
2355 state->top->current = state->parent;
2358 static sec_asn1d_state *
2359 sec_asn1d_before_choice (sec_asn1d_state *state)
2361 sec_asn1d_state *child;
2363 if (state->allocate) {
2364 void *dest;
2366 dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
2367 if ((void *)NULL == dest) {
2368 state->top->status = decodeError;
2369 return (sec_asn1d_state *)NULL;
2372 state->dest = (char *)dest + state->theTemplate->offset;
2375 child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
2376 (char *)state->dest - state->theTemplate->offset,
2377 PR_FALSE);
2378 if ((sec_asn1d_state *)NULL == child) {
2379 return (sec_asn1d_state *)NULL;
2382 sec_asn1d_scrub_state(child);
2383 child = sec_asn1d_init_state_based_on_template(child);
2384 if ((sec_asn1d_state *)NULL == child) {
2385 return (sec_asn1d_state *)NULL;
2388 child->optional = PR_TRUE;
2390 state->place = duringChoice;
2392 return child;
2395 static sec_asn1d_state *
2396 sec_asn1d_during_choice (sec_asn1d_state *state)
2398 sec_asn1d_state *child = state->child;
2400 PORT_Assert((sec_asn1d_state *)NULL != child);
2402 if (child->missing) {
2403 unsigned char child_found_tag_modifiers = 0;
2404 unsigned long child_found_tag_number = 0;
2405 void * dest;
2407 state->consumed += child->consumed;
2409 if (child->endofcontents) {
2410 /* This choice is probably the first item in a GROUP
2411 ** (e.g. SET_OF) that was indefinite-length encoded.
2412 ** We're actually at the end of that GROUP.
2413 ** We look up the stack to be sure that we find
2414 ** a state with indefinite length encoding before we
2415 ** find a state (like a SEQUENCE) that is definite.
2417 child->place = notInUse;
2418 state->place = afterChoice;
2419 state->endofcontents = PR_TRUE; /* propagate this up */
2420 if (sec_asn1d_parent_allows_EOC(state))
2421 return state;
2422 PORT_SetError(SEC_ERROR_BAD_DER);
2423 state->top->status = decodeError;
2424 return NULL;
2427 dest = (char *)child->dest - child->theTemplate->offset;
2428 child->theTemplate++;
2430 if (0 == child->theTemplate->kind) {
2431 /* Ran out of choices */
2432 PORT_SetError(SEC_ERROR_BAD_DER);
2433 state->top->status = decodeError;
2434 return (sec_asn1d_state *)NULL;
2436 child->dest = (char *)dest + child->theTemplate->offset;
2438 /* cargo'd from next_in_sequence innards */
2439 if (state->pending) {
2440 PORT_Assert(!state->indefinite);
2441 if (child->consumed > state->pending) {
2442 PORT_SetError (SEC_ERROR_BAD_DER);
2443 state->top->status = decodeError;
2444 return NULL;
2446 state->pending -= child->consumed;
2447 if (0 == state->pending) {
2448 /* XXX uh.. not sure if I should have stopped this
2449 * from happening before. */
2450 PORT_Assert(0);
2451 PORT_SetError(SEC_ERROR_BAD_DER);
2452 state->top->status = decodeError;
2453 return (sec_asn1d_state *)NULL;
2457 child->consumed = 0;
2458 sec_asn1d_scrub_state(child);
2460 /* move it on top again */
2461 state->top->current = child;
2463 child_found_tag_modifiers = child->found_tag_modifiers;
2464 child_found_tag_number = child->found_tag_number;
2466 child = sec_asn1d_init_state_based_on_template(child);
2467 if ((sec_asn1d_state *)NULL == child) {
2468 return (sec_asn1d_state *)NULL;
2471 /* copy our findings to the new top */
2472 child->found_tag_modifiers = child_found_tag_modifiers;
2473 child->found_tag_number = child_found_tag_number;
2475 child->optional = PR_TRUE;
2476 child->place = afterIdentifier;
2478 return child;
2480 if ((void *)NULL != state->dest) {
2481 /* Store the enum */
2482 int *which = (int *)state->dest;
2483 *which = (int)child->theTemplate->size;
2486 child->place = notInUse;
2488 state->place = afterChoice;
2489 return state;
2492 static void
2493 sec_asn1d_after_choice (sec_asn1d_state *state)
2495 state->consumed += state->child->consumed;
2496 state->child->consumed = 0;
2497 state->place = afterEndOfContents;
2498 sec_asn1d_pop_state(state);
2501 unsigned long
2502 sec_asn1d_uinteger(SECItem *src)
2504 unsigned long value;
2505 int len;
2507 if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
2508 return 0;
2510 value = 0;
2511 len = src->len;
2512 while (len) {
2513 value <<= 8;
2514 value |= src->data[--len];
2516 return value;
2519 SECStatus
2520 SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
2522 unsigned long v;
2523 unsigned int i;
2525 if (src == NULL) {
2526 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2527 return SECFailure;
2530 if (src->len > sizeof(unsigned long)) {
2531 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2532 return SECFailure;
2535 if (src->data == NULL) {
2536 PORT_SetError(SEC_ERROR_INVALID_ARGS);
2537 return SECFailure;
2540 if (src->data[0] & 0x80)
2541 v = -1; /* signed and negative - start with all 1's */
2542 else
2543 v = 0;
2545 for (i= 0; i < src->len; i++) {
2546 /* shift in next byte */
2547 v <<= 8;
2548 v |= src->data[i];
2550 *value = v;
2551 return SECSuccess;
2554 #ifdef DEBUG_ASN1D_STATES
2555 static void
2556 dump_states(SEC_ASN1DecoderContext *cx)
2558 sec_asn1d_state *state;
2559 char kindBuf[256];
2561 for (state = cx->current; state->parent; state = state->parent) {
2565 for (; state; state = state->child) {
2566 int i;
2567 for (i = 0; i < state->depth; i++) {
2568 printf(" ");
2571 i = formatKind(state->theTemplate->kind, kindBuf);
2572 printf("%s: tmpl %08x, kind%s",
2573 (state == cx->current) ? "STATE" : "State",
2574 state->theTemplate,
2575 kindBuf);
2576 printf(" %s", (state->place >= 0 && state->place <= notInUse)
2577 ? place_names[ state->place ]
2578 : "(undefined)");
2579 if (!i)
2580 printf(", expect 0x%02x",
2581 state->expect_tag_number | state->expect_tag_modifiers);
2583 printf("%s%s%s %d\n",
2584 state->indefinite ? ", indef" : "",
2585 state->missing ? ", miss" : "",
2586 state->endofcontents ? ", EOC" : "",
2587 state->pending
2591 return;
2593 #endif /* DEBUG_ASN1D_STATES */
2595 SECStatus
2596 SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,
2597 const char *buf, unsigned long len)
2599 sec_asn1d_state *state = NULL;
2600 unsigned long consumed;
2601 SEC_ASN1EncodingPart what;
2602 sec_asn1d_state *stateEnd = cx->current;
2604 if (cx->status == needBytes)
2605 cx->status = keepGoing;
2607 while (cx->status == keepGoing) {
2608 state = cx->current;
2609 what = SEC_ASN1_Contents;
2610 consumed = 0;
2611 #ifdef DEBUG_ASN1D_STATES
2612 printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
2613 (state->place >= 0 && state->place <= notInUse) ?
2614 place_names[ state->place ] : "(undefined)",
2615 (unsigned int)((unsigned char *)buf)[ consumed ],
2616 buf, consumed);
2617 dump_states(cx);
2618 #endif /* DEBUG_ASN1D_STATES */
2619 switch (state->place) {
2620 case beforeIdentifier:
2621 consumed = sec_asn1d_parse_identifier (state, buf, len);
2622 what = SEC_ASN1_Identifier;
2623 break;
2624 case duringIdentifier:
2625 consumed = sec_asn1d_parse_more_identifier (state, buf, len);
2626 what = SEC_ASN1_Identifier;
2627 break;
2628 case afterIdentifier:
2629 sec_asn1d_confirm_identifier (state);
2630 break;
2631 case beforeLength:
2632 consumed = sec_asn1d_parse_length (state, buf, len);
2633 what = SEC_ASN1_Length;
2634 break;
2635 case duringLength:
2636 consumed = sec_asn1d_parse_more_length (state, buf, len);
2637 what = SEC_ASN1_Length;
2638 break;
2639 case afterLength:
2640 sec_asn1d_prepare_for_contents (state);
2641 break;
2642 case beforeBitString:
2643 consumed = sec_asn1d_parse_bit_string (state, buf, len);
2644 break;
2645 case duringBitString:
2646 consumed = sec_asn1d_parse_more_bit_string (state, buf, len);
2647 break;
2648 case duringConstructedString:
2649 sec_asn1d_next_substring (state);
2650 break;
2651 case duringGroup:
2652 sec_asn1d_next_in_group (state);
2653 break;
2654 case duringLeaf:
2655 consumed = sec_asn1d_parse_leaf (state, buf, len);
2656 break;
2657 case duringSaveEncoding:
2658 sec_asn1d_reuse_encoding (state);
2659 if (cx->status == decodeError) {
2660 /* recursive call has already popped all states from stack.
2661 ** Bail out quickly.
2663 return SECFailure;
2665 if (cx->status == needBytes) {
2666 /* recursive call wanted more data. Fatal. Clean up below. */
2667 PORT_SetError (SEC_ERROR_BAD_DER);
2668 cx->status = decodeError;
2670 break;
2671 case duringSequence:
2672 sec_asn1d_next_in_sequence (state);
2673 break;
2674 case afterConstructedString:
2675 sec_asn1d_concat_substrings (state);
2676 break;
2677 case afterExplicit:
2678 case afterImplicit:
2679 case afterInline:
2680 case afterPointer:
2681 sec_asn1d_absorb_child (state);
2682 break;
2683 case afterGroup:
2684 sec_asn1d_concat_group (state);
2685 break;
2686 case afterSaveEncoding:
2687 /* SEC_ASN1DecoderUpdate has called itself recursively to
2688 ** decode SAVEd encoded data, and now is done decoding that.
2689 ** Return to the calling copy of SEC_ASN1DecoderUpdate.
2691 return SECSuccess;
2692 case beforeEndOfContents:
2693 sec_asn1d_prepare_for_end_of_contents (state);
2694 break;
2695 case duringEndOfContents:
2696 consumed = sec_asn1d_parse_end_of_contents (state, buf, len);
2697 what = SEC_ASN1_EndOfContents;
2698 break;
2699 case afterEndOfContents:
2700 sec_asn1d_pop_state (state);
2701 break;
2702 case beforeChoice:
2703 state = sec_asn1d_before_choice(state);
2704 break;
2705 case duringChoice:
2706 state = sec_asn1d_during_choice(state);
2707 break;
2708 case afterChoice:
2709 sec_asn1d_after_choice(state);
2710 break;
2711 case notInUse:
2712 default:
2713 /* This is not an error, but rather a plain old BUG! */
2714 PORT_Assert (0);
2715 PORT_SetError (SEC_ERROR_BAD_DER);
2716 cx->status = decodeError;
2717 break;
2720 if (cx->status == decodeError)
2721 break;
2723 /* We should not consume more than we have. */
2724 PORT_Assert (consumed <= len);
2725 if (consumed > len) {
2726 PORT_SetError (SEC_ERROR_BAD_DER);
2727 cx->status = decodeError;
2728 break;
2731 /* It might have changed, so we have to update our local copy. */
2732 state = cx->current;
2734 /* If it is NULL, we have popped all the way to the top. */
2735 if (state == NULL) {
2736 PORT_Assert (consumed == 0);
2737 #if 0 /* XXX I want this here, but it seems that we have situations (like
2738 * downloading a pkcs7 cert chain from some issuers) that give us a
2739 * length which is greater than the entire encoding. So, we cannot
2740 * have this be an error.
2742 if (len > 0) {
2743 PORT_SetError (SEC_ERROR_BAD_DER);
2744 cx->status = decodeError;
2745 } else
2746 #endif
2747 cx->status = allDone;
2748 break;
2750 else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
2751 cx->status = allDone;
2752 break;
2755 if (consumed == 0)
2756 continue;
2759 * The following check is specifically looking for an ANY
2760 * that is *not* also an INNER, because we need to save aside
2761 * all bytes in that case -- the contents parts will get
2762 * handled like all other contents, and the end-of-contents
2763 * bytes are added by the concat code, but the outer header
2764 * bytes need to get saved too, so we do them explicitly here.
2766 if (state->underlying_kind == SEC_ASN1_ANY
2767 && !cx->filter_only && (what == SEC_ASN1_Identifier
2768 || what == SEC_ASN1_Length)) {
2769 sec_asn1d_record_any_header (state, buf, consumed);
2773 * We had some number of good, accepted bytes. If the caller
2774 * has registered to see them, pass them along.
2776 if (state->top->filter_proc != NULL) {
2777 int depth;
2779 depth = state->depth;
2780 if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
2781 PORT_Assert (state->parent != NULL
2782 && state->parent->indefinite);
2783 depth--;
2784 PORT_Assert (depth == state->parent->depth);
2786 (* state->top->filter_proc) (state->top->filter_arg,
2787 buf, consumed, depth, what);
2790 state->consumed += consumed;
2791 buf += consumed;
2792 len -= consumed;
2795 if (cx->status == decodeError) {
2796 while (state != NULL && stateEnd->parent!=state) {
2797 sec_asn1d_free_child (state, PR_TRUE);
2798 state = state->parent;
2800 #ifdef SEC_ASN1D_FREE_ON_ERROR /*
2801 * XXX This does not work because we can
2802 * end up leaving behind dangling pointers
2803 * to stuff that was allocated. In order
2804 * to make this really work (which would
2805 * be a good thing, I think), we need to
2806 * keep track of every place/pointer that
2807 * was allocated and make sure to NULL it
2808 * out before we then free back to the mark.
2810 if (cx->their_pool != NULL) {
2811 PORT_Assert (cx->their_mark != NULL);
2812 PORT_ArenaRelease (cx->their_pool, cx->their_mark);
2814 #endif
2815 return SECFailure;
2818 #if 0 /* XXX This is what I want, but cannot have because it seems we
2819 * have situations (like when downloading a pkcs7 cert chain from
2820 * some issuers) that give us a total length which is greater than
2821 * the entire encoding. So, we have to allow allDone to have a
2822 * remaining length greater than zero. I wanted to catch internal
2823 * bugs with this, noticing when we do not have the right length.
2824 * Oh well.
2826 PORT_Assert (len == 0
2827 && (cx->status == needBytes || cx->status == allDone));
2828 #else
2829 PORT_Assert ((len == 0 && cx->status == needBytes)
2830 || cx->status == allDone);
2831 #endif
2832 return SECSuccess;
2836 SECStatus
2837 SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx)
2839 SECStatus rv;
2841 if (cx->status == needBytes) {
2842 PORT_SetError (SEC_ERROR_BAD_DER);
2843 rv = SECFailure;
2844 } else {
2845 rv = SECSuccess;
2849 * XXX anything else that needs to be finished?
2852 PORT_FreeArena (cx->our_pool, PR_TRUE);
2854 return rv;
2858 SEC_ASN1DecoderContext *
2859 SEC_ASN1DecoderStart (PRArenaPool *their_pool, void *dest,
2860 const SEC_ASN1Template *theTemplate)
2862 PRArenaPool *our_pool;
2863 SEC_ASN1DecoderContext *cx;
2865 our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
2866 if (our_pool == NULL)
2867 return NULL;
2869 cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx));
2870 if (cx == NULL) {
2871 PORT_FreeArena (our_pool, PR_FALSE);
2872 return NULL;
2875 cx->our_pool = our_pool;
2876 if (their_pool != NULL) {
2877 cx->their_pool = their_pool;
2878 #ifdef SEC_ASN1D_FREE_ON_ERROR
2879 cx->their_mark = PORT_ArenaMark (their_pool);
2880 #endif
2883 cx->status = needBytes;
2885 if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL
2886 || sec_asn1d_init_state_based_on_template (cx->current) == NULL) {
2888 * Trouble initializing (probably due to failed allocations)
2889 * requires that we just give up.
2891 PORT_FreeArena (our_pool, PR_FALSE);
2892 return NULL;
2895 return cx;
2899 void
2900 SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx,
2901 SEC_ASN1WriteProc fn, void *arg,
2902 PRBool only)
2904 /* check that we are "between" fields here */
2905 PORT_Assert (cx->during_notify);
2907 cx->filter_proc = fn;
2908 cx->filter_arg = arg;
2909 cx->filter_only = only;
2913 void
2914 SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx)
2916 /* check that we are "between" fields here */
2917 PORT_Assert (cx->during_notify);
2919 cx->filter_proc = NULL;
2920 cx->filter_arg = NULL;
2921 cx->filter_only = PR_FALSE;
2925 void
2926 SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx,
2927 SEC_ASN1NotifyProc fn, void *arg)
2929 cx->notify_proc = fn;
2930 cx->notify_arg = arg;
2934 void
2935 SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx)
2937 cx->notify_proc = NULL;
2938 cx->notify_arg = NULL; /* not necessary; just being clean */
2941 void
2942 SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
2944 PORT_Assert(cx);
2945 PORT_SetError(error);
2946 cx->status = decodeError;
2950 SECStatus
2951 SEC_ASN1Decode (PRArenaPool *poolp, void *dest,
2952 const SEC_ASN1Template *theTemplate,
2953 const char *buf, long len)
2955 SEC_ASN1DecoderContext *dcx;
2956 SECStatus urv, frv;
2958 dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate);
2959 if (dcx == NULL)
2960 return SECFailure;
2962 urv = SEC_ASN1DecoderUpdate (dcx, buf, len);
2963 frv = SEC_ASN1DecoderFinish (dcx);
2965 if (urv != SECSuccess)
2966 return urv;
2968 return frv;
2972 SECStatus
2973 SEC_ASN1DecodeItem (PRArenaPool *poolp, void *dest,
2974 const SEC_ASN1Template *theTemplate,
2975 const SECItem *src)
2977 return SEC_ASN1Decode (poolp, dest, theTemplate,
2978 (const char *)src->data, src->len);
2981 #ifdef DEBUG_ASN1D_STATES
2982 void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
2984 printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
2985 fflush(stdout);
2987 #endif
2990 * Generic templates for individual/simple items and pointers to
2991 * and sets of same.
2993 * If you need to add a new one, please note the following:
2994 * - For each new basic type you should add *four* templates:
2995 * one plain, one PointerTo, one SequenceOf and one SetOf.
2996 * - If the new type can be constructed (meaning, it is a
2997 * *string* type according to BER/DER rules), then you should
2998 * or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
2999 * See the definition of the OctetString template for an example.
3000 * - It may not be obvious, but these are in *alphabetical*
3001 * order based on the SEC_ASN1_XXX name; so put new ones in
3002 * the appropriate place.
3005 const SEC_ASN1Template SEC_AnyTemplate[] = {
3006 { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3009 const SEC_ASN1Template SEC_PointerToAnyTemplate[] = {
3010 { SEC_ASN1_POINTER, 0, SEC_AnyTemplate }
3013 const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
3014 { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
3017 const SEC_ASN1Template SEC_SetOfAnyTemplate[] = {
3018 { SEC_ASN1_SET_OF, 0, SEC_AnyTemplate }
3021 const SEC_ASN1Template SEC_BitStringTemplate[] = {
3022 { SEC_ASN1_BIT_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3025 const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = {
3026 { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate }
3029 const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = {
3030 { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate }
3033 const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = {
3034 { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate }
3037 const SEC_ASN1Template SEC_BMPStringTemplate[] = {
3038 { SEC_ASN1_BMP_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3041 const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = {
3042 { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate }
3045 const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = {
3046 { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate }
3049 const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = {
3050 { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate }
3053 const SEC_ASN1Template SEC_BooleanTemplate[] = {
3054 { SEC_ASN1_BOOLEAN, 0, NULL, sizeof(SECItem) }
3057 const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = {
3058 { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate }
3061 const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = {
3062 { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate }
3065 const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = {
3066 { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate }
3069 const SEC_ASN1Template SEC_EnumeratedTemplate[] = {
3070 { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
3073 const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = {
3074 { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate }
3077 const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = {
3078 { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate }
3081 const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = {
3082 { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate }
3085 const SEC_ASN1Template SEC_GeneralizedTimeTemplate[] = {
3086 { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
3089 const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = {
3090 { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate }
3093 const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = {
3094 { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate }
3097 const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = {
3098 { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate }
3101 const SEC_ASN1Template SEC_IA5StringTemplate[] = {
3102 { SEC_ASN1_IA5_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3105 const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = {
3106 { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate }
3109 const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = {
3110 { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate }
3113 const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = {
3114 { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate }
3117 const SEC_ASN1Template SEC_IntegerTemplate[] = {
3118 { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
3121 const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = {
3122 { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate }
3125 const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = {
3126 { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate }
3129 const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = {
3130 { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate }
3133 const SEC_ASN1Template SEC_NullTemplate[] = {
3134 { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
3137 const SEC_ASN1Template SEC_PointerToNullTemplate[] = {
3138 { SEC_ASN1_POINTER, 0, SEC_NullTemplate }
3141 const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = {
3142 { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate }
3145 const SEC_ASN1Template SEC_SetOfNullTemplate[] = {
3146 { SEC_ASN1_SET_OF, 0, SEC_NullTemplate }
3149 const SEC_ASN1Template SEC_ObjectIDTemplate[] = {
3150 { SEC_ASN1_OBJECT_ID, 0, NULL, sizeof(SECItem) }
3153 const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = {
3154 { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate }
3157 const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = {
3158 { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate }
3161 const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = {
3162 { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate }
3165 const SEC_ASN1Template SEC_OctetStringTemplate[] = {
3166 { SEC_ASN1_OCTET_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3169 const SEC_ASN1Template SEC_PointerToOctetStringTemplate[] = {
3170 { SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM, 0, SEC_OctetStringTemplate }
3173 const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = {
3174 { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate }
3177 const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
3178 { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate }
3181 const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
3182 { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
3185 const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = {
3186 { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate }
3189 const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = {
3190 { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate }
3193 const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = {
3194 { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate }
3197 const SEC_ASN1Template SEC_T61StringTemplate[] = {
3198 { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3201 const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = {
3202 { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate }
3205 const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = {
3206 { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate }
3209 const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
3210 { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate }
3213 const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
3214 { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
3217 const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = {
3218 { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate }
3221 const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = {
3222 { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate }
3225 const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = {
3226 { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate }
3229 const SEC_ASN1Template SEC_UTCTimeTemplate[] = {
3230 { SEC_ASN1_UTC_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3233 const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = {
3234 { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate }
3237 const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = {
3238 { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate }
3241 const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = {
3242 { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate }
3245 const SEC_ASN1Template SEC_UTF8StringTemplate[] = {
3246 { SEC_ASN1_UTF8_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
3249 const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = {
3250 { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate }
3253 const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = {
3254 { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate }
3257 const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = {
3258 { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate }
3261 const SEC_ASN1Template SEC_VisibleStringTemplate[] = {
3262 { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
3265 const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = {
3266 { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate }
3269 const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = {
3270 { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate }
3273 const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = {
3274 { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate }
3279 * Template for skipping a subitem.
3281 * Note that it only makes sense to use this for decoding (when you want
3282 * to decode something where you are only interested in one or two of
3283 * the fields); you cannot encode a SKIP!
3285 const SEC_ASN1Template SEC_SkipTemplate[] = {
3286 { SEC_ASN1_SKIP }
3290 /* These functions simply return the address of the above-declared templates.
3291 ** This is necessary for Windows DLLs. Sigh.
3293 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_AnyTemplate)
3294 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BMPStringTemplate)
3295 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BooleanTemplate)
3296 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BitStringTemplate)
3297 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IA5StringTemplate)
3298 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_GeneralizedTimeTemplate)
3299 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IntegerTemplate)
3300 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_NullTemplate)
3301 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_ObjectIDTemplate)
3302 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_OctetStringTemplate)
3303 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToAnyTemplate)
3304 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToOctetStringTemplate)
3305 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SetOfAnyTemplate)
3306 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTCTimeTemplate)
3307 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTF8StringTemplate)