security/nss/lib/util/secasn1d.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/util/secasn1d.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3236 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
    1.10 + * Encoding Rules).
    1.11 + */
    1.12 +
    1.13 +/* #define DEBUG_ASN1D_STATES 1 */
    1.14 +
    1.15 +#ifdef DEBUG_ASN1D_STATES
    1.16 +#include <stdio.h>
    1.17 +#define PR_Assert sec_asn1d_Assert
    1.18 +#endif
    1.19 +
    1.20 +#include "secasn1.h"
    1.21 +#include "secerr.h"
    1.22 +
    1.23 +typedef enum {
    1.24 +    beforeIdentifier,
    1.25 +    duringIdentifier,
    1.26 +    afterIdentifier,
    1.27 +    beforeLength,
    1.28 +    duringLength,
    1.29 +    afterLength,
    1.30 +    beforeBitString,
    1.31 +    duringBitString,
    1.32 +    duringConstructedString,
    1.33 +    duringGroup,
    1.34 +    duringLeaf,
    1.35 +    duringSaveEncoding,
    1.36 +    duringSequence,
    1.37 +    afterConstructedString,
    1.38 +    afterGroup,
    1.39 +    afterExplicit,
    1.40 +    afterImplicit,
    1.41 +    afterInline,
    1.42 +    afterPointer,
    1.43 +    afterSaveEncoding,
    1.44 +    beforeEndOfContents,
    1.45 +    duringEndOfContents,
    1.46 +    afterEndOfContents,
    1.47 +    beforeChoice,
    1.48 +    duringChoice,
    1.49 +    afterChoice,
    1.50 +    notInUse
    1.51 +} sec_asn1d_parse_place;
    1.52 +
    1.53 +#ifdef DEBUG_ASN1D_STATES
    1.54 +static const char * const place_names[] = {
    1.55 +    "beforeIdentifier",
    1.56 +    "duringIdentifier",
    1.57 +    "afterIdentifier",
    1.58 +    "beforeLength",
    1.59 +    "duringLength",
    1.60 +    "afterLength",
    1.61 +    "beforeBitString",
    1.62 +    "duringBitString",
    1.63 +    "duringConstructedString",
    1.64 +    "duringGroup",
    1.65 +    "duringLeaf",
    1.66 +    "duringSaveEncoding",
    1.67 +    "duringSequence",
    1.68 +    "afterConstructedString",
    1.69 +    "afterGroup",
    1.70 +    "afterExplicit",
    1.71 +    "afterImplicit",
    1.72 +    "afterInline",
    1.73 +    "afterPointer",
    1.74 +    "afterSaveEncoding",
    1.75 +    "beforeEndOfContents",
    1.76 +    "duringEndOfContents",
    1.77 +    "afterEndOfContents",
    1.78 +    "beforeChoice",
    1.79 +    "duringChoice",
    1.80 +    "afterChoice",
    1.81 +    "notInUse"
    1.82 +};
    1.83 +
    1.84 +static const char * const class_names[] = {
    1.85 +    "UNIVERSAL",
    1.86 +    "APPLICATION",
    1.87 +    "CONTEXT_SPECIFIC",
    1.88 +    "PRIVATE"
    1.89 +};
    1.90 +
    1.91 +static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
    1.92 +
    1.93 +static const char * const type_names[] = {
    1.94 +    "END_OF_CONTENTS",
    1.95 +    "BOOLEAN",
    1.96 +    "INTEGER",
    1.97 +    "BIT_STRING",
    1.98 +    "OCTET_STRING",
    1.99 +    "NULL",
   1.100 +    "OBJECT_ID",
   1.101 +    "OBJECT_DESCRIPTOR",
   1.102 +    "(type 08)",
   1.103 +    "REAL",
   1.104 +    "ENUMERATED",
   1.105 +    "EMBEDDED",
   1.106 +    "UTF8_STRING",
   1.107 +    "(type 0d)",
   1.108 +    "(type 0e)",
   1.109 +    "(type 0f)",
   1.110 +    "SEQUENCE",
   1.111 +    "SET",
   1.112 +    "NUMERIC_STRING",
   1.113 +    "PRINTABLE_STRING",
   1.114 +    "T61_STRING",
   1.115 +    "VIDEOTEXT_STRING",
   1.116 +    "IA5_STRING",
   1.117 +    "UTC_TIME",
   1.118 +    "GENERALIZED_TIME",
   1.119 +    "GRAPHIC_STRING",
   1.120 +    "VISIBLE_STRING",
   1.121 +    "GENERAL_STRING",
   1.122 +    "UNIVERSAL_STRING",
   1.123 +    "(type 1d)",
   1.124 +    "BMP_STRING",
   1.125 +    "HIGH_TAG_VALUE"
   1.126 +};
   1.127 +
   1.128 +static const char * const flag_names[] = { /* flags, right to left */
   1.129 +    "OPTIONAL",
   1.130 +    "EXPLICIT",
   1.131 +    "ANY",
   1.132 +    "INLINE",
   1.133 +    "POINTER",
   1.134 +    "GROUP",
   1.135 +    "DYNAMIC",
   1.136 +    "SKIP",
   1.137 +    "INNER",
   1.138 +    "SAVE",
   1.139 +    "",            /* decoder ignores "MAY_STREAM", */
   1.140 +    "SKIP_REST",
   1.141 +    "CHOICE",
   1.142 +    "NO_STREAM",
   1.143 +    "DEBUG_BREAK",
   1.144 +    "unknown 08",
   1.145 +    "unknown 10",
   1.146 +    "unknown 20",
   1.147 +    "unknown 40",
   1.148 +    "unknown 80"
   1.149 +};
   1.150 +
   1.151 +static int /* bool */
   1.152 +formatKind(unsigned long kind, char * buf)
   1.153 +{
   1.154 +    int i;
   1.155 +    unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
   1.156 +    unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
   1.157 +        SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
   1.158 +
   1.159 +    buf[0] = 0;
   1.160 +    if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
   1.161 +        sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] );
   1.162 +        buf += strlen(buf);
   1.163 +    }
   1.164 +    if (kind & SEC_ASN1_METHOD_MASK) {
   1.165 +        sprintf(buf, " %s", method_names[1]);
   1.166 +        buf += strlen(buf);
   1.167 +    }
   1.168 +    if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
   1.169 +        if (k || !notag) {
   1.170 +            sprintf(buf, " %s", type_names[k] );
   1.171 +            if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
   1.172 +                (kind & SEC_ASN1_GROUP)) {
   1.173 +                buf += strlen(buf);
   1.174 +                sprintf(buf, "_OF");
   1.175 +            }
   1.176 +        }
   1.177 +    } else {
   1.178 +        sprintf(buf, " [%d]", k);
   1.179 +    }
   1.180 +    buf += strlen(buf);
   1.181 +
   1.182 +    for (k = kind >> 8, i = 0; k; k >>= 1, ++i) {
   1.183 +        if (k & 1) {
   1.184 +            sprintf(buf, " %s", flag_names[i]);
   1.185 +            buf += strlen(buf);
   1.186 +        }
   1.187 +    }
   1.188 +    return notag != 0;
   1.189 +}
   1.190 +
   1.191 +#endif /* DEBUG_ASN1D_STATES */
   1.192 +
   1.193 +typedef enum {
   1.194 +    allDone,
   1.195 +    decodeError,
   1.196 +    keepGoing,
   1.197 +    needBytes
   1.198 +} sec_asn1d_parse_status;
   1.199 +
   1.200 +struct subitem {
   1.201 +    const void *data;
   1.202 +    unsigned long len;		/* only used for substrings */
   1.203 +    struct subitem *next;
   1.204 +};
   1.205 +
   1.206 +typedef struct sec_asn1d_state_struct {
   1.207 +    SEC_ASN1DecoderContext *top;
   1.208 +    const SEC_ASN1Template *theTemplate;
   1.209 +    void *dest;
   1.210 +
   1.211 +    void *our_mark;	/* free on completion */
   1.212 +
   1.213 +    struct sec_asn1d_state_struct *parent;	/* aka prev */
   1.214 +    struct sec_asn1d_state_struct *child;	/* aka next */
   1.215 +
   1.216 +    sec_asn1d_parse_place place;
   1.217 +
   1.218 +    /*
   1.219 +     * XXX explain the next fields as clearly as possible...
   1.220 +     */
   1.221 +    unsigned char found_tag_modifiers;
   1.222 +    unsigned char expect_tag_modifiers;
   1.223 +    unsigned long check_tag_mask;
   1.224 +    unsigned long found_tag_number;
   1.225 +    unsigned long expect_tag_number;
   1.226 +    unsigned long underlying_kind;
   1.227 +
   1.228 +    unsigned long contents_length;
   1.229 +    unsigned long pending;
   1.230 +    unsigned long consumed;
   1.231 +
   1.232 +    int depth;
   1.233 +
   1.234 +    /*
   1.235 +     * Bit strings have their length adjusted -- the first octet of the
   1.236 +     * contents contains a value between 0 and 7 which says how many bits
   1.237 +     * at the end of the octets are not actually part of the bit string;
   1.238 +     * when parsing bit strings we put that value here because we need it
   1.239 +     * later, for adjustment of the length (when the whole string is done).
   1.240 +     */
   1.241 +    unsigned int bit_string_unused_bits;
   1.242 +
   1.243 +    /*
   1.244 +     * The following are used for indefinite-length constructed strings.
   1.245 +     */
   1.246 +    struct subitem *subitems_head;
   1.247 +    struct subitem *subitems_tail;
   1.248 +
   1.249 +    PRPackedBool
   1.250 +	allocate,	/* when true, need to allocate the destination */
   1.251 +	endofcontents,	/* this state ended up parsing end-of-contents octets */
   1.252 +	explicit,	/* we are handling an explicit header */
   1.253 +	indefinite,	/* the current item has indefinite-length encoding */
   1.254 +	missing,	/* an optional field that was not present */
   1.255 +	optional,	/* the template says this field may be omitted */
   1.256 +	substring;	/* this is a substring of a constructed string */
   1.257 +
   1.258 +} sec_asn1d_state;
   1.259 +
   1.260 +#define IS_HIGH_TAG_NUMBER(n)	((n) == SEC_ASN1_HIGH_TAG_NUMBER)
   1.261 +#define LAST_TAG_NUMBER_BYTE(b)	(((b) & 0x80) == 0)
   1.262 +#define TAG_NUMBER_BITS		7
   1.263 +#define TAG_NUMBER_MASK		0x7f
   1.264 +
   1.265 +#define LENGTH_IS_SHORT_FORM(b)	(((b) & 0x80) == 0)
   1.266 +#define LONG_FORM_LENGTH(b)	((b) & 0x7f)
   1.267 +
   1.268 +#define HIGH_BITS(field,cnt)	((field) >> ((sizeof(field) * 8) - (cnt)))
   1.269 +
   1.270 +
   1.271 +/*
   1.272 + * An "outsider" will have an opaque pointer to this, created by calling
   1.273 + * SEC_ASN1DecoderStart().  It will be passed back in to all subsequent
   1.274 + * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
   1.275 + * SEC_ASN1DecoderFinish().
   1.276 + */
   1.277 +struct sec_DecoderContext_struct {
   1.278 +    PLArenaPool *our_pool;		/* for our internal allocs */
   1.279 +    PLArenaPool *their_pool;		/* for destination structure allocs */
   1.280 +#ifdef SEC_ASN1D_FREE_ON_ERROR		/*
   1.281 +					 * XXX see comment below (by same
   1.282 +					 * ifdef) that explains why this
   1.283 +					 * does not work (need more smarts
   1.284 +					 * in order to free back to mark)
   1.285 +					 */
   1.286 +    /*
   1.287 +     * XXX how to make their_mark work in the case where they do NOT
   1.288 +     * give us a pool pointer?
   1.289 +     */
   1.290 +    void *their_mark;			/* free on error */
   1.291 +#endif
   1.292 +
   1.293 +    sec_asn1d_state *current;
   1.294 +    sec_asn1d_parse_status status;
   1.295 +
   1.296 +    SEC_ASN1NotifyProc notify_proc;	/* call before/after handling field */
   1.297 +    void *notify_arg;			/* argument to notify_proc */
   1.298 +    PRBool during_notify;		/* true during call to notify_proc */
   1.299 +
   1.300 +    SEC_ASN1WriteProc filter_proc;	/* pass field bytes to this  */
   1.301 +    void *filter_arg;			/* argument to that function */
   1.302 +    PRBool filter_only;			/* do not allocate/store fields */
   1.303 +};
   1.304 +
   1.305 +
   1.306 +/*
   1.307 + * XXX this is a fairly generic function that may belong elsewhere
   1.308 + */
   1.309 +static void *
   1.310 +sec_asn1d_alloc (PLArenaPool *poolp, unsigned long len)
   1.311 +{
   1.312 +    void *thing;
   1.313 +
   1.314 +    if (poolp != NULL) {
   1.315 +	/*
   1.316 +	 * Allocate from the pool.
   1.317 +	 */
   1.318 +	thing = PORT_ArenaAlloc (poolp, len);
   1.319 +    } else {
   1.320 +	/*
   1.321 +	 * Allocate generically.
   1.322 +	 */
   1.323 +	thing = PORT_Alloc (len);
   1.324 +    }
   1.325 +
   1.326 +    return thing;
   1.327 +}
   1.328 +
   1.329 +
   1.330 +/*
   1.331 + * XXX this is a fairly generic function that may belong elsewhere
   1.332 + */
   1.333 +static void *
   1.334 +sec_asn1d_zalloc (PLArenaPool *poolp, unsigned long len)
   1.335 +{
   1.336 +    void *thing;
   1.337 +
   1.338 +    thing = sec_asn1d_alloc (poolp, len);
   1.339 +    if (thing != NULL)
   1.340 +	PORT_Memset (thing, 0, len);
   1.341 +    return thing;
   1.342 +}
   1.343 +
   1.344 +
   1.345 +static sec_asn1d_state *
   1.346 +sec_asn1d_push_state (SEC_ASN1DecoderContext *cx,
   1.347 +		      const SEC_ASN1Template *theTemplate,
   1.348 +		      void *dest, PRBool new_depth)
   1.349 +{
   1.350 +    sec_asn1d_state *state, *new_state;
   1.351 +
   1.352 +    state = cx->current;
   1.353 +
   1.354 +    PORT_Assert (state == NULL || state->child == NULL);
   1.355 +
   1.356 +    if (state != NULL) {
   1.357 +	PORT_Assert (state->our_mark == NULL);
   1.358 +	state->our_mark = PORT_ArenaMark (cx->our_pool);
   1.359 +    }
   1.360 +
   1.361 +    new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool, 
   1.362 +						    sizeof(*new_state));
   1.363 +    if (new_state == NULL) {
   1.364 +	goto loser;
   1.365 +    }
   1.366 +
   1.367 +    new_state->top         = cx;
   1.368 +    new_state->parent      = state;
   1.369 +    new_state->theTemplate = theTemplate;
   1.370 +    new_state->place       = notInUse;
   1.371 +    if (dest != NULL)
   1.372 +	new_state->dest = (char *)dest + theTemplate->offset;
   1.373 +
   1.374 +    if (state != NULL) {
   1.375 +	new_state->depth = state->depth;
   1.376 +	if (new_depth) {
   1.377 +	    if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
   1.378 +		PORT_SetError (SEC_ERROR_BAD_DER);
   1.379 +		goto loser;
   1.380 +	    }
   1.381 +	}
   1.382 +	state->child = new_state;
   1.383 +    }
   1.384 +
   1.385 +    cx->current = new_state;
   1.386 +    return new_state;
   1.387 +
   1.388 +loser:
   1.389 +    cx->status = decodeError;
   1.390 +    if (state != NULL) {
   1.391 +	PORT_ArenaRelease(cx->our_pool, state->our_mark);
   1.392 +	state->our_mark = NULL;
   1.393 +    }
   1.394 +    return NULL;
   1.395 +}
   1.396 +
   1.397 +
   1.398 +static void
   1.399 +sec_asn1d_scrub_state (sec_asn1d_state *state)
   1.400 +{
   1.401 +    /*
   1.402 +     * Some default "scrubbing".
   1.403 +     * XXX right set of initializations?
   1.404 +     */
   1.405 +    state->place = beforeIdentifier;
   1.406 +    state->endofcontents = PR_FALSE;
   1.407 +    state->indefinite = PR_FALSE;
   1.408 +    state->missing = PR_FALSE;
   1.409 +    PORT_Assert (state->consumed == 0);
   1.410 +}
   1.411 +
   1.412 +
   1.413 +static void
   1.414 +sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth)
   1.415 +{
   1.416 +    if (cx->notify_proc == NULL)
   1.417 +	return;
   1.418 +
   1.419 +    cx->during_notify = PR_TRUE;
   1.420 +    (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth);
   1.421 +    cx->during_notify = PR_FALSE;
   1.422 +}
   1.423 +
   1.424 +
   1.425 +static void
   1.426 +sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth)
   1.427 +{
   1.428 +    if (cx->notify_proc == NULL)
   1.429 +	return;
   1.430 +
   1.431 +    cx->during_notify = PR_TRUE;
   1.432 +    (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth);
   1.433 +    cx->during_notify = PR_FALSE;
   1.434 +}
   1.435 +
   1.436 +
   1.437 +static sec_asn1d_state *
   1.438 +sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
   1.439 +{
   1.440 +    PRBool explicit, optional, universal;
   1.441 +    unsigned char expect_tag_modifiers;
   1.442 +    unsigned long encode_kind, under_kind;
   1.443 +    unsigned long check_tag_mask, expect_tag_number;
   1.444 +
   1.445 +
   1.446 +    /* XXX Check that both of these tests are really needed/appropriate. */
   1.447 +    if (state == NULL || state->top->status == decodeError)
   1.448 +	return state;
   1.449 +
   1.450 +    encode_kind = state->theTemplate->kind;
   1.451 +
   1.452 +    if (encode_kind & SEC_ASN1_SAVE) {
   1.453 +	/*
   1.454 +	 * This is a "magic" field that saves away all bytes, allowing
   1.455 +	 * the immediately following field to still be decoded from this
   1.456 +	 * same spot -- sort of a fork.
   1.457 +	 */
   1.458 +	/* check that there are no extraneous bits */
   1.459 +	PORT_Assert (encode_kind == SEC_ASN1_SAVE);
   1.460 +	if (state->top->filter_only) {
   1.461 +	    /*
   1.462 +	     * If we are not storing, then we do not do the SAVE field
   1.463 +	     * at all.  Just move ahead to the "real" field instead,
   1.464 +	     * doing the appropriate notify calls before and after.
   1.465 +	     */
   1.466 +	    sec_asn1d_notify_after (state->top, state->dest, state->depth);
   1.467 +	    /*
   1.468 +	     * Since we are not storing, allow for our current dest value
   1.469 +	     * to be NULL.  (This might not actually occur, but right now I
   1.470 +	     * cannot convince myself one way or the other.)  If it is NULL,
   1.471 +	     * assume that our parent dest can help us out.
   1.472 +	     */
   1.473 +	    if (state->dest == NULL)
   1.474 +		state->dest = state->parent->dest;
   1.475 +	    else
   1.476 +		state->dest = (char *)state->dest - state->theTemplate->offset;
   1.477 +	    state->theTemplate++;
   1.478 +	    if (state->dest != NULL)
   1.479 +		state->dest = (char *)state->dest + state->theTemplate->offset;
   1.480 +	    sec_asn1d_notify_before (state->top, state->dest, state->depth);
   1.481 +	    encode_kind = state->theTemplate->kind;
   1.482 +	    PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0);
   1.483 +	} else {
   1.484 +	    sec_asn1d_scrub_state (state);
   1.485 +	    state->place = duringSaveEncoding;
   1.486 +	    state = sec_asn1d_push_state (state->top, SEC_AnyTemplate,
   1.487 +					  state->dest, PR_FALSE);
   1.488 +	    if (state != NULL)
   1.489 +		state = sec_asn1d_init_state_based_on_template (state);
   1.490 +	    return state;
   1.491 +	}
   1.492 +    }
   1.493 +
   1.494 +
   1.495 +    universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
   1.496 +		? PR_TRUE : PR_FALSE;
   1.497 +
   1.498 +    explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
   1.499 +    encode_kind &= ~SEC_ASN1_EXPLICIT;
   1.500 +
   1.501 +    optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
   1.502 +    encode_kind &= ~SEC_ASN1_OPTIONAL;
   1.503 +
   1.504 +    PORT_Assert (!(explicit && universal));	/* bad templates */
   1.505 +
   1.506 +    encode_kind &= ~SEC_ASN1_DYNAMIC;
   1.507 +    encode_kind &= ~SEC_ASN1_MAY_STREAM;
   1.508 +
   1.509 +    if (encode_kind & SEC_ASN1_CHOICE) {
   1.510 +#if 0	/* XXX remove? */
   1.511 +      sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
   1.512 +      if ((sec_asn1d_state *)NULL == child) {
   1.513 +        return (sec_asn1d_state *)NULL;
   1.514 +      }
   1.515 +
   1.516 +      child->allocate = state->allocate;
   1.517 +      child->place = beforeChoice;
   1.518 +      return child;
   1.519 +#else
   1.520 +      state->place = beforeChoice;
   1.521 +      return state;
   1.522 +#endif
   1.523 +    }
   1.524 +
   1.525 +    if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal
   1.526 +							      && !explicit)) {
   1.527 +	const SEC_ASN1Template *subt;
   1.528 +	void *dest;
   1.529 +	PRBool child_allocate;
   1.530 +
   1.531 +	PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
   1.532 +
   1.533 +	sec_asn1d_scrub_state (state);
   1.534 +	child_allocate = PR_FALSE;
   1.535 +
   1.536 +	if (encode_kind & SEC_ASN1_POINTER) {
   1.537 +	    /*
   1.538 +	     * A POINTER means we need to allocate the destination for
   1.539 +	     * this field.  But, since it may also be an optional field,
   1.540 +	     * we defer the allocation until later; we just record that
   1.541 +	     * it needs to be done.
   1.542 +	     *
   1.543 +	     * There are two possible scenarios here -- one is just a
   1.544 +	     * plain POINTER (kind of like INLINE, except with allocation)
   1.545 +	     * and the other is an implicitly-tagged POINTER.  We don't
   1.546 +	     * need to do anything special here for the two cases, but
   1.547 +	     * since the template definition can be tricky, we do check
   1.548 +	     * that there are no extraneous bits set in encode_kind.
   1.549 +	     *
   1.550 +	     * XXX The same conditions which assert should set an error.
   1.551 +	     */
   1.552 +	    if (universal) {
   1.553 +		/*
   1.554 +		 * "universal" means this entry is a standalone POINTER;
   1.555 +		 * there should be no other bits set in encode_kind.
   1.556 +		 */
   1.557 +		PORT_Assert (encode_kind == SEC_ASN1_POINTER);
   1.558 +	    } else {
   1.559 +		/*
   1.560 +		 * If we get here we have an implicitly-tagged field
   1.561 +		 * that needs to be put into a POINTER.  The subtemplate
   1.562 +		 * will determine how to decode the field, but encode_kind
   1.563 +		 * describes the (implicit) tag we are looking for.
   1.564 +		 * The non-tag bits of encode_kind will be ignored by
   1.565 +		 * the code below; none of them should be set, however,
   1.566 +		 * except for the POINTER bit itself -- so check that.
   1.567 +		 */
   1.568 +		PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK)
   1.569 +			     == SEC_ASN1_POINTER);
   1.570 +	    }
   1.571 +	    if (!state->top->filter_only)
   1.572 +		child_allocate = PR_TRUE;
   1.573 +	    dest = NULL;
   1.574 +	    state->place = afterPointer;
   1.575 +	} else {
   1.576 +	    dest = state->dest;
   1.577 +	    if (encode_kind & SEC_ASN1_INLINE) {
   1.578 +		/* check that there are no extraneous bits */
   1.579 +		PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional);
   1.580 +		state->place = afterInline;
   1.581 +	    } else {
   1.582 +		state->place = afterImplicit;
   1.583 +	    }
   1.584 +	}
   1.585 +
   1.586 +	state->optional = optional;
   1.587 +	subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, PR_FALSE);
   1.588 +	state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE);
   1.589 +	if (state == NULL)
   1.590 +	    return NULL;
   1.591 +
   1.592 +	state->allocate = child_allocate;
   1.593 +
   1.594 +	if (universal) {
   1.595 +	    state = sec_asn1d_init_state_based_on_template (state);
   1.596 +	    if (state != NULL) {
   1.597 +		/*
   1.598 +		 * If this field is optional, we need to record that on
   1.599 +		 * the pushed child so it won't fail if the field isn't
   1.600 +		 * found.  I can't think of a way that this new state
   1.601 +		 * could already have optional set (which we would wipe
   1.602 +		 * out below if our local optional is not set) -- but
   1.603 +		 * just to be sure, assert that it isn't set.
   1.604 +		 */
   1.605 +		PORT_Assert (!state->optional);
   1.606 +		state->optional = optional;
   1.607 +	    }
   1.608 +	    return state;
   1.609 +	}
   1.610 +
   1.611 +	under_kind = state->theTemplate->kind;
   1.612 +	under_kind &= ~SEC_ASN1_MAY_STREAM;
   1.613 +    } else if (explicit) {
   1.614 +	/*
   1.615 +	 * For explicit, we only need to match the encoding tag next,
   1.616 +	 * then we will push another state to handle the entire inner
   1.617 +	 * part.  In this case, there is no underlying kind which plays
   1.618 +	 * any part in the determination of the outer, explicit tag.
   1.619 +	 * So we just set under_kind to 0, which is not a valid tag,
   1.620 +	 * and the rest of the tag matching stuff should be okay.
   1.621 +	 */
   1.622 +	under_kind = 0;
   1.623 +    } else {
   1.624 +	/*
   1.625 +	 * Nothing special; the underlying kind and the given encoding
   1.626 +	 * information are the same.
   1.627 +	 */
   1.628 +	under_kind = encode_kind;
   1.629 +    }
   1.630 +
   1.631 +    /* XXX is this the right set of bits to test here? */
   1.632 +    PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL
   1.633 +				| SEC_ASN1_MAY_STREAM
   1.634 +				| SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
   1.635 +
   1.636 +    if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
   1.637 +	PORT_Assert (encode_kind == under_kind);
   1.638 +	if (encode_kind & SEC_ASN1_SKIP) {
   1.639 +	    PORT_Assert (!optional);
   1.640 +	    PORT_Assert (encode_kind == SEC_ASN1_SKIP);
   1.641 +	    state->dest = NULL;
   1.642 +	}
   1.643 +	check_tag_mask = 0;
   1.644 +	expect_tag_modifiers = 0;
   1.645 +	expect_tag_number = 0;
   1.646 +    } else {
   1.647 +	check_tag_mask = SEC_ASN1_TAG_MASK;
   1.648 +	expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK
   1.649 +				& ~SEC_ASN1_TAGNUM_MASK;
   1.650 +	/*
   1.651 +	 * XXX This assumes only single-octet identifiers.  To handle
   1.652 +	 * the HIGH TAG form we would need to do some more work, especially
   1.653 +	 * in how to specify them in the template, because right now we
   1.654 +	 * do not provide a way to specify more *tag* bits in encode_kind.
   1.655 +	 */
   1.656 +	expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
   1.657 +
   1.658 +	switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
   1.659 +	  case SEC_ASN1_SET:
   1.660 +	    /*
   1.661 +	     * XXX A plain old SET (as opposed to a SET OF) is not implemented.
   1.662 +	     * If it ever is, remove this assert...
   1.663 +	     */
   1.664 +	    PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0);
   1.665 +	    /* fallthru */
   1.666 +	  case SEC_ASN1_SEQUENCE:
   1.667 +	    expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
   1.668 +	    break;
   1.669 +	  case SEC_ASN1_BIT_STRING:
   1.670 +	  case SEC_ASN1_BMP_STRING:
   1.671 +	  case SEC_ASN1_GENERALIZED_TIME:
   1.672 +	  case SEC_ASN1_IA5_STRING:
   1.673 +	  case SEC_ASN1_OCTET_STRING:
   1.674 +	  case SEC_ASN1_PRINTABLE_STRING:
   1.675 +	  case SEC_ASN1_T61_STRING:
   1.676 +	  case SEC_ASN1_UNIVERSAL_STRING:
   1.677 +	  case SEC_ASN1_UTC_TIME:
   1.678 +	  case SEC_ASN1_UTF8_STRING:
   1.679 +	  case SEC_ASN1_VISIBLE_STRING:
   1.680 +	    check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
   1.681 +	    break;
   1.682 +	}
   1.683 +    }
   1.684 +
   1.685 +    state->check_tag_mask = check_tag_mask;
   1.686 +    state->expect_tag_modifiers = expect_tag_modifiers;
   1.687 +    state->expect_tag_number = expect_tag_number;
   1.688 +    state->underlying_kind = under_kind;
   1.689 +    state->explicit = explicit;
   1.690 +    state->optional = optional;
   1.691 +
   1.692 +    sec_asn1d_scrub_state (state);
   1.693 +
   1.694 +    return state;
   1.695 +}
   1.696 +
   1.697 +static sec_asn1d_state *
   1.698 +sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
   1.699 +{
   1.700 +    for (state = state->parent; state; state = state->parent) {
   1.701 +	sec_asn1d_parse_place place = state->place;
   1.702 +	if (place != afterImplicit      &&
   1.703 +	    place != afterPointer       &&
   1.704 +	    place != afterInline        &&
   1.705 +	    place != afterSaveEncoding  &&
   1.706 +	    place != duringSaveEncoding &&
   1.707 +	    place != duringChoice) {
   1.708 +
   1.709 +            /* we've walked up the stack to a state that represents
   1.710 +            ** the enclosing construct.  
   1.711 +	    */
   1.712 +            break;
   1.713 +	}
   1.714 +    }
   1.715 +    return state;
   1.716 +}
   1.717 +
   1.718 +static PRBool
   1.719 +sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
   1.720 +{
   1.721 +    /* get state of enclosing construct. */
   1.722 +    state = sec_asn1d_get_enclosing_construct(state);
   1.723 +    if (state) {
   1.724 +	sec_asn1d_parse_place place = state->place;
   1.725 +        /* Is it one of the types that permits an unexpected EOC? */
   1.726 +	int eoc_permitted = 
   1.727 +	    (place == duringGroup ||
   1.728 +	     place == duringConstructedString ||
   1.729 +	     state->child->optional);
   1.730 +	return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
   1.731 +    }
   1.732 +    return PR_FALSE;
   1.733 +}
   1.734 +
   1.735 +static unsigned long
   1.736 +sec_asn1d_parse_identifier (sec_asn1d_state *state,
   1.737 +			    const char *buf, unsigned long len)
   1.738 +{
   1.739 +    unsigned char byte;
   1.740 +    unsigned char tag_number;
   1.741 +
   1.742 +    PORT_Assert (state->place == beforeIdentifier);
   1.743 +
   1.744 +    if (len == 0) {
   1.745 +	state->top->status = needBytes;
   1.746 +	return 0;
   1.747 +    }
   1.748 +
   1.749 +    byte = (unsigned char) *buf;
   1.750 +#ifdef DEBUG_ASN1D_STATES
   1.751 +    {
   1.752 +        char kindBuf[256];
   1.753 +        formatKind(byte, kindBuf);
   1.754 +        printf("Found tag %02x %s\n", byte, kindBuf);
   1.755 +    }
   1.756 +#endif
   1.757 +    tag_number = byte & SEC_ASN1_TAGNUM_MASK;
   1.758 +
   1.759 +    if (IS_HIGH_TAG_NUMBER (tag_number)) {
   1.760 +	state->place = duringIdentifier;
   1.761 +	state->found_tag_number = 0;
   1.762 +	/*
   1.763 +	 * Actually, we have no idea how many bytes are pending, but we
   1.764 +	 * do know that it is at least 1.  That is all we know; we have
   1.765 +	 * to look at each byte to know if there is another, etc.
   1.766 +	 */
   1.767 +	state->pending = 1;
   1.768 +    } else {
   1.769 +	if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
   1.770 +	    /*
   1.771 +	     * Our parent has indefinite-length encoding, and the
   1.772 +	     * entire tag found is 0, so it seems that we have hit the
   1.773 +	     * end-of-contents octets.  To handle this, we just change
   1.774 +	     * our state to that which expects to get the bytes of the
   1.775 +	     * end-of-contents octets and let that code re-read this byte
   1.776 +	     * so that our categorization of field types is correct.
   1.777 +	     * After that, our parent will then deal with everything else.
   1.778 +	     */
   1.779 +	    state->place = duringEndOfContents;
   1.780 +	    state->pending = 2;
   1.781 +	    state->found_tag_number = 0;
   1.782 +	    state->found_tag_modifiers = 0;
   1.783 +	    /*
   1.784 +	     * We might be an optional field that is, as we now find out,
   1.785 +	     * missing.  Give our parent a clue that this happened.
   1.786 +	     */
   1.787 +	    if (state->optional)
   1.788 +		state->missing = PR_TRUE;
   1.789 +	    return 0;
   1.790 +	}
   1.791 +	state->place = afterIdentifier;
   1.792 +	state->found_tag_number = tag_number;
   1.793 +    }
   1.794 +    state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
   1.795 +
   1.796 +    return 1;
   1.797 +}
   1.798 +
   1.799 +
   1.800 +static unsigned long
   1.801 +sec_asn1d_parse_more_identifier (sec_asn1d_state *state,
   1.802 +				 const char *buf, unsigned long len)
   1.803 +{
   1.804 +    unsigned char byte;
   1.805 +    int count;
   1.806 +
   1.807 +    PORT_Assert (state->pending == 1);
   1.808 +    PORT_Assert (state->place == duringIdentifier);
   1.809 +
   1.810 +    if (len == 0) {
   1.811 +	state->top->status = needBytes;
   1.812 +	return 0;
   1.813 +    }
   1.814 +
   1.815 +    count = 0;
   1.816 +
   1.817 +    while (len && state->pending) {
   1.818 +	if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) {
   1.819 +	    /*
   1.820 +	     * The given high tag number overflows our container;
   1.821 +	     * just give up.  This is not likely to *ever* happen.
   1.822 +	     */
   1.823 +	    PORT_SetError (SEC_ERROR_BAD_DER);
   1.824 +	    state->top->status = decodeError;
   1.825 +	    return 0;
   1.826 +	}
   1.827 +
   1.828 +	state->found_tag_number <<= TAG_NUMBER_BITS;
   1.829 +
   1.830 +	byte = (unsigned char) buf[count++];
   1.831 +	state->found_tag_number |= (byte & TAG_NUMBER_MASK);
   1.832 +
   1.833 +	len--;
   1.834 +	if (LAST_TAG_NUMBER_BYTE (byte))
   1.835 +	    state->pending = 0;
   1.836 +    }
   1.837 +
   1.838 +    if (state->pending == 0)
   1.839 +	state->place = afterIdentifier;
   1.840 +
   1.841 +    return count;
   1.842 +}
   1.843 +
   1.844 +
   1.845 +static void
   1.846 +sec_asn1d_confirm_identifier (sec_asn1d_state *state)
   1.847 +{
   1.848 +    PRBool match;
   1.849 +
   1.850 +    PORT_Assert (state->place == afterIdentifier);
   1.851 +
   1.852 +    match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask)
   1.853 +	     == state->expect_tag_modifiers)
   1.854 +	    && ((state->found_tag_number & state->check_tag_mask)
   1.855 +		== state->expect_tag_number));
   1.856 +    if (match) {
   1.857 +	state->place = beforeLength;
   1.858 +    } else {
   1.859 +	if (state->optional) {
   1.860 +	    state->missing = PR_TRUE;
   1.861 +	    state->place = afterEndOfContents;
   1.862 +	} else {
   1.863 +	    PORT_SetError (SEC_ERROR_BAD_DER);
   1.864 +	    state->top->status = decodeError;
   1.865 +	}
   1.866 +    }
   1.867 +}
   1.868 +
   1.869 +
   1.870 +static unsigned long
   1.871 +sec_asn1d_parse_length (sec_asn1d_state *state,
   1.872 +			const char *buf, unsigned long len)
   1.873 +{
   1.874 +    unsigned char byte;
   1.875 +
   1.876 +    PORT_Assert (state->place == beforeLength);
   1.877 +
   1.878 +    if (len == 0) {
   1.879 +	state->top->status = needBytes;
   1.880 +	return 0;
   1.881 +    }
   1.882 +
   1.883 +    /*
   1.884 +     * The default/likely outcome.  It may get adjusted below.
   1.885 +     */
   1.886 +    state->place = afterLength;
   1.887 +
   1.888 +    byte = (unsigned char) *buf;
   1.889 +
   1.890 +    if (LENGTH_IS_SHORT_FORM (byte)) {
   1.891 +	state->contents_length = byte;
   1.892 +    } else {
   1.893 +	state->contents_length = 0;
   1.894 +	state->pending = LONG_FORM_LENGTH (byte);
   1.895 +	if (state->pending == 0) {
   1.896 +	    state->indefinite = PR_TRUE;
   1.897 +	} else {
   1.898 +	    state->place = duringLength;
   1.899 +	}
   1.900 +    }
   1.901 +
   1.902 +    /* If we're parsing an ANY, SKIP, or SAVE template, and 
   1.903 +    ** the object being saved is definite length encoded and constructed, 
   1.904 +    ** there's no point in decoding that construct's members.
   1.905 +    ** So, just forget it's constructed and treat it as primitive.
   1.906 +    ** (SAVE appears as an ANY at this point)
   1.907 +    */
   1.908 +    if (!state->indefinite &&
   1.909 +	(state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
   1.910 +	state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
   1.911 +    }
   1.912 +
   1.913 +    return 1;
   1.914 +}
   1.915 +
   1.916 +
   1.917 +static unsigned long
   1.918 +sec_asn1d_parse_more_length (sec_asn1d_state *state,
   1.919 +			     const char *buf, unsigned long len)
   1.920 +{
   1.921 +    int count;
   1.922 +
   1.923 +    PORT_Assert (state->pending > 0);
   1.924 +    PORT_Assert (state->place == duringLength);
   1.925 +
   1.926 +    if (len == 0) {
   1.927 +	state->top->status = needBytes;
   1.928 +	return 0;
   1.929 +    }
   1.930 +
   1.931 +    count = 0;
   1.932 +
   1.933 +    while (len && state->pending) {
   1.934 +	if (HIGH_BITS (state->contents_length, 9) != 0) {
   1.935 +	    /*
   1.936 +	     * The given full content length overflows our container;
   1.937 +	     * just give up.
   1.938 +	     */
   1.939 +	    PORT_SetError (SEC_ERROR_BAD_DER);
   1.940 +	    state->top->status = decodeError;
   1.941 +	    return 0;
   1.942 +	}
   1.943 +
   1.944 +	state->contents_length <<= 8;
   1.945 +	state->contents_length |= (unsigned char) buf[count++];
   1.946 +
   1.947 +	len--;
   1.948 +	state->pending--;
   1.949 +    }
   1.950 +
   1.951 +    if (state->pending == 0)
   1.952 +	state->place = afterLength;
   1.953 +
   1.954 +    return count;
   1.955 +}
   1.956 +
   1.957 +
   1.958 +static void
   1.959 +sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
   1.960 +{
   1.961 +    SECItem *item;
   1.962 +    PLArenaPool *poolp;
   1.963 +    unsigned long alloc_len;
   1.964 +
   1.965 +#ifdef DEBUG_ASN1D_STATES
   1.966 +    {
   1.967 +        printf("Found Length %d %s\n", state->contents_length,
   1.968 +               state->indefinite ? "indefinite" : "");
   1.969 +    }
   1.970 +#endif
   1.971 +
   1.972 +    /*
   1.973 +     * XXX I cannot decide if this allocation should exclude the case
   1.974 +     *     where state->endofcontents is true -- figure it out!
   1.975 +     */
   1.976 +    if (state->allocate) {
   1.977 +	void *dest;
   1.978 +
   1.979 +	PORT_Assert (state->dest == NULL);
   1.980 +	/*
   1.981 +	 * We are handling a POINTER or a member of a GROUP, and need to
   1.982 +	 * allocate for the data structure.
   1.983 +	 */
   1.984 +	dest = sec_asn1d_zalloc (state->top->their_pool,
   1.985 +				 state->theTemplate->size);
   1.986 +	if (dest == NULL) {
   1.987 +	    state->top->status = decodeError;
   1.988 +	    return;
   1.989 +	}
   1.990 +	state->dest = (char *)dest + state->theTemplate->offset;
   1.991 +
   1.992 +	/*
   1.993 +	 * For a member of a GROUP, our parent will later put the
   1.994 +	 * pointer wherever it belongs.  But for a POINTER, we need
   1.995 +	 * to record the destination now, in case notify or filter
   1.996 +	 * procs need access to it -- they cannot find it otherwise,
   1.997 +	 * until it is too late (for one-pass processing).
   1.998 +	 */
   1.999 +	if (state->parent->place == afterPointer) {
  1.1000 +	    void **placep;
  1.1001 +
  1.1002 +	    placep = state->parent->dest;
  1.1003 +	    *placep = dest;
  1.1004 +	}
  1.1005 +    }
  1.1006 +
  1.1007 +    /*
  1.1008 +     * Remember, length may be indefinite here!  In that case,
  1.1009 +     * both contents_length and pending will be zero.
  1.1010 +     */
  1.1011 +    state->pending = state->contents_length;
  1.1012 +
  1.1013 +    /* If this item has definite length encoding, and 
  1.1014 +    ** is enclosed by a definite length constructed type,
  1.1015 +    ** make sure it isn't longer than the remaining space in that 
  1.1016 +    ** constructed type.  
  1.1017 +    */
  1.1018 +    if (state->contents_length > 0) {
  1.1019 +	sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
  1.1020 +	if (parent && !parent->indefinite && 
  1.1021 +	    state->consumed + state->contents_length > parent->pending) {
  1.1022 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1023 +	    state->top->status = decodeError;
  1.1024 +	    return;
  1.1025 +	}
  1.1026 +    }
  1.1027 +
  1.1028 +    /*
  1.1029 +     * An EXPLICIT is nothing but an outer header, which we have
  1.1030 +     * already parsed and accepted.  Now we need to do the inner
  1.1031 +     * header and its contents.
  1.1032 +     */
  1.1033 +    if (state->explicit) {
  1.1034 +	state->place = afterExplicit;
  1.1035 +	state = sec_asn1d_push_state (state->top,
  1.1036 +				      SEC_ASN1GetSubtemplate(state->theTemplate,
  1.1037 +							     state->dest,
  1.1038 +							     PR_FALSE),
  1.1039 +				      state->dest, PR_TRUE);
  1.1040 +	if (state != NULL)
  1.1041 +	    state = sec_asn1d_init_state_based_on_template (state);
  1.1042 +	return;
  1.1043 +    }
  1.1044 +
  1.1045 +    /*
  1.1046 +     * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
  1.1047 +     * we cannot tell how many items we will end up with ... so push a
  1.1048 +     * state that can keep track of "children" (the individual members
  1.1049 +     * of the group; we will allocate as we go and put them all together
  1.1050 +     * at the end.
  1.1051 +     */
  1.1052 +    if (state->underlying_kind & SEC_ASN1_GROUP) {
  1.1053 +	/* XXX If this assertion holds (should be able to confirm it via
  1.1054 +	 * inspection, too) then move this code into the switch statement
  1.1055 +	 * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
  1.1056 +	 */
  1.1057 +	PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF
  1.1058 +	   || state->underlying_kind == SEC_ASN1_SEQUENCE_OF
  1.1059 +	   || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
  1.1060 +	   || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
  1.1061 +		     );
  1.1062 +	if (state->contents_length != 0 || state->indefinite) {
  1.1063 +	    const SEC_ASN1Template *subt;
  1.1064 +
  1.1065 +	    state->place = duringGroup;
  1.1066 +	    subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest,
  1.1067 +					   PR_FALSE);
  1.1068 +	    state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE);
  1.1069 +	    if (state != NULL) {
  1.1070 +		if (!state->top->filter_only)
  1.1071 +		    state->allocate = PR_TRUE;	/* XXX propogate this? */
  1.1072 +		/*
  1.1073 +		 * Do the "before" field notification for next in group.
  1.1074 +		 */
  1.1075 +		sec_asn1d_notify_before (state->top, state->dest, state->depth);
  1.1076 +		state = sec_asn1d_init_state_based_on_template (state);
  1.1077 +	    }
  1.1078 +	} else {
  1.1079 +	    /*
  1.1080 +	     * A group of zero; we are done.
  1.1081 +	     * Set state to afterGroup and let that code plant the NULL.
  1.1082 +	     */
  1.1083 +	    state->place = afterGroup;
  1.1084 +	}
  1.1085 +	return;
  1.1086 +    }
  1.1087 +
  1.1088 +    switch (state->underlying_kind) {
  1.1089 +      case SEC_ASN1_SEQUENCE:
  1.1090 +	/*
  1.1091 +	 * We need to push a child to handle the individual fields.
  1.1092 +	 */
  1.1093 +	state->place = duringSequence;
  1.1094 +	state = sec_asn1d_push_state (state->top, state->theTemplate + 1,
  1.1095 +				      state->dest, PR_TRUE);
  1.1096 +	if (state != NULL) {
  1.1097 +	    /*
  1.1098 +	     * Do the "before" field notification.
  1.1099 +	     */
  1.1100 +	    sec_asn1d_notify_before (state->top, state->dest, state->depth);
  1.1101 +	    state = sec_asn1d_init_state_based_on_template (state);
  1.1102 +	}
  1.1103 +	break;
  1.1104 +
  1.1105 +      case SEC_ASN1_SET:	/* XXX SET is not really implemented */
  1.1106 +	/*
  1.1107 +	 * XXX A plain SET requires special handling; scanning of a
  1.1108 +	 * template to see where a field should go (because by definition,
  1.1109 +	 * they are not in any particular order, and you have to look at
  1.1110 +	 * each tag to disambiguate what the field is).  We may never
  1.1111 +	 * implement this because in practice, it seems to be unused.
  1.1112 +	 */
  1.1113 +	PORT_Assert(0);
  1.1114 +	PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */
  1.1115 +	state->top->status = decodeError;
  1.1116 +	break;
  1.1117 +
  1.1118 +      case SEC_ASN1_NULL:
  1.1119 +	/*
  1.1120 +	 * The NULL type, by definition, is "nothing", content length of zero.
  1.1121 +	 * An indefinite-length encoding is not alloweed.
  1.1122 +	 */
  1.1123 +	if (state->contents_length || state->indefinite) {
  1.1124 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1125 +	    state->top->status = decodeError;
  1.1126 +	    break;
  1.1127 +	}
  1.1128 +	if (state->dest != NULL) {
  1.1129 +	    item = (SECItem *)(state->dest);
  1.1130 +	    item->data = NULL;
  1.1131 +	    item->len = 0;
  1.1132 +	}
  1.1133 +	state->place = afterEndOfContents;
  1.1134 +	break;
  1.1135 +
  1.1136 +      case SEC_ASN1_BMP_STRING:
  1.1137 +	/* Error if length is not divisable by 2 */
  1.1138 +	if (state->contents_length % 2) {
  1.1139 +	   PORT_SetError (SEC_ERROR_BAD_DER);
  1.1140 +	   state->top->status = decodeError;
  1.1141 +	   break;
  1.1142 +	}   
  1.1143 +	/* otherwise, handle as other string types */
  1.1144 +	goto regular_string_type;
  1.1145 +
  1.1146 +      case SEC_ASN1_UNIVERSAL_STRING:
  1.1147 +	/* Error if length is not divisable by 4 */
  1.1148 +	if (state->contents_length % 4) {
  1.1149 +	   PORT_SetError (SEC_ERROR_BAD_DER);
  1.1150 +	   state->top->status = decodeError;
  1.1151 +	   break;
  1.1152 +	}   
  1.1153 +	/* otherwise, handle as other string types */
  1.1154 +	goto regular_string_type;
  1.1155 +
  1.1156 +      case SEC_ASN1_SKIP:
  1.1157 +      case SEC_ASN1_ANY:
  1.1158 +      case SEC_ASN1_ANY_CONTENTS:
  1.1159 +	/*
  1.1160 +	 * These are not (necessarily) strings, but they need nearly
  1.1161 +	 * identical handling (especially when we need to deal with
  1.1162 +	 * constructed sub-pieces), so we pretend they are.
  1.1163 +	 */
  1.1164 +	/* fallthru */
  1.1165 +regular_string_type:
  1.1166 +      case SEC_ASN1_BIT_STRING:
  1.1167 +      case SEC_ASN1_IA5_STRING:
  1.1168 +      case SEC_ASN1_OCTET_STRING:
  1.1169 +      case SEC_ASN1_PRINTABLE_STRING:
  1.1170 +      case SEC_ASN1_T61_STRING:
  1.1171 +      case SEC_ASN1_UTC_TIME:
  1.1172 +      case SEC_ASN1_UTF8_STRING:
  1.1173 +      case SEC_ASN1_VISIBLE_STRING:
  1.1174 +	/*
  1.1175 +	 * We are allocating for a primitive or a constructed string.
  1.1176 +	 * If it is a constructed string, it may also be indefinite-length.
  1.1177 +	 * If it is primitive, the length can (legally) be zero.
  1.1178 +	 * Our first order of business is to allocate the memory for
  1.1179 +	 * the string, if we can (if we know the length).
  1.1180 +	 */
  1.1181 +	item = (SECItem *)(state->dest);
  1.1182 +
  1.1183 +	/*
  1.1184 +	 * If the item is a definite-length constructed string, then
  1.1185 +	 * the contents_length is actually larger than what we need
  1.1186 +	 * (because it also counts each intermediate header which we
  1.1187 +	 * will be throwing away as we go), but it is a perfectly good
  1.1188 +	 * upper bound that we just allocate anyway, and then concat
  1.1189 +	 * as we go; we end up wasting a few extra bytes but save a
  1.1190 +	 * whole other copy.
  1.1191 +	 */
  1.1192 +	alloc_len = state->contents_length;
  1.1193 +	poolp = NULL;	/* quiet compiler warnings about unused... */
  1.1194 +
  1.1195 +	if (item == NULL || state->top->filter_only) {
  1.1196 +	    if (item != NULL) {
  1.1197 +		item->data = NULL;
  1.1198 +		item->len = 0;
  1.1199 +	    }
  1.1200 +	    alloc_len = 0;
  1.1201 +	} else if (state->substring) {
  1.1202 +	    /*
  1.1203 +	     * If we are a substring of a constructed string, then we may
  1.1204 +	     * not have to allocate anything (because our parent, the
  1.1205 +	     * actual constructed string, did it for us).  If we are a
  1.1206 +	     * substring and we *do* have to allocate, that means our
  1.1207 +	     * parent is an indefinite-length, so we allocate from our pool;
  1.1208 +	     * later our parent will copy our string into the aggregated
  1.1209 +	     * whole and free our pool allocation.
  1.1210 +	     */
  1.1211 +	    if (item->data == NULL) {
  1.1212 +		PORT_Assert (item->len == 0);
  1.1213 +		poolp = state->top->our_pool;
  1.1214 +	    } else {
  1.1215 +		alloc_len = 0;
  1.1216 +	    }
  1.1217 +	} else {
  1.1218 +	    item->len = 0;
  1.1219 +	    item->data = NULL;
  1.1220 +	    poolp = state->top->their_pool;
  1.1221 +	}
  1.1222 +
  1.1223 +	if (alloc_len || ((! state->indefinite)
  1.1224 +			  && (state->subitems_head != NULL))) {
  1.1225 +	    struct subitem *subitem;
  1.1226 +	    int len;
  1.1227 +
  1.1228 +	    PORT_Assert (item);
  1.1229 +	    if (!item) {
  1.1230 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.1231 +		state->top->status = decodeError;
  1.1232 +		return;
  1.1233 +	    }
  1.1234 +	    PORT_Assert (item->len == 0 && item->data == NULL);
  1.1235 +	    /*
  1.1236 +	     * Check for and handle an ANY which has stashed aside the
  1.1237 +	     * header (identifier and length) bytes for us to include
  1.1238 +	     * in the saved contents.
  1.1239 +	     */
  1.1240 +	    if (state->subitems_head != NULL) {
  1.1241 +		PORT_Assert (state->underlying_kind == SEC_ASN1_ANY);
  1.1242 +		for (subitem = state->subitems_head;
  1.1243 +		     subitem != NULL; subitem = subitem->next)
  1.1244 +		    alloc_len += subitem->len;
  1.1245 +	    }
  1.1246 +
  1.1247 +	    item->data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len);
  1.1248 +	    if (item->data == NULL) {
  1.1249 +		state->top->status = decodeError;
  1.1250 +		break;
  1.1251 +	    }
  1.1252 +
  1.1253 +	    len = 0;
  1.1254 +	    for (subitem = state->subitems_head;
  1.1255 +		 subitem != NULL; subitem = subitem->next) {
  1.1256 +		PORT_Memcpy (item->data + len, subitem->data, subitem->len);
  1.1257 +		len += subitem->len;
  1.1258 +	    }
  1.1259 +	    item->len = len;
  1.1260 +
  1.1261 +	    /*
  1.1262 +	     * Because we use arenas and have a mark set, we later free
  1.1263 +	     * everything we have allocated, so this does *not* present
  1.1264 +	     * a memory leak (it is just temporarily left dangling).
  1.1265 +	     */
  1.1266 +	    state->subitems_head = state->subitems_tail = NULL;
  1.1267 +	}
  1.1268 +
  1.1269 +	if (state->contents_length == 0 && (! state->indefinite)) {
  1.1270 +	    /*
  1.1271 +	     * A zero-length simple or constructed string; we are done.
  1.1272 +	     */
  1.1273 +	    state->place = afterEndOfContents;
  1.1274 +	} else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
  1.1275 +	    const SEC_ASN1Template *sub;
  1.1276 +
  1.1277 +	    switch (state->underlying_kind) {
  1.1278 +	      case SEC_ASN1_ANY:
  1.1279 +	      case SEC_ASN1_ANY_CONTENTS:
  1.1280 +		sub = SEC_AnyTemplate;
  1.1281 +		break;
  1.1282 +	      case SEC_ASN1_BIT_STRING:
  1.1283 +		sub = SEC_BitStringTemplate;
  1.1284 +		break;
  1.1285 +	      case SEC_ASN1_BMP_STRING:
  1.1286 +		sub = SEC_BMPStringTemplate;
  1.1287 +		break;
  1.1288 +	      case SEC_ASN1_GENERALIZED_TIME:
  1.1289 +		sub = SEC_GeneralizedTimeTemplate;
  1.1290 +		break;
  1.1291 +	      case SEC_ASN1_IA5_STRING:
  1.1292 +		sub = SEC_IA5StringTemplate;
  1.1293 +		break;
  1.1294 +	      case SEC_ASN1_OCTET_STRING:
  1.1295 +		sub = SEC_OctetStringTemplate;
  1.1296 +		break;
  1.1297 +	      case SEC_ASN1_PRINTABLE_STRING:
  1.1298 +		sub = SEC_PrintableStringTemplate;
  1.1299 +		break;
  1.1300 +	      case SEC_ASN1_T61_STRING:
  1.1301 +		sub = SEC_T61StringTemplate;
  1.1302 +		break;
  1.1303 +	      case SEC_ASN1_UNIVERSAL_STRING:
  1.1304 +		sub = SEC_UniversalStringTemplate;
  1.1305 +		break;
  1.1306 +	      case SEC_ASN1_UTC_TIME:
  1.1307 +		sub = SEC_UTCTimeTemplate;
  1.1308 +		break;
  1.1309 +	      case SEC_ASN1_UTF8_STRING:
  1.1310 +		sub = SEC_UTF8StringTemplate;
  1.1311 +		break;
  1.1312 +	      case SEC_ASN1_VISIBLE_STRING:
  1.1313 +		sub = SEC_VisibleStringTemplate;
  1.1314 +		break;
  1.1315 +	      case SEC_ASN1_SKIP:
  1.1316 +		sub = SEC_SkipTemplate;
  1.1317 +		break;
  1.1318 +	      default:		/* redundant given outer switch cases, but */
  1.1319 +		PORT_Assert(0);	/* the compiler does not seem to know that, */
  1.1320 +		sub = NULL;	/* so just do enough to quiet it. */
  1.1321 +		break;
  1.1322 +	    }
  1.1323 +
  1.1324 +	    state->place = duringConstructedString;
  1.1325 +	    state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE);
  1.1326 +	    if (state != NULL) {
  1.1327 +		state->substring = PR_TRUE;	/* XXX propogate? */
  1.1328 +		state = sec_asn1d_init_state_based_on_template (state);
  1.1329 +	    }
  1.1330 +	} else if (state->indefinite) {
  1.1331 +	    /*
  1.1332 +	     * An indefinite-length string *must* be constructed!
  1.1333 +	     */
  1.1334 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1335 +	    state->top->status = decodeError;
  1.1336 +	} else {
  1.1337 +	    /*
  1.1338 +	     * A non-zero-length simple string.
  1.1339 +	     */
  1.1340 +	    if (state->underlying_kind == SEC_ASN1_BIT_STRING)
  1.1341 +		state->place = beforeBitString;
  1.1342 +	    else
  1.1343 +		state->place = duringLeaf;
  1.1344 +	}
  1.1345 +	break;
  1.1346 +
  1.1347 +      default:
  1.1348 +	/*
  1.1349 +	 * We are allocating for a simple leaf item.
  1.1350 +	 */
  1.1351 +	if (state->contents_length) {
  1.1352 +	    if (state->dest != NULL) {
  1.1353 +		item = (SECItem *)(state->dest);
  1.1354 +		item->len = 0;
  1.1355 +		if (state->top->filter_only) {
  1.1356 +		    item->data = NULL;
  1.1357 +		} else {
  1.1358 +		    item->data = (unsigned char*)
  1.1359 +		                  sec_asn1d_zalloc (state->top->their_pool,
  1.1360 +						   state->contents_length);
  1.1361 +		    if (item->data == NULL) {
  1.1362 +			state->top->status = decodeError;
  1.1363 +			return;
  1.1364 +		    }
  1.1365 +		}
  1.1366 +	    }
  1.1367 +	    state->place = duringLeaf;
  1.1368 +	} else {
  1.1369 +	    /*
  1.1370 +	     * An indefinite-length or zero-length item is not allowed.
  1.1371 +	     * (All legal cases of such were handled above.)
  1.1372 +	     */
  1.1373 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1374 +	    state->top->status = decodeError;
  1.1375 +	}
  1.1376 +    }
  1.1377 +}
  1.1378 +
  1.1379 +
  1.1380 +static void
  1.1381 +sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
  1.1382 +{
  1.1383 +    if (state->child != NULL) {
  1.1384 +	PORT_Assert (error || state->child->consumed == 0);
  1.1385 +	PORT_Assert (state->our_mark != NULL);
  1.1386 +	PORT_ArenaZRelease (state->top->our_pool, state->our_mark);
  1.1387 +	if (error && state->top->their_pool == NULL) {
  1.1388 +	    /*
  1.1389 +	     * XXX We need to free anything allocated.
  1.1390 +             * At this point, we failed in the middle of decoding. But we
  1.1391 +             * can't free the data we previously allocated with PR_Malloc
  1.1392 +             * unless we keep track of every pointer. So instead we have a
  1.1393 +             * memory leak when decoding fails half-way, unless an arena is
  1.1394 +             * used. See bug 95311 .
  1.1395 +	     */
  1.1396 +	}
  1.1397 +	state->child = NULL;
  1.1398 +	state->our_mark = NULL;
  1.1399 +    } else {
  1.1400 +	/*
  1.1401 +	 * It is important that we do not leave a mark unreleased/unmarked.
  1.1402 +	 * But I do not think we should ever have one set in this case, only
  1.1403 +	 * if we had a child (handled above).  So check for that.  If this
  1.1404 +	 * assertion should ever get hit, then we probably need to add code
  1.1405 +	 * here to release back to our_mark (and then set our_mark to NULL).
  1.1406 +	 */
  1.1407 +	PORT_Assert (state->our_mark == NULL);
  1.1408 +    }
  1.1409 +    state->place = beforeEndOfContents;
  1.1410 +}
  1.1411 +
  1.1412 +/* We have just saved an entire encoded ASN.1 object (type) for a SAVE 
  1.1413 +** template, and now in the next template, we are going to decode that 
  1.1414 +** saved data  by calling SEC_ASN1DecoderUpdate recursively.
  1.1415 +** If that recursive call fails with needBytes, it is a fatal error,
  1.1416 +** because the encoded object should have been complete.
  1.1417 +** If that recursive call fails with decodeError, it will have already
  1.1418 +** cleaned up the state stack, so we must bail out quickly.
  1.1419 +**
  1.1420 +** These checks of the status returned by the recursive call are now
  1.1421 +** done in the caller of this function, immediately after it returns.
  1.1422 +*/
  1.1423 +static void
  1.1424 +sec_asn1d_reuse_encoding (sec_asn1d_state *state)
  1.1425 +{
  1.1426 +    sec_asn1d_state *child;
  1.1427 +    unsigned long consumed;
  1.1428 +    SECItem *item;
  1.1429 +    void *dest;
  1.1430 +
  1.1431 +
  1.1432 +    child = state->child;
  1.1433 +    PORT_Assert (child != NULL);
  1.1434 +
  1.1435 +    consumed = child->consumed;
  1.1436 +    child->consumed = 0;
  1.1437 +
  1.1438 +    item = (SECItem *)(state->dest);
  1.1439 +    PORT_Assert (item != NULL);
  1.1440 +
  1.1441 +    PORT_Assert (item->len == consumed);
  1.1442 +
  1.1443 +    /*
  1.1444 +     * Free any grandchild.
  1.1445 +     */
  1.1446 +    sec_asn1d_free_child (child, PR_FALSE);
  1.1447 +
  1.1448 +    /*
  1.1449 +     * Notify after the SAVE field.
  1.1450 +     */
  1.1451 +    sec_asn1d_notify_after (state->top, state->dest, state->depth);
  1.1452 +
  1.1453 +    /*
  1.1454 +     * Adjust to get new dest and move forward.
  1.1455 +     */
  1.1456 +    dest = (char *)state->dest - state->theTemplate->offset;
  1.1457 +    state->theTemplate++;
  1.1458 +    child->dest = (char *)dest + state->theTemplate->offset;
  1.1459 +    child->theTemplate = state->theTemplate;
  1.1460 +
  1.1461 +    /*
  1.1462 +     * Notify before the "real" field.
  1.1463 +     */
  1.1464 +    PORT_Assert (state->depth == child->depth);
  1.1465 +    sec_asn1d_notify_before (state->top, child->dest, child->depth);
  1.1466 +
  1.1467 +    /*
  1.1468 +     * This will tell DecoderUpdate to return when it is done.
  1.1469 +     */
  1.1470 +    state->place = afterSaveEncoding;
  1.1471 +
  1.1472 +    /*
  1.1473 +     * We already have a child; "push" it by making it current.
  1.1474 +     */
  1.1475 +    state->top->current = child;
  1.1476 +
  1.1477 +    /*
  1.1478 +     * And initialize it so it is ready to parse.
  1.1479 +     */
  1.1480 +    (void) sec_asn1d_init_state_based_on_template(child);
  1.1481 +
  1.1482 +    /*
  1.1483 +     * Now parse that out of our data.
  1.1484 +     */
  1.1485 +    if (SEC_ASN1DecoderUpdate (state->top,
  1.1486 +			       (char *) item->data, item->len) != SECSuccess)
  1.1487 +	return;
  1.1488 +    if (state->top->status == needBytes) {
  1.1489 +	return;
  1.1490 +    }
  1.1491 +
  1.1492 +    PORT_Assert (state->top->current == state);
  1.1493 +    PORT_Assert (state->child == child);
  1.1494 +
  1.1495 +    /*
  1.1496 +     * That should have consumed what we consumed before.
  1.1497 +     */
  1.1498 +    PORT_Assert (consumed == child->consumed);
  1.1499 +    child->consumed = 0;
  1.1500 +
  1.1501 +    /*
  1.1502 +     * Done.
  1.1503 +     */
  1.1504 +    state->consumed += consumed;
  1.1505 +    child->place = notInUse;
  1.1506 +    state->place = afterEndOfContents;
  1.1507 +}
  1.1508 +
  1.1509 +
  1.1510 +static unsigned long
  1.1511 +sec_asn1d_parse_leaf (sec_asn1d_state *state,
  1.1512 +		      const char *buf, unsigned long len)
  1.1513 +{
  1.1514 +    SECItem *item;
  1.1515 +    unsigned long bufLen;
  1.1516 +
  1.1517 +    if (len == 0) {
  1.1518 +	state->top->status = needBytes;
  1.1519 +	return 0;
  1.1520 +    }
  1.1521 +
  1.1522 +    if (state->pending < len)
  1.1523 +	len = state->pending;
  1.1524 +
  1.1525 +    bufLen = len;
  1.1526 +
  1.1527 +    item = (SECItem *)(state->dest);
  1.1528 +    if (item != NULL && item->data != NULL) {
  1.1529 +	/* Strip leading zeroes when target is unsigned integer */
  1.1530 +	if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER   */
  1.1531 +	    item->len == 0 &&                             /* MSB       */
  1.1532 +	    item->type == siUnsignedInteger)              /* unsigned  */
  1.1533 +	{
  1.1534 +	    while (len > 1 && buf[0] == 0) {              /* leading 0 */
  1.1535 +		buf++;
  1.1536 +		len--;
  1.1537 +	    }
  1.1538 +	}
  1.1539 +	PORT_Memcpy (item->data + item->len, buf, len);
  1.1540 +	item->len += len;
  1.1541 +    }
  1.1542 +    state->pending -= bufLen;
  1.1543 +    if (state->pending == 0)
  1.1544 +	state->place = beforeEndOfContents;
  1.1545 +
  1.1546 +    return bufLen;
  1.1547 +}
  1.1548 +
  1.1549 +
  1.1550 +static unsigned long
  1.1551 +sec_asn1d_parse_bit_string (sec_asn1d_state *state,
  1.1552 +			    const char *buf, unsigned long len)
  1.1553 +{
  1.1554 +    unsigned char byte;
  1.1555 +
  1.1556 +    /*PORT_Assert (state->pending > 0); */
  1.1557 +    PORT_Assert (state->place == beforeBitString);
  1.1558 +
  1.1559 +    if (state->pending == 0) {
  1.1560 +	if (state->dest != NULL) {
  1.1561 +	    SECItem *item = (SECItem *)(state->dest);
  1.1562 +	    item->data = NULL;
  1.1563 +	    item->len = 0;
  1.1564 +	    state->place = beforeEndOfContents;
  1.1565 +	    return 0;
  1.1566 +	}
  1.1567 +    }
  1.1568 +
  1.1569 +    if (len == 0) {
  1.1570 +	state->top->status = needBytes;
  1.1571 +	return 0;
  1.1572 +    }
  1.1573 +
  1.1574 +    byte = (unsigned char) *buf;
  1.1575 +    if (byte > 7) {
  1.1576 +	PORT_SetError (SEC_ERROR_BAD_DER);
  1.1577 +	state->top->status = decodeError;
  1.1578 +	return 0;
  1.1579 +    }
  1.1580 +
  1.1581 +    state->bit_string_unused_bits = byte;
  1.1582 +    state->place = duringBitString;
  1.1583 +    state->pending -= 1;
  1.1584 +
  1.1585 +    return 1;
  1.1586 +}
  1.1587 +
  1.1588 +
  1.1589 +static unsigned long
  1.1590 +sec_asn1d_parse_more_bit_string (sec_asn1d_state *state,
  1.1591 +				 const char *buf, unsigned long len)
  1.1592 +{
  1.1593 +    PORT_Assert (state->place == duringBitString);
  1.1594 +    if (state->pending == 0) {
  1.1595 +	/* An empty bit string with some unused bits is invalid. */
  1.1596 +	if (state->bit_string_unused_bits) {
  1.1597 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1598 +	    state->top->status = decodeError;
  1.1599 +	} else {
  1.1600 +	    /* An empty bit string with no unused bits is OK. */
  1.1601 +	    state->place = beforeEndOfContents;
  1.1602 +	}
  1.1603 +	return 0;
  1.1604 +    }
  1.1605 +
  1.1606 +    len = sec_asn1d_parse_leaf (state, buf, len);
  1.1607 +    if (state->place == beforeEndOfContents && state->dest != NULL) {
  1.1608 +	SECItem *item;
  1.1609 +
  1.1610 +	item = (SECItem *)(state->dest);
  1.1611 +	if (item->len)
  1.1612 +	    item->len = (item->len << 3) - state->bit_string_unused_bits;
  1.1613 +    }
  1.1614 +
  1.1615 +    return len;
  1.1616 +}
  1.1617 +
  1.1618 +
  1.1619 +/*
  1.1620 + * XXX All callers should be looking at return value to detect
  1.1621 + * out-of-memory errors (and stop!).
  1.1622 + */
  1.1623 +static struct subitem *
  1.1624 +sec_asn1d_add_to_subitems (sec_asn1d_state *state,
  1.1625 +			   const void *data, unsigned long len,
  1.1626 +			   PRBool copy_data)
  1.1627 +{
  1.1628 +    struct subitem *thing;
  1.1629 +
  1.1630 +    thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool,
  1.1631 +				sizeof (struct subitem));
  1.1632 +    if (thing == NULL) {
  1.1633 +	state->top->status = decodeError;
  1.1634 +	return NULL;
  1.1635 +    }
  1.1636 +
  1.1637 +    if (copy_data) {
  1.1638 +	void *copy;
  1.1639 +	copy = sec_asn1d_alloc (state->top->our_pool, len);
  1.1640 +	if (copy == NULL) {
  1.1641 +	    state->top->status = decodeError;
  1.1642 +	    if (!state->top->our_pool)
  1.1643 +	    	PORT_Free(thing);
  1.1644 +	    return NULL;
  1.1645 +	}
  1.1646 +	PORT_Memcpy (copy, data, len);
  1.1647 +	thing->data = copy;
  1.1648 +    } else {
  1.1649 +	thing->data = data;
  1.1650 +    }
  1.1651 +    thing->len = len;
  1.1652 +    thing->next = NULL;
  1.1653 +
  1.1654 +    if (state->subitems_head == NULL) {
  1.1655 +	PORT_Assert (state->subitems_tail == NULL);
  1.1656 +	state->subitems_head = state->subitems_tail = thing;
  1.1657 +    } else {
  1.1658 +	state->subitems_tail->next = thing;
  1.1659 +	state->subitems_tail = thing;
  1.1660 +    }
  1.1661 +
  1.1662 +    return thing;
  1.1663 +}
  1.1664 +
  1.1665 +
  1.1666 +static void
  1.1667 +sec_asn1d_record_any_header (sec_asn1d_state *state,
  1.1668 +			     const char *buf,
  1.1669 +			     unsigned long len)
  1.1670 +{
  1.1671 +    SECItem *item;
  1.1672 +
  1.1673 +    item = (SECItem *)(state->dest);
  1.1674 +    if (item != NULL && item->data != NULL) {
  1.1675 +	PORT_Assert (state->substring);
  1.1676 +	PORT_Memcpy (item->data + item->len, buf, len);
  1.1677 +	item->len += len;
  1.1678 +    } else {
  1.1679 +	sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE);
  1.1680 +    }
  1.1681 +}
  1.1682 +
  1.1683 +
  1.1684 +/*
  1.1685 + * We are moving along through the substrings of a constructed string,
  1.1686 + * and have just finished parsing one -- we need to save our child data
  1.1687 + * (if the child was not already writing directly into the destination)
  1.1688 + * and then move forward by one.
  1.1689 + *
  1.1690 + * We also have to detect when we are done:
  1.1691 + *	- a definite-length encoding stops when our pending value hits 0
  1.1692 + *	- an indefinite-length encoding stops when our child is empty
  1.1693 + *	  (which means it was the end-of-contents octets)
  1.1694 + */
  1.1695 +static void
  1.1696 +sec_asn1d_next_substring (sec_asn1d_state *state)
  1.1697 +{
  1.1698 +    sec_asn1d_state *child;
  1.1699 +    SECItem *item;
  1.1700 +    unsigned long child_consumed;
  1.1701 +    PRBool done;
  1.1702 +
  1.1703 +    PORT_Assert (state->place == duringConstructedString);
  1.1704 +    PORT_Assert (state->child != NULL);
  1.1705 +
  1.1706 +    child = state->child;
  1.1707 +
  1.1708 +    child_consumed = child->consumed;
  1.1709 +    child->consumed = 0;
  1.1710 +    state->consumed += child_consumed;
  1.1711 +
  1.1712 +    done = PR_FALSE;
  1.1713 +
  1.1714 +    if (state->pending) {
  1.1715 +	PORT_Assert (!state->indefinite);
  1.1716 +	if (child_consumed > state->pending) {
  1.1717 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1718 +	    state->top->status = decodeError;
  1.1719 +	    return;
  1.1720 +	}
  1.1721 +
  1.1722 +	state->pending -= child_consumed;
  1.1723 +	if (state->pending == 0)
  1.1724 +	    done = PR_TRUE;
  1.1725 +    } else {
  1.1726 +	PORT_Assert (state->indefinite);
  1.1727 +
  1.1728 +	item = (SECItem *)(child->dest);
  1.1729 +	if (item != NULL && item->data != NULL) {
  1.1730 +	    /*
  1.1731 +	     * Save the string away for later concatenation.
  1.1732 +	     */
  1.1733 +	    PORT_Assert (item->data != NULL);
  1.1734 +	    sec_asn1d_add_to_subitems (state, item->data, item->len, PR_FALSE);
  1.1735 +	    /*
  1.1736 +	     * Clear the child item for the next round.
  1.1737 +	     */
  1.1738 +	    item->data = NULL;
  1.1739 +	    item->len = 0;
  1.1740 +	}
  1.1741 +
  1.1742 +	/*
  1.1743 +	 * If our child was just our end-of-contents octets, we are done.
  1.1744 +	 */
  1.1745 +	if (child->endofcontents)
  1.1746 +	    done = PR_TRUE;
  1.1747 +    }
  1.1748 +
  1.1749 +    /*
  1.1750 +     * Stop or do the next one.
  1.1751 +     */
  1.1752 +    if (done) {
  1.1753 +	child->place = notInUse;
  1.1754 +	state->place = afterConstructedString;
  1.1755 +    } else {
  1.1756 +	sec_asn1d_scrub_state (child);
  1.1757 +	state->top->current = child;
  1.1758 +    }
  1.1759 +}
  1.1760 +
  1.1761 +
  1.1762 +/*
  1.1763 + * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
  1.1764 + */
  1.1765 +static void
  1.1766 +sec_asn1d_next_in_group (sec_asn1d_state *state)
  1.1767 +{
  1.1768 +    sec_asn1d_state *child;
  1.1769 +    unsigned long child_consumed;
  1.1770 +
  1.1771 +    PORT_Assert (state->place == duringGroup);
  1.1772 +    PORT_Assert (state->child != NULL);
  1.1773 +
  1.1774 +    child = state->child;
  1.1775 +
  1.1776 +    child_consumed = child->consumed;
  1.1777 +    child->consumed = 0;
  1.1778 +    state->consumed += child_consumed;
  1.1779 +
  1.1780 +    /*
  1.1781 +     * If our child was just our end-of-contents octets, we are done.
  1.1782 +     */
  1.1783 +    if (child->endofcontents) {
  1.1784 +	/* XXX I removed the PORT_Assert (child->dest == NULL) because there
  1.1785 +	 * was a bug in that a template that was a sequence of which also had
  1.1786 +	 * a child of a sequence of, in an indefinite group was not working 
  1.1787 +	 * properly.  This fix seems to work, (added the if statement below),
  1.1788 +	 * and nothing appears broken, but I am putting this note here just
  1.1789 +	 * in case. */
  1.1790 +	/*
  1.1791 +	 * XXX No matter how many times I read that comment,
  1.1792 +	 * I cannot figure out what case he was fixing.  I believe what he
  1.1793 +	 * did was deliberate, so I am loathe to touch it.  I need to
  1.1794 +	 * understand how it could ever be that child->dest != NULL but
  1.1795 +	 * child->endofcontents is true, and why it is important to check
  1.1796 +	 * that state->subitems_head is NULL.  This really needs to be
  1.1797 +	 * figured out, as I am not sure if the following code should be
  1.1798 +	 * compensating for "offset", as is done a little farther below
  1.1799 +	 * in the more normal case.
  1.1800 +	 */
  1.1801 +	PORT_Assert (state->indefinite);
  1.1802 +	PORT_Assert (state->pending == 0);
  1.1803 +	if(child->dest && !state->subitems_head) {
  1.1804 +	    sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE);
  1.1805 +	    child->dest = NULL;
  1.1806 +	}
  1.1807 +
  1.1808 +	child->place = notInUse;
  1.1809 +	state->place = afterGroup;
  1.1810 +	return;
  1.1811 +    }
  1.1812 +
  1.1813 +    /* 
  1.1814 +     * Do the "after" field notification for next in group.
  1.1815 +     */
  1.1816 +    sec_asn1d_notify_after (state->top, child->dest, child->depth);
  1.1817 +
  1.1818 +    /*
  1.1819 +     * Save it away (unless we are not storing).
  1.1820 +     */
  1.1821 +    if (child->dest != NULL) {
  1.1822 +	void *dest;
  1.1823 +
  1.1824 +	dest = child->dest;
  1.1825 +	dest = (char *)dest - child->theTemplate->offset;
  1.1826 +	sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE);
  1.1827 +	child->dest = NULL;
  1.1828 +    }
  1.1829 +
  1.1830 +    /*
  1.1831 +     * Account for those bytes; see if we are done.
  1.1832 +     */
  1.1833 +    if (state->pending) {
  1.1834 +	PORT_Assert (!state->indefinite);
  1.1835 +	if (child_consumed > state->pending) {
  1.1836 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1837 +	    state->top->status = decodeError;
  1.1838 +	    return;
  1.1839 +	}
  1.1840 +
  1.1841 +	state->pending -= child_consumed;
  1.1842 +	if (state->pending == 0) {
  1.1843 +	    child->place = notInUse;
  1.1844 +	    state->place = afterGroup;
  1.1845 +	    return;
  1.1846 +	}
  1.1847 +    }
  1.1848 +
  1.1849 +    /*
  1.1850 +     * Do the "before" field notification for next item in group.
  1.1851 +     */
  1.1852 +    sec_asn1d_notify_before (state->top, child->dest, child->depth);
  1.1853 +
  1.1854 +    /*
  1.1855 +     * Now we do the next one.
  1.1856 +     */
  1.1857 +    sec_asn1d_scrub_state (child);
  1.1858 +
  1.1859 +    /* Initialize child state from the template */
  1.1860 +    sec_asn1d_init_state_based_on_template(child);
  1.1861 +
  1.1862 +    state->top->current = child;
  1.1863 +}
  1.1864 +
  1.1865 +
  1.1866 +/*
  1.1867 + * We are moving along through a sequence; move forward by one,
  1.1868 + * (detecting end-of-sequence when it happens).
  1.1869 + * XXX The handling of "missing" is ugly.  Fix it.
  1.1870 + */
  1.1871 +static void
  1.1872 +sec_asn1d_next_in_sequence (sec_asn1d_state *state)
  1.1873 +{
  1.1874 +    sec_asn1d_state *child;
  1.1875 +    unsigned long child_consumed;
  1.1876 +    PRBool child_missing;
  1.1877 +
  1.1878 +    PORT_Assert (state->place == duringSequence);
  1.1879 +    PORT_Assert (state->child != NULL);
  1.1880 +
  1.1881 +    child = state->child;
  1.1882 +
  1.1883 +    /*
  1.1884 +     * Do the "after" field notification.
  1.1885 +     */
  1.1886 +    sec_asn1d_notify_after (state->top, child->dest, child->depth);
  1.1887 +
  1.1888 +    child_missing = (PRBool) child->missing;
  1.1889 +    child_consumed = child->consumed;
  1.1890 +    child->consumed = 0;
  1.1891 +
  1.1892 +    /*
  1.1893 +     * Take care of accounting.
  1.1894 +     */
  1.1895 +    if (child_missing) {
  1.1896 +	PORT_Assert (child->optional);
  1.1897 +    } else {
  1.1898 +	state->consumed += child_consumed;
  1.1899 +	/*
  1.1900 +	 * Free any grandchild.
  1.1901 +	 */
  1.1902 +	sec_asn1d_free_child (child, PR_FALSE);
  1.1903 +	if (state->pending) {
  1.1904 +	    PORT_Assert (!state->indefinite);
  1.1905 +	    if (child_consumed > state->pending) {
  1.1906 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.1907 +		state->top->status = decodeError;
  1.1908 +		return;
  1.1909 +	    }
  1.1910 +	    state->pending -= child_consumed;
  1.1911 +	    if (state->pending == 0) {
  1.1912 +		child->theTemplate++;
  1.1913 +		while (child->theTemplate->kind != 0) {
  1.1914 +		    if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
  1.1915 +			PORT_SetError (SEC_ERROR_BAD_DER);
  1.1916 +			state->top->status = decodeError;
  1.1917 +			return;
  1.1918 +		    }
  1.1919 +		    child->theTemplate++;
  1.1920 +		}
  1.1921 +		child->place = notInUse;
  1.1922 +		state->place = afterEndOfContents;
  1.1923 +		return;
  1.1924 +	    }
  1.1925 +	}
  1.1926 +    }
  1.1927 +
  1.1928 +    /*
  1.1929 +     * Move forward.
  1.1930 +     */
  1.1931 +    child->theTemplate++;
  1.1932 +    if (child->theTemplate->kind == 0) {
  1.1933 +	/*
  1.1934 +	 * We are done with this sequence.
  1.1935 +	 */
  1.1936 +	child->place = notInUse;
  1.1937 +	if (state->pending) {
  1.1938 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1939 +	    state->top->status = decodeError;
  1.1940 +	} else if (child_missing) {
  1.1941 +	    /*
  1.1942 +	     * We got to the end, but have a child that started parsing
  1.1943 +	     * and ended up "missing".  The only legitimate reason for
  1.1944 +	     * this is that we had one or more optional fields at the
  1.1945 +	     * end of our sequence, and we were encoded indefinite-length,
  1.1946 +	     * so when we went looking for those optional fields we
  1.1947 +	     * found our end-of-contents octets instead.
  1.1948 +	     * (Yes, this is ugly; dunno a better way to handle it.)
  1.1949 +	     * So, first confirm the situation, and then mark that we
  1.1950 +	     * are done.
  1.1951 +	     */
  1.1952 +	    if (state->indefinite && child->endofcontents) {
  1.1953 +		PORT_Assert (child_consumed == 2);
  1.1954 +		if (child_consumed != 2) {
  1.1955 +		    PORT_SetError (SEC_ERROR_BAD_DER);
  1.1956 +		    state->top->status = decodeError;
  1.1957 +		} else {
  1.1958 +		    state->consumed += child_consumed;
  1.1959 +		    state->place = afterEndOfContents;
  1.1960 +		}
  1.1961 +	    } else {
  1.1962 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.1963 +		state->top->status = decodeError;
  1.1964 +	    }
  1.1965 +	} else {
  1.1966 +	    /*
  1.1967 +	     * We have to finish out, maybe reading end-of-contents octets;
  1.1968 +	     * let the normal logic do the right thing.
  1.1969 +	     */
  1.1970 +	    state->place = beforeEndOfContents;
  1.1971 +	}
  1.1972 +    } else {
  1.1973 +	unsigned char child_found_tag_modifiers = 0;
  1.1974 +	unsigned long child_found_tag_number = 0;
  1.1975 +
  1.1976 +	/*
  1.1977 +	 * Reset state and push.
  1.1978 +	 */
  1.1979 +	if (state->dest != NULL)
  1.1980 +	    child->dest = (char *)state->dest + child->theTemplate->offset;
  1.1981 +
  1.1982 +	/*
  1.1983 +	 * Do the "before" field notification.
  1.1984 +	 */
  1.1985 +	sec_asn1d_notify_before (state->top, child->dest, child->depth);
  1.1986 +
  1.1987 +	if (child_missing) { /* if previous child was missing, copy the tag data we already have */
  1.1988 +	    child_found_tag_modifiers = child->found_tag_modifiers;
  1.1989 +	    child_found_tag_number = child->found_tag_number;
  1.1990 +	}
  1.1991 +	state->top->current = child;
  1.1992 +	child = sec_asn1d_init_state_based_on_template (child);
  1.1993 +	if (child_missing && child) {
  1.1994 +	    child->place = afterIdentifier;
  1.1995 +	    child->found_tag_modifiers = child_found_tag_modifiers;
  1.1996 +	    child->found_tag_number = child_found_tag_number;
  1.1997 +	    child->consumed = child_consumed;
  1.1998 +	    if (child->underlying_kind == SEC_ASN1_ANY
  1.1999 +		&& !child->top->filter_only) {
  1.2000 +		/*
  1.2001 +		 * If the new field is an ANY, and we are storing, then
  1.2002 +		 * we need to save the tag out.  We would have done this
  1.2003 +		 * already in the normal case, but since we were looking
  1.2004 +		 * for an optional field, and we did not find it, we only
  1.2005 +		 * now realize we need to save the tag.
  1.2006 +		 */
  1.2007 +		unsigned char identifier;
  1.2008 +
  1.2009 +		/*
  1.2010 +		 * Check that we did not end up with a high tag; for that
  1.2011 +		 * we need to re-encode the tag into multiple bytes in order
  1.2012 +		 * to store it back to look like what we parsed originally.
  1.2013 +		 * In practice this does not happen, but for completeness
  1.2014 +		 * sake it should probably be made to work at some point.
  1.2015 +		 */
  1.2016 +		PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
  1.2017 +		identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
  1.2018 +		sec_asn1d_record_any_header (child, (char *) &identifier, 1);
  1.2019 +	    }
  1.2020 +	}
  1.2021 +    }
  1.2022 +}
  1.2023 +
  1.2024 +
  1.2025 +static void
  1.2026 +sec_asn1d_concat_substrings (sec_asn1d_state *state)
  1.2027 +{
  1.2028 +    PORT_Assert (state->place == afterConstructedString);
  1.2029 +
  1.2030 +    if (state->subitems_head != NULL) {
  1.2031 +	struct subitem *substring;
  1.2032 +	unsigned long alloc_len, item_len;
  1.2033 +	unsigned char *where;
  1.2034 +	SECItem *item;
  1.2035 +	PRBool is_bit_string;
  1.2036 +
  1.2037 +	item_len = 0;
  1.2038 +	is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
  1.2039 +			? PR_TRUE : PR_FALSE;
  1.2040 +
  1.2041 +	substring = state->subitems_head;
  1.2042 +	while (substring != NULL) {
  1.2043 +	    /*
  1.2044 +	     * All bit-string substrings except the last one should be
  1.2045 +	     * a clean multiple of 8 bits.
  1.2046 +	     */
  1.2047 +	    if (is_bit_string && (substring->next == NULL)
  1.2048 +			      && (substring->len & 0x7)) {
  1.2049 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.2050 +		state->top->status = decodeError;
  1.2051 +		return;
  1.2052 +	    }
  1.2053 +	    item_len += substring->len;
  1.2054 +	    substring = substring->next;
  1.2055 +	}
  1.2056 +
  1.2057 +	if (is_bit_string) {
  1.2058 +	    alloc_len = ((item_len + 7) >> 3);
  1.2059 +	} else {
  1.2060 +	    /*
  1.2061 +	     * Add 2 for the end-of-contents octets of an indefinite-length
  1.2062 +	     * ANY that is *not* also an INNER.  Because we zero-allocate
  1.2063 +	     * below, all we need to do is increase the length here.
  1.2064 +	     */
  1.2065 +	    if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
  1.2066 +		item_len += 2; 
  1.2067 +	    alloc_len = item_len;
  1.2068 +	}
  1.2069 +
  1.2070 +	item = (SECItem *)(state->dest);
  1.2071 +	PORT_Assert (item != NULL);
  1.2072 +	PORT_Assert (item->data == NULL);
  1.2073 +	item->data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool, 
  1.2074 +						       alloc_len);
  1.2075 +	if (item->data == NULL) {
  1.2076 +	    state->top->status = decodeError;
  1.2077 +	    return;
  1.2078 +	}
  1.2079 +	item->len = item_len;
  1.2080 +
  1.2081 +	where = item->data;
  1.2082 +	substring = state->subitems_head;
  1.2083 +	while (substring != NULL) {
  1.2084 +	    if (is_bit_string)
  1.2085 +		item_len = (substring->len + 7) >> 3;
  1.2086 +	    else
  1.2087 +		item_len = substring->len;
  1.2088 +	    PORT_Memcpy (where, substring->data, item_len);
  1.2089 +	    where += item_len;
  1.2090 +	    substring = substring->next;
  1.2091 +	}
  1.2092 +
  1.2093 +	/*
  1.2094 +	 * Because we use arenas and have a mark set, we later free
  1.2095 +	 * everything we have allocated, so this does *not* present
  1.2096 +	 * a memory leak (it is just temporarily left dangling).
  1.2097 +	 */
  1.2098 +	state->subitems_head = state->subitems_tail = NULL;
  1.2099 +    }
  1.2100 +
  1.2101 +    state->place = afterEndOfContents;
  1.2102 +}
  1.2103 +
  1.2104 +
  1.2105 +static void
  1.2106 +sec_asn1d_concat_group (sec_asn1d_state *state)
  1.2107 +{
  1.2108 +    const void ***placep;
  1.2109 +
  1.2110 +    PORT_Assert (state->place == afterGroup);
  1.2111 +
  1.2112 +    placep = (const void***)state->dest;
  1.2113 +    PORT_Assert(state->subitems_head == NULL || placep != NULL);
  1.2114 +    if (placep != NULL) {
  1.2115 +	struct subitem *item;
  1.2116 +	const void **group;
  1.2117 +	int count;
  1.2118 +
  1.2119 +	count = 0;
  1.2120 +	item = state->subitems_head;
  1.2121 +	while (item != NULL) {
  1.2122 +	    PORT_Assert (item->next != NULL || item == state->subitems_tail);
  1.2123 +	    count++;
  1.2124 +	    item = item->next;
  1.2125 +	}
  1.2126 +
  1.2127 +	group = (const void**)sec_asn1d_zalloc (state->top->their_pool,
  1.2128 +				  (count + 1) * (sizeof(void *)));
  1.2129 +	if (group == NULL) {
  1.2130 +	    state->top->status = decodeError;
  1.2131 +	    return;
  1.2132 +	}
  1.2133 +
  1.2134 +	*placep = group;
  1.2135 +
  1.2136 +	item = state->subitems_head;
  1.2137 +	while (item != NULL) {
  1.2138 +	    *group++ = item->data;
  1.2139 +	    item = item->next;
  1.2140 +	}
  1.2141 +	*group = NULL;
  1.2142 +
  1.2143 +	/*
  1.2144 +	 * Because we use arenas and have a mark set, we later free
  1.2145 +	 * everything we have allocated, so this does *not* present
  1.2146 +	 * a memory leak (it is just temporarily left dangling).
  1.2147 +	 */
  1.2148 +	state->subitems_head = state->subitems_tail = NULL;
  1.2149 +    }
  1.2150 +
  1.2151 +    state->place = afterEndOfContents;
  1.2152 +}
  1.2153 +
  1.2154 +
  1.2155 +/*
  1.2156 + * For those states that push a child to handle a subtemplate,
  1.2157 + * "absorb" that child (transfer necessary information).
  1.2158 + */
  1.2159 +static void
  1.2160 +sec_asn1d_absorb_child (sec_asn1d_state *state)
  1.2161 +{
  1.2162 +    /*
  1.2163 +     * There is absolutely supposed to be a child there.
  1.2164 +     */
  1.2165 +    PORT_Assert (state->child != NULL);
  1.2166 +
  1.2167 +    /*
  1.2168 +     * Inherit the missing status of our child, and do the ugly
  1.2169 +     * backing-up if necessary.
  1.2170 +     */
  1.2171 +    state->missing = state->child->missing;
  1.2172 +    if (state->missing) {
  1.2173 +	state->found_tag_number = state->child->found_tag_number;
  1.2174 +	state->found_tag_modifiers = state->child->found_tag_modifiers;
  1.2175 +	state->endofcontents = state->child->endofcontents;
  1.2176 +    }
  1.2177 +
  1.2178 +    /*
  1.2179 +     * Add in number of bytes consumed by child.
  1.2180 +     * (Only EXPLICIT should have already consumed bytes itself.)
  1.2181 +     */
  1.2182 +    PORT_Assert (state->place == afterExplicit || state->consumed == 0);
  1.2183 +    state->consumed += state->child->consumed;
  1.2184 +
  1.2185 +    /*
  1.2186 +     * Subtract from bytes pending; this only applies to a definite-length
  1.2187 +     * EXPLICIT field.
  1.2188 +     */
  1.2189 +    if (state->pending) {
  1.2190 +	PORT_Assert (!state->indefinite);
  1.2191 +	PORT_Assert (state->place == afterExplicit);
  1.2192 +
  1.2193 +	/*
  1.2194 +	 * If we had a definite-length explicit, then what the child
  1.2195 +	 * consumed should be what was left pending.
  1.2196 +	 */
  1.2197 +	if (state->pending != state->child->consumed) {
  1.2198 +	    if (state->pending < state->child->consumed) {
  1.2199 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.2200 +		state->top->status = decodeError;
  1.2201 +		return;
  1.2202 +	    }
  1.2203 +	    /*
  1.2204 +	     * Okay, this is a hack.  It *should* be an error whether
  1.2205 +	     * pending is too big or too small, but it turns out that
  1.2206 +	     * we had a bug in our *old* DER encoder that ended up
  1.2207 +	     * counting an explicit header twice in the case where
  1.2208 +	     * the underlying type was an ANY.  So, because we cannot
  1.2209 +	     * prevent receiving these (our own certificate server can
  1.2210 +	     * send them to us), we need to be lenient and accept them.
  1.2211 +	     * To do so, we need to pretend as if we read all of the
  1.2212 +	     * bytes that the header said we would find, even though
  1.2213 +	     * we actually came up short.
  1.2214 +	     */
  1.2215 +	    state->consumed += (state->pending - state->child->consumed);
  1.2216 +	}
  1.2217 +	state->pending = 0;
  1.2218 +    }
  1.2219 +
  1.2220 +    /*
  1.2221 +     * Indicate that we are done with child.
  1.2222 +     */
  1.2223 +    state->child->consumed = 0;
  1.2224 +
  1.2225 +    /*
  1.2226 +     * And move on to final state.
  1.2227 +     * (Technically everybody could move to afterEndOfContents except
  1.2228 +     * for an indefinite-length EXPLICIT; for simplicity though we assert
  1.2229 +     * that but let the end-of-contents code do the real determination.)
  1.2230 +     */
  1.2231 +    PORT_Assert (state->place == afterExplicit || (! state->indefinite));
  1.2232 +    state->place = beforeEndOfContents;
  1.2233 +}
  1.2234 +
  1.2235 +
  1.2236 +static void
  1.2237 +sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state)
  1.2238 +{
  1.2239 +    PORT_Assert (state->place == beforeEndOfContents);
  1.2240 +
  1.2241 +    if (state->indefinite) {
  1.2242 +	state->place = duringEndOfContents;
  1.2243 +	state->pending = 2;
  1.2244 +    } else {
  1.2245 +	state->place = afterEndOfContents;
  1.2246 +    }
  1.2247 +}
  1.2248 +
  1.2249 +
  1.2250 +static unsigned long
  1.2251 +sec_asn1d_parse_end_of_contents (sec_asn1d_state *state,
  1.2252 +				 const char *buf, unsigned long len)
  1.2253 +{
  1.2254 +    unsigned int i;
  1.2255 +
  1.2256 +    PORT_Assert (state->pending <= 2);
  1.2257 +    PORT_Assert (state->place == duringEndOfContents);
  1.2258 +
  1.2259 +    if (len == 0) {
  1.2260 +	state->top->status = needBytes;
  1.2261 +	return 0;
  1.2262 +    }
  1.2263 +
  1.2264 +    if (state->pending < len)
  1.2265 +	len = state->pending;
  1.2266 +
  1.2267 +    for (i = 0; i < len; i++) {
  1.2268 +	if (buf[i] != 0) {
  1.2269 +	    /*
  1.2270 +	     * We expect to find only zeros; if not, just give up.
  1.2271 +	     */
  1.2272 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.2273 +	    state->top->status = decodeError;
  1.2274 +	    return 0;
  1.2275 +	}
  1.2276 +    }
  1.2277 +
  1.2278 +    state->pending -= len;
  1.2279 +
  1.2280 +    if (state->pending == 0) {
  1.2281 +	state->place = afterEndOfContents;
  1.2282 +	state->endofcontents = PR_TRUE;
  1.2283 +    }
  1.2284 +
  1.2285 +    return len;
  1.2286 +}
  1.2287 +
  1.2288 +
  1.2289 +static void
  1.2290 +sec_asn1d_pop_state (sec_asn1d_state *state)
  1.2291 +{
  1.2292 +#if 0	/* XXX I think this should always be handled explicitly by parent? */
  1.2293 +    /*
  1.2294 +     * Account for our child.
  1.2295 +     */
  1.2296 +    if (state->child != NULL) {
  1.2297 +	state->consumed += state->child->consumed;
  1.2298 +	if (state->pending) {
  1.2299 +	    PORT_Assert (!state->indefinite);
  1.2300 +	    if (state->child->consumed > state->pending) {
  1.2301 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.2302 +		state->top->status = decodeError;
  1.2303 +	    } else {
  1.2304 +		state->pending -= state->child->consumed;
  1.2305 +	    }
  1.2306 +	}
  1.2307 +	state->child->consumed = 0;
  1.2308 +    }
  1.2309 +#endif	/* XXX */
  1.2310 +
  1.2311 +    /*
  1.2312 +     * Free our child.
  1.2313 +     */
  1.2314 +    sec_asn1d_free_child (state, PR_FALSE);
  1.2315 +
  1.2316 +    /*
  1.2317 +     * Just make my parent be the current state.  It will then clean
  1.2318 +     * up after me and free me (or reuse me).
  1.2319 +     */
  1.2320 +    state->top->current = state->parent;
  1.2321 +}
  1.2322 +
  1.2323 +static sec_asn1d_state *
  1.2324 +sec_asn1d_before_choice (sec_asn1d_state *state)
  1.2325 +{
  1.2326 +    sec_asn1d_state *child;
  1.2327 +
  1.2328 +    if (state->allocate) {
  1.2329 +	void *dest;
  1.2330 +
  1.2331 +	dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
  1.2332 +	if ((void *)NULL == dest) {
  1.2333 +	    state->top->status = decodeError;
  1.2334 +	    return (sec_asn1d_state *)NULL;
  1.2335 +	}
  1.2336 +
  1.2337 +	state->dest = (char *)dest + state->theTemplate->offset;
  1.2338 +    }
  1.2339 +
  1.2340 +    child = sec_asn1d_push_state(state->top, state->theTemplate + 1, 
  1.2341 +				 (char *)state->dest - state->theTemplate->offset, 
  1.2342 +				 PR_FALSE);
  1.2343 +    if ((sec_asn1d_state *)NULL == child) {
  1.2344 +	return (sec_asn1d_state *)NULL;
  1.2345 +    }
  1.2346 +
  1.2347 +    sec_asn1d_scrub_state(child);
  1.2348 +    child = sec_asn1d_init_state_based_on_template(child);
  1.2349 +    if ((sec_asn1d_state *)NULL == child) {
  1.2350 +	return (sec_asn1d_state *)NULL;
  1.2351 +    }
  1.2352 +
  1.2353 +    child->optional = PR_TRUE;
  1.2354 +
  1.2355 +    state->place = duringChoice;
  1.2356 +
  1.2357 +    return child;
  1.2358 +}
  1.2359 +
  1.2360 +static sec_asn1d_state *
  1.2361 +sec_asn1d_during_choice (sec_asn1d_state *state)
  1.2362 +{
  1.2363 +    sec_asn1d_state *child = state->child;
  1.2364 +    
  1.2365 +    PORT_Assert((sec_asn1d_state *)NULL != child);
  1.2366 +
  1.2367 +    if (child->missing) {
  1.2368 +	unsigned char child_found_tag_modifiers = 0;
  1.2369 +	unsigned long child_found_tag_number = 0;
  1.2370 +	void *        dest;
  1.2371 +
  1.2372 +	state->consumed += child->consumed;
  1.2373 +
  1.2374 +	if (child->endofcontents) {
  1.2375 +	    /* This choice is probably the first item in a GROUP
  1.2376 +	    ** (e.g. SET_OF) that was indefinite-length encoded.
  1.2377 +	    ** We're actually at the end of that GROUP.
  1.2378 +	    ** We look up the stack to be sure that we find
  1.2379 +	    ** a state with indefinite length encoding before we
  1.2380 +	    ** find a state (like a SEQUENCE) that is definite.
  1.2381 +	    */
  1.2382 +	    child->place = notInUse;
  1.2383 +	    state->place = afterChoice;
  1.2384 +	    state->endofcontents = PR_TRUE;  /* propagate this up */
  1.2385 +	    if (sec_asn1d_parent_allows_EOC(state))
  1.2386 +		return state;
  1.2387 +	    PORT_SetError(SEC_ERROR_BAD_DER);
  1.2388 +	    state->top->status = decodeError;
  1.2389 +	    return NULL;
  1.2390 +	}
  1.2391 +
  1.2392 +	dest = (char *)child->dest - child->theTemplate->offset;
  1.2393 +	child->theTemplate++;
  1.2394 +
  1.2395 +	if (0 == child->theTemplate->kind) {
  1.2396 +	    /* Ran out of choices */
  1.2397 +	    PORT_SetError(SEC_ERROR_BAD_DER);
  1.2398 +	    state->top->status = decodeError;
  1.2399 +	    return (sec_asn1d_state *)NULL;
  1.2400 +	}
  1.2401 +	child->dest = (char *)dest + child->theTemplate->offset;
  1.2402 +
  1.2403 +	/* cargo'd from next_in_sequence innards */
  1.2404 +	if (state->pending) {
  1.2405 +	    PORT_Assert(!state->indefinite);
  1.2406 +	    if (child->consumed > state->pending) {
  1.2407 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.2408 +		state->top->status = decodeError;
  1.2409 +		return NULL;
  1.2410 +	    }
  1.2411 +	    state->pending -= child->consumed;
  1.2412 +	    if (0 == state->pending) {
  1.2413 +		/* XXX uh.. not sure if I should have stopped this
  1.2414 +		 * from happening before. */
  1.2415 +		PORT_Assert(0);
  1.2416 +		PORT_SetError(SEC_ERROR_BAD_DER);
  1.2417 +		state->top->status = decodeError;
  1.2418 +		return (sec_asn1d_state *)NULL;
  1.2419 +	    }
  1.2420 +	}
  1.2421 +
  1.2422 +	child->consumed = 0;
  1.2423 +	sec_asn1d_scrub_state(child);
  1.2424 +
  1.2425 +	/* move it on top again */
  1.2426 +	state->top->current = child;
  1.2427 +
  1.2428 +	child_found_tag_modifiers = child->found_tag_modifiers;
  1.2429 +	child_found_tag_number = child->found_tag_number;
  1.2430 +
  1.2431 +	child = sec_asn1d_init_state_based_on_template(child);
  1.2432 +	if ((sec_asn1d_state *)NULL == child) {
  1.2433 +	    return (sec_asn1d_state *)NULL;
  1.2434 +	}
  1.2435 +
  1.2436 +	/* copy our findings to the new top */
  1.2437 +	child->found_tag_modifiers = child_found_tag_modifiers;
  1.2438 +	child->found_tag_number = child_found_tag_number;
  1.2439 +
  1.2440 +	child->optional = PR_TRUE;
  1.2441 +	child->place = afterIdentifier;
  1.2442 +
  1.2443 +	return child;
  1.2444 +    } 
  1.2445 +    if ((void *)NULL != state->dest) {
  1.2446 +	/* Store the enum */
  1.2447 +	int *which = (int *)state->dest;
  1.2448 +	*which = (int)child->theTemplate->size;
  1.2449 +    }
  1.2450 +
  1.2451 +    child->place = notInUse;
  1.2452 +
  1.2453 +    state->place = afterChoice;
  1.2454 +    return state;
  1.2455 +}
  1.2456 +
  1.2457 +static void
  1.2458 +sec_asn1d_after_choice (sec_asn1d_state *state)
  1.2459 +{
  1.2460 +    state->consumed += state->child->consumed;
  1.2461 +    state->child->consumed = 0;
  1.2462 +    state->place = afterEndOfContents;
  1.2463 +    sec_asn1d_pop_state(state);
  1.2464 +}
  1.2465 +
  1.2466 +unsigned long
  1.2467 +sec_asn1d_uinteger(SECItem *src)
  1.2468 +{
  1.2469 +    unsigned long value;
  1.2470 +    int len;
  1.2471 +
  1.2472 +    if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
  1.2473 +	return 0;
  1.2474 +
  1.2475 +    value = 0;
  1.2476 +    len = src->len;
  1.2477 +    while (len) {
  1.2478 +	value <<= 8;
  1.2479 +	value |= src->data[--len];
  1.2480 +    }
  1.2481 +    return value;
  1.2482 +}
  1.2483 +
  1.2484 +SECStatus
  1.2485 +SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
  1.2486 +{
  1.2487 +    unsigned long v;
  1.2488 +    unsigned int i;
  1.2489 +    
  1.2490 +    if (src == NULL) {
  1.2491 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.2492 +	return SECFailure;
  1.2493 +    }
  1.2494 +
  1.2495 +    if (src->len > sizeof(unsigned long)) {
  1.2496 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.2497 +	return SECFailure;
  1.2498 +    }
  1.2499 +
  1.2500 +    if (src->data == NULL) {
  1.2501 +	PORT_SetError(SEC_ERROR_INVALID_ARGS);
  1.2502 +    	return SECFailure;
  1.2503 +    }
  1.2504 +
  1.2505 +    if (src->data[0] & 0x80)
  1.2506 +	v = -1;		/* signed and negative - start with all 1's */
  1.2507 +    else
  1.2508 +	v = 0;
  1.2509 +
  1.2510 +    for (i= 0; i < src->len; i++) {
  1.2511 +	/* shift in next byte */
  1.2512 +	v <<= 8;
  1.2513 +	v |= src->data[i];
  1.2514 +    }
  1.2515 +    *value = v;
  1.2516 +    return SECSuccess;
  1.2517 +}
  1.2518 +
  1.2519 +#ifdef DEBUG_ASN1D_STATES
  1.2520 +static void
  1.2521 +dump_states(SEC_ASN1DecoderContext *cx)
  1.2522 +{
  1.2523 +    sec_asn1d_state *state;
  1.2524 +    char kindBuf[256];
  1.2525 +
  1.2526 +    for (state = cx->current; state->parent; state = state->parent) {
  1.2527 +        ;
  1.2528 +    }
  1.2529 +
  1.2530 +    for (; state; state = state->child) {
  1.2531 +        int i;
  1.2532 +        for (i = 0; i < state->depth; i++) {
  1.2533 +            printf("  ");
  1.2534 +        }
  1.2535 +
  1.2536 +        i = formatKind(state->theTemplate->kind, kindBuf);
  1.2537 +        printf("%s: tmpl %08x, kind%s",
  1.2538 +               (state == cx->current) ? "STATE" : "State",
  1.2539 +               state->theTemplate,
  1.2540 +               kindBuf);
  1.2541 +        printf(" %s", (state->place >= 0 && state->place <= notInUse)
  1.2542 +                       ? place_names[ state->place ]
  1.2543 +                       : "(undefined)");
  1.2544 +        if (!i)
  1.2545 +            printf(", expect 0x%02x",
  1.2546 +                   state->expect_tag_number | state->expect_tag_modifiers);
  1.2547 +
  1.2548 +        printf("%s%s%s %d\n",
  1.2549 +               state->indefinite    ? ", indef"   : "",
  1.2550 +               state->missing       ? ", miss"    : "",
  1.2551 +               state->endofcontents ? ", EOC"     : "",
  1.2552 +               state->pending
  1.2553 +               );
  1.2554 +    }
  1.2555 +
  1.2556 +    return;
  1.2557 +}
  1.2558 +#endif /* DEBUG_ASN1D_STATES */
  1.2559 +
  1.2560 +SECStatus
  1.2561 +SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,
  1.2562 +		       const char *buf, unsigned long len)
  1.2563 +{
  1.2564 +    sec_asn1d_state *state = NULL;
  1.2565 +    unsigned long consumed;
  1.2566 +    SEC_ASN1EncodingPart what;
  1.2567 +    sec_asn1d_state *stateEnd = cx->current;
  1.2568 +
  1.2569 +    if (cx->status == needBytes)
  1.2570 +	cx->status = keepGoing;
  1.2571 +
  1.2572 +    while (cx->status == keepGoing) {
  1.2573 +	state = cx->current;
  1.2574 +	what = SEC_ASN1_Contents;
  1.2575 +	consumed = 0;
  1.2576 +#ifdef DEBUG_ASN1D_STATES
  1.2577 +        printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
  1.2578 +               (state->place >= 0 && state->place <= notInUse) ?
  1.2579 +               place_names[ state->place ] : "(undefined)",
  1.2580 +               (unsigned int)((unsigned char *)buf)[ consumed ],
  1.2581 +               buf, consumed);
  1.2582 +        dump_states(cx);
  1.2583 +#endif /* DEBUG_ASN1D_STATES */
  1.2584 +	switch (state->place) {
  1.2585 +	  case beforeIdentifier:
  1.2586 +	    consumed = sec_asn1d_parse_identifier (state, buf, len);
  1.2587 +	    what = SEC_ASN1_Identifier;
  1.2588 +	    break;
  1.2589 +	  case duringIdentifier:
  1.2590 +	    consumed = sec_asn1d_parse_more_identifier (state, buf, len);
  1.2591 +	    what = SEC_ASN1_Identifier;
  1.2592 +	    break;
  1.2593 +	  case afterIdentifier:
  1.2594 +	    sec_asn1d_confirm_identifier (state);
  1.2595 +	    break;
  1.2596 +	  case beforeLength:
  1.2597 +	    consumed = sec_asn1d_parse_length (state, buf, len);
  1.2598 +	    what = SEC_ASN1_Length;
  1.2599 +	    break;
  1.2600 +	  case duringLength:
  1.2601 +	    consumed = sec_asn1d_parse_more_length (state, buf, len);
  1.2602 +	    what = SEC_ASN1_Length;
  1.2603 +	    break;
  1.2604 +	  case afterLength:
  1.2605 +	    sec_asn1d_prepare_for_contents (state);
  1.2606 +	    break;
  1.2607 +	  case beforeBitString:
  1.2608 +	    consumed = sec_asn1d_parse_bit_string (state, buf, len);
  1.2609 +	    break;
  1.2610 +	  case duringBitString:
  1.2611 +	    consumed = sec_asn1d_parse_more_bit_string (state, buf, len);
  1.2612 +	    break;
  1.2613 +	  case duringConstructedString:
  1.2614 +	    sec_asn1d_next_substring (state);
  1.2615 +	    break;
  1.2616 +	  case duringGroup:
  1.2617 +	    sec_asn1d_next_in_group (state);
  1.2618 +	    break;
  1.2619 +	  case duringLeaf:
  1.2620 +	    consumed = sec_asn1d_parse_leaf (state, buf, len);
  1.2621 +	    break;
  1.2622 +	  case duringSaveEncoding:
  1.2623 +	    sec_asn1d_reuse_encoding (state);
  1.2624 +	    if (cx->status == decodeError) {
  1.2625 +		/* recursive call has already popped all states from stack.
  1.2626 +		** Bail out quickly.
  1.2627 +		*/
  1.2628 +		return SECFailure;
  1.2629 +	    }
  1.2630 +	    if (cx->status == needBytes) {
  1.2631 +		/* recursive call wanted more data. Fatal. Clean up below. */
  1.2632 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.2633 +		cx->status = decodeError;
  1.2634 +	    }
  1.2635 +	    break;
  1.2636 +	  case duringSequence:
  1.2637 +	    sec_asn1d_next_in_sequence (state);
  1.2638 +	    break;
  1.2639 +	  case afterConstructedString:
  1.2640 +	    sec_asn1d_concat_substrings (state);
  1.2641 +	    break;
  1.2642 +	  case afterExplicit:
  1.2643 +	  case afterImplicit:
  1.2644 +	  case afterInline:
  1.2645 +	  case afterPointer:
  1.2646 +	    sec_asn1d_absorb_child (state);
  1.2647 +	    break;
  1.2648 +	  case afterGroup:
  1.2649 +	    sec_asn1d_concat_group (state);
  1.2650 +	    break;
  1.2651 +	  case afterSaveEncoding:
  1.2652 +	    /* SEC_ASN1DecoderUpdate has called itself recursively to 
  1.2653 +	    ** decode SAVEd encoded data, and now is done decoding that.
  1.2654 +	    ** Return to the calling copy of SEC_ASN1DecoderUpdate.
  1.2655 +	    */
  1.2656 +	    return SECSuccess;
  1.2657 +	  case beforeEndOfContents:
  1.2658 +	    sec_asn1d_prepare_for_end_of_contents (state);
  1.2659 +	    break;
  1.2660 +	  case duringEndOfContents:
  1.2661 +	    consumed = sec_asn1d_parse_end_of_contents (state, buf, len);
  1.2662 +	    what = SEC_ASN1_EndOfContents;
  1.2663 +	    break;
  1.2664 +	  case afterEndOfContents:
  1.2665 +	    sec_asn1d_pop_state (state);
  1.2666 +	    break;
  1.2667 +          case beforeChoice:
  1.2668 +            state = sec_asn1d_before_choice(state);
  1.2669 +            break;
  1.2670 +          case duringChoice:
  1.2671 +            state = sec_asn1d_during_choice(state);
  1.2672 +            break;
  1.2673 +          case afterChoice:
  1.2674 +            sec_asn1d_after_choice(state);
  1.2675 +            break;
  1.2676 +	  case notInUse:
  1.2677 +	  default:
  1.2678 +	    /* This is not an error, but rather a plain old BUG! */
  1.2679 +	    PORT_Assert (0);
  1.2680 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.2681 +	    cx->status = decodeError;
  1.2682 +	    break;
  1.2683 +	}
  1.2684 +
  1.2685 +	if (cx->status == decodeError)
  1.2686 +	    break;
  1.2687 +
  1.2688 +	/* We should not consume more than we have.  */
  1.2689 +	PORT_Assert (consumed <= len);
  1.2690 +	if (consumed > len) {
  1.2691 +	    PORT_SetError (SEC_ERROR_BAD_DER);
  1.2692 +	    cx->status = decodeError;
  1.2693 +	    break;
  1.2694 +	}
  1.2695 +
  1.2696 +	/* It might have changed, so we have to update our local copy.  */
  1.2697 +	state = cx->current;
  1.2698 +
  1.2699 +	/* If it is NULL, we have popped all the way to the top.  */
  1.2700 +	if (state == NULL) {
  1.2701 +	    PORT_Assert (consumed == 0);
  1.2702 +#if 0	/* XXX I want this here, but it seems that we have situations (like
  1.2703 +	 * downloading a pkcs7 cert chain from some issuers) that give us a
  1.2704 +	 * length which is greater than the entire encoding.  So, we cannot
  1.2705 +	 * have this be an error.
  1.2706 +	 */
  1.2707 +	    if (len > 0) {
  1.2708 +		PORT_SetError (SEC_ERROR_BAD_DER);
  1.2709 +		cx->status = decodeError;
  1.2710 +	    } else
  1.2711 +#endif
  1.2712 +		cx->status = allDone;
  1.2713 +	    break;
  1.2714 +	}
  1.2715 +	else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
  1.2716 +	    cx->status = allDone;
  1.2717 +	    break;
  1.2718 +	}
  1.2719 +	  
  1.2720 +	if (consumed == 0)
  1.2721 +	    continue;
  1.2722 +
  1.2723 +	/*
  1.2724 +	 * The following check is specifically looking for an ANY
  1.2725 +	 * that is *not* also an INNER, because we need to save aside
  1.2726 +	 * all bytes in that case -- the contents parts will get
  1.2727 +	 * handled like all other contents, and the end-of-contents
  1.2728 +	 * bytes are added by the concat code, but the outer header
  1.2729 +	 * bytes need to get saved too, so we do them explicitly here.
  1.2730 +	 */
  1.2731 +	if (state->underlying_kind == SEC_ASN1_ANY
  1.2732 +	    && !cx->filter_only && (what == SEC_ASN1_Identifier
  1.2733 +				    || what == SEC_ASN1_Length)) {
  1.2734 +	    sec_asn1d_record_any_header (state, buf, consumed);
  1.2735 +	}
  1.2736 +
  1.2737 +	/*
  1.2738 +	 * We had some number of good, accepted bytes.  If the caller
  1.2739 +	 * has registered to see them, pass them along.
  1.2740 +	 */
  1.2741 +	if (state->top->filter_proc != NULL) {
  1.2742 +	    int depth;
  1.2743 +
  1.2744 +	    depth = state->depth;
  1.2745 +	    if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
  1.2746 +		PORT_Assert (state->parent != NULL
  1.2747 +			     && state->parent->indefinite);
  1.2748 +		depth--;
  1.2749 +		PORT_Assert (depth == state->parent->depth);
  1.2750 +	    }
  1.2751 +	    (* state->top->filter_proc) (state->top->filter_arg,
  1.2752 +					 buf, consumed, depth, what);
  1.2753 +	}
  1.2754 +
  1.2755 +	state->consumed += consumed;
  1.2756 +	buf += consumed;
  1.2757 +	len -= consumed;
  1.2758 +    }
  1.2759 +
  1.2760 +    if (cx->status == decodeError) {
  1.2761 +	while (state != NULL && stateEnd->parent!=state) {
  1.2762 +	    sec_asn1d_free_child (state, PR_TRUE);
  1.2763 +	    state = state->parent;
  1.2764 +	}
  1.2765 +#ifdef SEC_ASN1D_FREE_ON_ERROR	/*
  1.2766 +				 * XXX This does not work because we can
  1.2767 +				 * end up leaving behind dangling pointers
  1.2768 +				 * to stuff that was allocated.  In order
  1.2769 +				 * to make this really work (which would
  1.2770 +				 * be a good thing, I think), we need to
  1.2771 +				 * keep track of every place/pointer that
  1.2772 +				 * was allocated and make sure to NULL it
  1.2773 +				 * out before we then free back to the mark.	
  1.2774 +				 */
  1.2775 +	if (cx->their_pool != NULL) {
  1.2776 +	    PORT_Assert (cx->their_mark != NULL);
  1.2777 +	    PORT_ArenaRelease (cx->their_pool, cx->their_mark);
  1.2778 +	    cx->their_mark = NULL;
  1.2779 +	}
  1.2780 +#endif
  1.2781 +	return SECFailure;
  1.2782 +    }
  1.2783 +
  1.2784 +#if 0	/* XXX This is what I want, but cannot have because it seems we
  1.2785 +	 * have situations (like when downloading a pkcs7 cert chain from
  1.2786 +	 * some issuers) that give us a total length which is greater than
  1.2787 +	 * the entire encoding.  So, we have to allow allDone to have a
  1.2788 +	 * remaining length greater than zero.  I wanted to catch internal
  1.2789 +	 * bugs with this, noticing when we do not have the right length.
  1.2790 +	 * Oh well.
  1.2791 +	 */
  1.2792 +    PORT_Assert (len == 0
  1.2793 +		 && (cx->status == needBytes || cx->status == allDone));
  1.2794 +#else
  1.2795 +    PORT_Assert ((len == 0 && cx->status == needBytes)
  1.2796 +		 || cx->status == allDone);
  1.2797 +#endif
  1.2798 +    return SECSuccess;
  1.2799 +}
  1.2800 +
  1.2801 +
  1.2802 +SECStatus
  1.2803 +SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx)
  1.2804 +{
  1.2805 +    SECStatus rv;
  1.2806 +
  1.2807 +    if (cx->status == needBytes) {
  1.2808 +	PORT_SetError (SEC_ERROR_BAD_DER);
  1.2809 +	rv = SECFailure;
  1.2810 +    } else {
  1.2811 +	rv = SECSuccess;
  1.2812 +    }
  1.2813 +
  1.2814 +    /*
  1.2815 +     * XXX anything else that needs to be finished?
  1.2816 +     */
  1.2817 +
  1.2818 +    PORT_FreeArena (cx->our_pool, PR_TRUE);
  1.2819 +
  1.2820 +    return rv;
  1.2821 +}
  1.2822 +
  1.2823 +
  1.2824 +SEC_ASN1DecoderContext *
  1.2825 +SEC_ASN1DecoderStart (PLArenaPool *their_pool, void *dest,
  1.2826 +		      const SEC_ASN1Template *theTemplate)
  1.2827 +{
  1.2828 +    PLArenaPool *our_pool;
  1.2829 +    SEC_ASN1DecoderContext *cx;
  1.2830 +
  1.2831 +    our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
  1.2832 +    if (our_pool == NULL)
  1.2833 +	return NULL;
  1.2834 +
  1.2835 +    cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx));
  1.2836 +    if (cx == NULL) {
  1.2837 +	PORT_FreeArena (our_pool, PR_FALSE);
  1.2838 +	return NULL;
  1.2839 +    }
  1.2840 +
  1.2841 +    cx->our_pool = our_pool;
  1.2842 +    if (their_pool != NULL) {
  1.2843 +	cx->their_pool = their_pool;
  1.2844 +#ifdef SEC_ASN1D_FREE_ON_ERROR
  1.2845 +	cx->their_mark = PORT_ArenaMark (their_pool);
  1.2846 +#endif
  1.2847 +    }
  1.2848 +
  1.2849 +    cx->status = needBytes;
  1.2850 +
  1.2851 +    if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL
  1.2852 +	|| sec_asn1d_init_state_based_on_template (cx->current) == NULL) {
  1.2853 +	/*
  1.2854 +	 * Trouble initializing (probably due to failed allocations)
  1.2855 +	 * requires that we just give up.
  1.2856 +	 */
  1.2857 +	PORT_FreeArena (our_pool, PR_FALSE);
  1.2858 +	return NULL;
  1.2859 +    }
  1.2860 +
  1.2861 +    return cx;
  1.2862 +}
  1.2863 +
  1.2864 +
  1.2865 +void
  1.2866 +SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx,
  1.2867 +			      SEC_ASN1WriteProc fn, void *arg,
  1.2868 +			      PRBool only)
  1.2869 +{
  1.2870 +    /* check that we are "between" fields here */
  1.2871 +    PORT_Assert (cx->during_notify);
  1.2872 +
  1.2873 +    cx->filter_proc = fn;
  1.2874 +    cx->filter_arg = arg;
  1.2875 +    cx->filter_only = only;
  1.2876 +}
  1.2877 +
  1.2878 +
  1.2879 +void
  1.2880 +SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx)
  1.2881 +{
  1.2882 +    /* check that we are "between" fields here */
  1.2883 +    PORT_Assert (cx->during_notify);
  1.2884 +
  1.2885 +    cx->filter_proc = NULL;
  1.2886 +    cx->filter_arg = NULL;
  1.2887 +    cx->filter_only = PR_FALSE;
  1.2888 +}
  1.2889 +
  1.2890 +
  1.2891 +void
  1.2892 +SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx,
  1.2893 +			      SEC_ASN1NotifyProc fn, void *arg)
  1.2894 +{
  1.2895 +    cx->notify_proc = fn;
  1.2896 +    cx->notify_arg = arg;
  1.2897 +}
  1.2898 +
  1.2899 +
  1.2900 +void
  1.2901 +SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx)
  1.2902 +{
  1.2903 +    cx->notify_proc = NULL;
  1.2904 +    cx->notify_arg = NULL;	/* not necessary; just being clean */
  1.2905 +}
  1.2906 +
  1.2907 +void
  1.2908 +SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
  1.2909 +{
  1.2910 +    PORT_Assert(cx);
  1.2911 +    PORT_SetError(error);
  1.2912 +    cx->status = decodeError;
  1.2913 +}
  1.2914 +
  1.2915 +
  1.2916 +SECStatus
  1.2917 +SEC_ASN1Decode (PLArenaPool *poolp, void *dest,
  1.2918 +		const SEC_ASN1Template *theTemplate,
  1.2919 +		const char *buf, long len)
  1.2920 +{
  1.2921 +    SEC_ASN1DecoderContext *dcx;
  1.2922 +    SECStatus urv, frv;
  1.2923 +
  1.2924 +    dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate);
  1.2925 +    if (dcx == NULL)
  1.2926 +	return SECFailure;
  1.2927 +
  1.2928 +    urv = SEC_ASN1DecoderUpdate (dcx, buf, len);
  1.2929 +    frv = SEC_ASN1DecoderFinish (dcx);
  1.2930 +
  1.2931 +    if (urv != SECSuccess)
  1.2932 +	return urv;
  1.2933 +
  1.2934 +    return frv;
  1.2935 +}
  1.2936 +
  1.2937 +
  1.2938 +SECStatus
  1.2939 +SEC_ASN1DecodeItem (PLArenaPool *poolp, void *dest,
  1.2940 +		    const SEC_ASN1Template *theTemplate,
  1.2941 +		    const SECItem *src)
  1.2942 +{
  1.2943 +    return SEC_ASN1Decode (poolp, dest, theTemplate,
  1.2944 +			   (const char *)src->data, src->len);
  1.2945 +}
  1.2946 +
  1.2947 +#ifdef DEBUG_ASN1D_STATES
  1.2948 +void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
  1.2949 +{
  1.2950 +    printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
  1.2951 +    fflush(stdout);
  1.2952 +}
  1.2953 +#endif
  1.2954 +
  1.2955 +/*
  1.2956 + * Generic templates for individual/simple items and pointers to
  1.2957 + * and sets of same.
  1.2958 + *
  1.2959 + * If you need to add a new one, please note the following:
  1.2960 + *	 - For each new basic type you should add *four* templates:
  1.2961 + *	one plain, one PointerTo, one SequenceOf and one SetOf.
  1.2962 + *	 - If the new type can be constructed (meaning, it is a
  1.2963 + *	*string* type according to BER/DER rules), then you should
  1.2964 + *	or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
  1.2965 + *	See the definition of the OctetString template for an example.
  1.2966 + *	 - It may not be obvious, but these are in *alphabetical*
  1.2967 + *	order based on the SEC_ASN1_XXX name; so put new ones in
  1.2968 + *	the appropriate place.
  1.2969 + */
  1.2970 +
  1.2971 +const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
  1.2972 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
  1.2973 +};
  1.2974 +
  1.2975 +#if 0
  1.2976 +
  1.2977 +const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = {
  1.2978 +    { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate }
  1.2979 +};
  1.2980 +
  1.2981 +const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = {
  1.2982 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate }
  1.2983 +};
  1.2984 +
  1.2985 +const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = {
  1.2986 +    { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate }
  1.2987 +};
  1.2988 +
  1.2989 +const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = {
  1.2990 +    { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate }
  1.2991 +};
  1.2992 +
  1.2993 +const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = {
  1.2994 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate }
  1.2995 +};
  1.2996 +
  1.2997 +const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = {
  1.2998 +    { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate }
  1.2999 +};
  1.3000 +
  1.3001 +const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = {
  1.3002 +    { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate }
  1.3003 +};
  1.3004 +
  1.3005 +const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = {
  1.3006 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate }
  1.3007 +};
  1.3008 +
  1.3009 +const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = {
  1.3010 +    { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate }
  1.3011 +};
  1.3012 +
  1.3013 +#endif
  1.3014 +
  1.3015 +const SEC_ASN1Template SEC_EnumeratedTemplate[] = {
  1.3016 +    { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
  1.3017 +};
  1.3018 +
  1.3019 +const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = {
  1.3020 +    { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate }
  1.3021 +};
  1.3022 +
  1.3023 +#if 0
  1.3024 +
  1.3025 +const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = {
  1.3026 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate }
  1.3027 +};
  1.3028 +
  1.3029 +#endif
  1.3030 +
  1.3031 +const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = {
  1.3032 +    { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate }
  1.3033 +};
  1.3034 +
  1.3035 +const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = {
  1.3036 +    { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate }
  1.3037 +};
  1.3038 +
  1.3039 +#if 0
  1.3040 +
  1.3041 +const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = {
  1.3042 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate }
  1.3043 +};
  1.3044 +
  1.3045 +const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = {
  1.3046 +    { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate }
  1.3047 +};
  1.3048 +
  1.3049 +const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = {
  1.3050 +    { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate }
  1.3051 +};
  1.3052 +
  1.3053 +const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = {
  1.3054 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate }
  1.3055 +};
  1.3056 +
  1.3057 +const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = {
  1.3058 +    { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate }
  1.3059 +};
  1.3060 +
  1.3061 +const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = {
  1.3062 +    { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate }
  1.3063 +};
  1.3064 +
  1.3065 +const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = {
  1.3066 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate }
  1.3067 +};
  1.3068 +
  1.3069 +const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = {
  1.3070 +    { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate }
  1.3071 +};
  1.3072 +
  1.3073 +const SEC_ASN1Template SEC_PointerToNullTemplate[] = {
  1.3074 +    { SEC_ASN1_POINTER, 0, SEC_NullTemplate }
  1.3075 +};
  1.3076 +
  1.3077 +const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = {
  1.3078 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate }
  1.3079 +};
  1.3080 +
  1.3081 +const SEC_ASN1Template SEC_SetOfNullTemplate[] = {
  1.3082 +    { SEC_ASN1_SET_OF, 0, SEC_NullTemplate }
  1.3083 +};
  1.3084 +
  1.3085 +const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = {
  1.3086 +    { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate }
  1.3087 +};
  1.3088 +
  1.3089 +#endif
  1.3090 +
  1.3091 +const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = {
  1.3092 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate }
  1.3093 +};
  1.3094 +
  1.3095 +#if 0
  1.3096 +
  1.3097 +const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = {
  1.3098 +    { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate }
  1.3099 +};
  1.3100 +
  1.3101 +const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = {
  1.3102 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate }
  1.3103 +};
  1.3104 +
  1.3105 +const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
  1.3106 +    { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate }
  1.3107 +};
  1.3108 +
  1.3109 +#endif
  1.3110 +
  1.3111 +const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
  1.3112 +    { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
  1.3113 +};
  1.3114 +
  1.3115 +#if 0
  1.3116 +
  1.3117 +const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = {
  1.3118 +    { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate }
  1.3119 +};
  1.3120 +
  1.3121 +const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = {
  1.3122 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate }
  1.3123 +};
  1.3124 +
  1.3125 +const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = {
  1.3126 +    { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate }
  1.3127 +};
  1.3128 +
  1.3129 +#endif
  1.3130 +
  1.3131 +const SEC_ASN1Template SEC_T61StringTemplate[] = {
  1.3132 +    { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
  1.3133 +};
  1.3134 +
  1.3135 +#if 0
  1.3136 +
  1.3137 +const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = {
  1.3138 +    { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate }
  1.3139 +};
  1.3140 +
  1.3141 +const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = {
  1.3142 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate }
  1.3143 +};
  1.3144 +
  1.3145 +const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
  1.3146 +    { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate }
  1.3147 +};
  1.3148 +
  1.3149 +#endif
  1.3150 +
  1.3151 +const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
  1.3152 +    { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
  1.3153 +};
  1.3154 +
  1.3155 +#if 0
  1.3156 +
  1.3157 +const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = {
  1.3158 +    { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate }
  1.3159 +};
  1.3160 +
  1.3161 +const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = {
  1.3162 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate }
  1.3163 +};
  1.3164 +
  1.3165 +const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = {
  1.3166 +    { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate }
  1.3167 +};
  1.3168 +
  1.3169 +const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = {
  1.3170 +    { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate }
  1.3171 +};
  1.3172 +
  1.3173 +const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = {
  1.3174 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate }
  1.3175 +};
  1.3176 +
  1.3177 +const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = {
  1.3178 +    { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate }
  1.3179 +};
  1.3180 +
  1.3181 +const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = {
  1.3182 +    { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate }
  1.3183 +};
  1.3184 +
  1.3185 +const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = {
  1.3186 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate }
  1.3187 +};
  1.3188 +
  1.3189 +const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = {
  1.3190 +    { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate }
  1.3191 +};
  1.3192 +
  1.3193 +#endif
  1.3194 +
  1.3195 +const SEC_ASN1Template SEC_VisibleStringTemplate[] = {
  1.3196 +    { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
  1.3197 +};
  1.3198 +
  1.3199 +#if 0
  1.3200 +
  1.3201 +const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = {
  1.3202 +    { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate }
  1.3203 +};
  1.3204 +
  1.3205 +const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = {
  1.3206 +    { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate }
  1.3207 +};
  1.3208 +
  1.3209 +const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = {
  1.3210 +    { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate }
  1.3211 +};
  1.3212 +
  1.3213 +#endif
  1.3214 +
  1.3215 +/*
  1.3216 + * Template for skipping a subitem.
  1.3217 + *
  1.3218 + * Note that it only makes sense to use this for decoding (when you want
  1.3219 + * to decode something where you are only interested in one or two of
  1.3220 + * the fields); you cannot encode a SKIP!
  1.3221 + */
  1.3222 +const SEC_ASN1Template SEC_SkipTemplate[] = {
  1.3223 +    { SEC_ASN1_SKIP }
  1.3224 +};
  1.3225 +
  1.3226 +
  1.3227 +/* These functions simply return the address of the above-declared templates.
  1.3228 +** This is necessary for Windows DLLs.  Sigh.
  1.3229 +*/
  1.3230 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_EnumeratedTemplate)
  1.3231 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToEnumeratedTemplate)
  1.3232 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfAnyTemplate)
  1.3233 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SequenceOfObjectIDTemplate)
  1.3234 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SkipTemplate)
  1.3235 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UniversalStringTemplate)
  1.3236 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PrintableStringTemplate)
  1.3237 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_T61StringTemplate)
  1.3238 +SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToGeneralizedTimeTemplate)
  1.3239 +

mercurial