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