Back to index

lightning-sunbird  0.9+nobinonly
secasn1d.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /*
00038  * Support for DEcoding ASN.1 data based on BER/DER (Basic/Distinguished
00039  * Encoding Rules).
00040  *
00041  * $Id: secasn1d.c,v 1.33.28.3 2006/08/16 00:08:19 wtchang%redhat.com Exp $
00042  */
00043 
00044 /* #define DEBUG_ASN1D_STATES 1 */
00045 
00046 #ifdef DEBUG_ASN1D_STATES
00047 #include <stdio.h>
00048 #define PR_Assert sec_asn1d_Assert
00049 #endif
00050 
00051 #include "secasn1.h"
00052 #include "secerr.h"
00053 
00054 typedef enum {
00055     beforeIdentifier,
00056     duringIdentifier,
00057     afterIdentifier,
00058     beforeLength,
00059     duringLength,
00060     afterLength,
00061     beforeBitString,
00062     duringBitString,
00063     duringConstructedString,
00064     duringGroup,
00065     duringLeaf,
00066     duringSaveEncoding,
00067     duringSequence,
00068     afterConstructedString,
00069     afterGroup,
00070     afterExplicit,
00071     afterImplicit,
00072     afterInline,
00073     afterPointer,
00074     afterSaveEncoding,
00075     beforeEndOfContents,
00076     duringEndOfContents,
00077     afterEndOfContents,
00078     beforeChoice,
00079     duringChoice,
00080     afterChoice,
00081     notInUse
00082 } sec_asn1d_parse_place;
00083 
00084 #ifdef DEBUG_ASN1D_STATES
00085 static const char * const place_names[] = {
00086     "beforeIdentifier",
00087     "duringIdentifier",
00088     "afterIdentifier",
00089     "beforeLength",
00090     "duringLength",
00091     "afterLength",
00092     "beforeBitString",
00093     "duringBitString",
00094     "duringConstructedString",
00095     "duringGroup",
00096     "duringLeaf",
00097     "duringSaveEncoding",
00098     "duringSequence",
00099     "afterConstructedString",
00100     "afterGroup",
00101     "afterExplicit",
00102     "afterImplicit",
00103     "afterInline",
00104     "afterPointer",
00105     "afterSaveEncoding",
00106     "beforeEndOfContents",
00107     "duringEndOfContents",
00108     "afterEndOfContents",
00109     "beforeChoice",
00110     "duringChoice",
00111     "afterChoice",
00112     "notInUse"
00113 };
00114 
00115 static const char * const class_names[] = {
00116     "UNIVERSAL",
00117     "APPLICATION",
00118     "CONTEXT_SPECIFIC",
00119     "PRIVATE"
00120 };
00121 
00122 static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
00123 
00124 static const char * const type_names[] = {
00125     "END_OF_CONTENTS",
00126     "BOOLEAN",
00127     "INTEGER",
00128     "BIT_STRING",
00129     "OCTET_STRING",
00130     "NULL",
00131     "OBJECT_ID",
00132     "OBJECT_DESCRIPTOR",
00133     "(type 08)",
00134     "REAL",
00135     "ENUMERATED",
00136     "EMBEDDED",
00137     "UTF8_STRING",
00138     "(type 0d)",
00139     "(type 0e)",
00140     "(type 0f)",
00141     "SEQUENCE",
00142     "SET",
00143     "NUMERIC_STRING",
00144     "PRINTABLE_STRING",
00145     "T61_STRING",
00146     "VIDEOTEXT_STRING",
00147     "IA5_STRING",
00148     "UTC_TIME",
00149     "GENERALIZED_TIME",
00150     "GRAPHIC_STRING",
00151     "VISIBLE_STRING",
00152     "GENERAL_STRING",
00153     "UNIVERSAL_STRING",
00154     "(type 1d)",
00155     "BMP_STRING",
00156     "HIGH_TAG_VALUE"
00157 };
00158 
00159 static const char * const flag_names[] = { /* flags, right to left */
00160     "OPTIONAL",
00161     "EXPLICIT",
00162     "ANY",
00163     "INLINE",
00164     "POINTER",
00165     "GROUP",
00166     "DYNAMIC",
00167     "SKIP",
00168     "INNER",
00169     "SAVE",
00170     "",            /* decoder ignores "MAY_STREAM", */
00171     "SKIP_REST",
00172     "CHOICE",
00173     "NO_STREAM",
00174     "DEBUG_BREAK",
00175     "unknown 08",
00176     "unknown 10",
00177     "unknown 20",
00178     "unknown 40",
00179     "unknown 80"
00180 };
00181 
00182 static int /* bool */
00183 formatKind(unsigned long kind, char * buf)
00184 {
00185     int i;
00186     unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
00187     unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
00188         SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
00189 
00190     buf[0] = 0;
00191     if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
00192         sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] );
00193         buf += strlen(buf);
00194     }
00195     if (kind & SEC_ASN1_METHOD_MASK) {
00196         sprintf(buf, " %s", method_names[1]);
00197         buf += strlen(buf);
00198     }
00199     if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
00200         if (k || !notag) {
00201             sprintf(buf, " %s", type_names[k] );
00202             if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
00203                 (kind & SEC_ASN1_GROUP)) {
00204                 buf += strlen(buf);
00205                 sprintf(buf, "_OF");
00206             }
00207         }
00208     } else {
00209         sprintf(buf, " [%d]", k);
00210     }
00211     buf += strlen(buf);
00212 
00213     for (k = kind >> 8, i = 0; k; k >>= 1, ++i) {
00214         if (k & 1) {
00215             sprintf(buf, " %s", flag_names[i]);
00216             buf += strlen(buf);
00217         }
00218     }
00219     return notag != 0;
00220 }
00221 
00222 #endif /* DEBUG_ASN1D_STATES */
00223 
00224 typedef enum {
00225     allDone,
00226     decodeError,
00227     keepGoing,
00228     needBytes
00229 } sec_asn1d_parse_status;
00230 
00231 struct subitem {
00232     const void *data;
00233     unsigned long len;             /* only used for substrings */
00234     struct subitem *next;
00235 };
00236 
00237 typedef struct sec_asn1d_state_struct {
00238     SEC_ASN1DecoderContext *top;
00239     const SEC_ASN1Template *theTemplate;
00240     void *dest;
00241 
00242     void *our_mark;  /* free on completion */
00243 
00244     struct sec_asn1d_state_struct *parent;       /* aka prev */
00245     struct sec_asn1d_state_struct *child; /* aka next */
00246 
00247     sec_asn1d_parse_place place;
00248 
00249     /*
00250      * XXX explain the next fields as clearly as possible...
00251      */
00252     unsigned char found_tag_modifiers;
00253     unsigned char expect_tag_modifiers;
00254     unsigned long check_tag_mask;
00255     unsigned long found_tag_number;
00256     unsigned long expect_tag_number;
00257     unsigned long underlying_kind;
00258 
00259     unsigned long contents_length;
00260     unsigned long pending;
00261     unsigned long consumed;
00262 
00263     int depth;
00264 
00265     /*
00266      * Bit strings have their length adjusted -- the first octet of the
00267      * contents contains a value between 0 and 7 which says how many bits
00268      * at the end of the octets are not actually part of the bit string;
00269      * when parsing bit strings we put that value here because we need it
00270      * later, for adjustment of the length (when the whole string is done).
00271      */
00272     unsigned int bit_string_unused_bits;
00273 
00274     /*
00275      * The following are used for indefinite-length constructed strings.
00276      */
00277     struct subitem *subitems_head;
00278     struct subitem *subitems_tail;
00279 
00280     PRPackedBool
00281        allocate,     /* when true, need to allocate the destination */
00282        endofcontents,       /* this state ended up parsing end-of-contents octets */
00283        explicit,     /* we are handling an explicit header */
00284        indefinite,   /* the current item has indefinite-length encoding */
00285        missing,      /* an optional field that was not present */
00286        optional,     /* the template says this field may be omitted */
00287        substring;    /* this is a substring of a constructed string */
00288 
00289 } sec_asn1d_state;
00290 
00291 #define IS_HIGH_TAG_NUMBER(n)      ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
00292 #define LAST_TAG_NUMBER_BYTE(b)    (((b) & 0x80) == 0)
00293 #define TAG_NUMBER_BITS            7
00294 #define TAG_NUMBER_MASK            0x7f
00295 
00296 #define LENGTH_IS_SHORT_FORM(b)    (((b) & 0x80) == 0)
00297 #define LONG_FORM_LENGTH(b) ((b) & 0x7f)
00298 
00299 #define HIGH_BITS(field,cnt)       ((field) >> ((sizeof(field) * 8) - (cnt)))
00300 
00301 
00302 /*
00303  * An "outsider" will have an opaque pointer to this, created by calling
00304  * SEC_ASN1DecoderStart().  It will be passed back in to all subsequent
00305  * calls to SEC_ASN1DecoderUpdate(), and when done it is passed to
00306  * SEC_ASN1DecoderFinish().
00307  */
00308 struct sec_DecoderContext_struct {
00309     PRArenaPool *our_pool;         /* for our internal allocs */
00310     PRArenaPool *their_pool;              /* for destination structure allocs */
00311 #ifdef SEC_ASN1D_FREE_ON_ERROR            /*
00312                                     * XXX see comment below (by same
00313                                     * ifdef) that explains why this
00314                                     * does not work (need more smarts
00315                                     * in order to free back to mark)
00316                                     */
00317     /*
00318      * XXX how to make their_mark work in the case where they do NOT
00319      * give us a pool pointer?
00320      */
00321     void *their_mark;                     /* free on error */
00322 #endif
00323 
00324     sec_asn1d_state *current;
00325     sec_asn1d_parse_status status;
00326 
00327     SEC_ASN1NotifyProc notify_proc;       /* call before/after handling field */
00328     void *notify_arg;                     /* argument to notify_proc */
00329     PRBool during_notify;          /* true during call to notify_proc */
00330 
00331     SEC_ASN1WriteProc filter_proc; /* pass field bytes to this  */
00332     void *filter_arg;                     /* argument to that function */
00333     PRBool filter_only;                   /* do not allocate/store fields */
00334 };
00335 
00336 
00337 /*
00338  * XXX this is a fairly generic function that may belong elsewhere
00339  */
00340 static void *
00341 sec_asn1d_alloc (PRArenaPool *poolp, unsigned long len)
00342 {
00343     void *thing;
00344 
00345     if (poolp != NULL) {
00346        /*
00347         * Allocate from the pool.
00348         */
00349        thing = PORT_ArenaAlloc (poolp, len);
00350     } else {
00351        /*
00352         * Allocate generically.
00353         */
00354        thing = PORT_Alloc (len);
00355     }
00356 
00357     return thing;
00358 }
00359 
00360 
00361 /*
00362  * XXX this is a fairly generic function that may belong elsewhere
00363  */
00364 static void *
00365 sec_asn1d_zalloc (PRArenaPool *poolp, unsigned long len)
00366 {
00367     void *thing;
00368 
00369     thing = sec_asn1d_alloc (poolp, len);
00370     if (thing != NULL)
00371        PORT_Memset (thing, 0, len);
00372     return thing;
00373 }
00374 
00375 
00376 static sec_asn1d_state *
00377 sec_asn1d_push_state (SEC_ASN1DecoderContext *cx,
00378                     const SEC_ASN1Template *theTemplate,
00379                     void *dest, PRBool new_depth)
00380 {
00381     sec_asn1d_state *state, *new_state;
00382 
00383     state = cx->current;
00384 
00385     PORT_Assert (state == NULL || state->child == NULL);
00386 
00387     if (state != NULL) {
00388        PORT_Assert (state->our_mark == NULL);
00389        state->our_mark = PORT_ArenaMark (cx->our_pool);
00390     }
00391 
00392     new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool, 
00393                                               sizeof(*new_state));
00394     if (new_state == NULL) {
00395        goto loser;
00396     }
00397 
00398     new_state->top         = cx;
00399     new_state->parent      = state;
00400     new_state->theTemplate = theTemplate;
00401     new_state->place       = notInUse;
00402     if (dest != NULL)
00403        new_state->dest = (char *)dest + theTemplate->offset;
00404 
00405     if (state != NULL) {
00406        new_state->depth = state->depth;
00407        if (new_depth) {
00408            if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
00409               PORT_SetError (SEC_ERROR_BAD_DER);
00410               goto loser;
00411            }
00412        }
00413        state->child = new_state;
00414     }
00415 
00416     cx->current = new_state;
00417     return new_state;
00418 
00419 loser:
00420     cx->status = decodeError;
00421     if (state != NULL) {
00422        PORT_ArenaRelease(cx->our_pool, state->our_mark);
00423        state->our_mark = NULL;
00424     }
00425     return NULL;
00426 }
00427 
00428 
00429 static void
00430 sec_asn1d_scrub_state (sec_asn1d_state *state)
00431 {
00432     /*
00433      * Some default "scrubbing".
00434      * XXX right set of initializations?
00435      */
00436     state->place = beforeIdentifier;
00437     state->endofcontents = PR_FALSE;
00438     state->indefinite = PR_FALSE;
00439     state->missing = PR_FALSE;
00440     PORT_Assert (state->consumed == 0);
00441 }
00442 
00443 
00444 static void
00445 sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth)
00446 {
00447     if (cx->notify_proc == NULL)
00448        return;
00449 
00450     cx->during_notify = PR_TRUE;
00451     (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth);
00452     cx->during_notify = PR_FALSE;
00453 }
00454 
00455 
00456 static void
00457 sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth)
00458 {
00459     if (cx->notify_proc == NULL)
00460        return;
00461 
00462     cx->during_notify = PR_TRUE;
00463     (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth);
00464     cx->during_notify = PR_FALSE;
00465 }
00466 
00467 
00468 static sec_asn1d_state *
00469 sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
00470 {
00471     PRBool explicit, optional, universal;
00472     unsigned char expect_tag_modifiers;
00473     unsigned long encode_kind, under_kind;
00474     unsigned long check_tag_mask, expect_tag_number;
00475 
00476 
00477     /* XXX Check that both of these tests are really needed/appropriate. */
00478     if (state == NULL || state->top->status == decodeError)
00479        return state;
00480 
00481     encode_kind = state->theTemplate->kind;
00482 
00483     if (encode_kind & SEC_ASN1_SAVE) {
00484        /*
00485         * This is a "magic" field that saves away all bytes, allowing
00486         * the immediately following field to still be decoded from this
00487         * same spot -- sort of a fork.
00488         */
00489        /* check that there are no extraneous bits */
00490        PORT_Assert (encode_kind == SEC_ASN1_SAVE);
00491        if (state->top->filter_only) {
00492            /*
00493             * If we are not storing, then we do not do the SAVE field
00494             * at all.  Just move ahead to the "real" field instead,
00495             * doing the appropriate notify calls before and after.
00496             */
00497            sec_asn1d_notify_after (state->top, state->dest, state->depth);
00498            /*
00499             * Since we are not storing, allow for our current dest value
00500             * to be NULL.  (This might not actually occur, but right now I
00501             * cannot convince myself one way or the other.)  If it is NULL,
00502             * assume that our parent dest can help us out.
00503             */
00504            if (state->dest == NULL)
00505               state->dest = state->parent->dest;
00506            else
00507               state->dest = (char *)state->dest - state->theTemplate->offset;
00508            state->theTemplate++;
00509            if (state->dest != NULL)
00510               state->dest = (char *)state->dest + state->theTemplate->offset;
00511            sec_asn1d_notify_before (state->top, state->dest, state->depth);
00512            encode_kind = state->theTemplate->kind;
00513            PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0);
00514        } else {
00515            sec_asn1d_scrub_state (state);
00516            state->place = duringSaveEncoding;
00517            state = sec_asn1d_push_state (state->top, SEC_AnyTemplate,
00518                                      state->dest, PR_FALSE);
00519            if (state != NULL)
00520               state = sec_asn1d_init_state_based_on_template (state);
00521            return state;
00522        }
00523     }
00524 
00525 
00526     universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
00527               ? PR_TRUE : PR_FALSE;
00528 
00529     explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
00530     encode_kind &= ~SEC_ASN1_EXPLICIT;
00531 
00532     optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
00533     encode_kind &= ~SEC_ASN1_OPTIONAL;
00534 
00535     PORT_Assert (!(explicit && universal));      /* bad templates */
00536 
00537     encode_kind &= ~SEC_ASN1_DYNAMIC;
00538     encode_kind &= ~SEC_ASN1_MAY_STREAM;
00539 
00540     if (encode_kind & SEC_ASN1_CHOICE) {
00541 #if 0  /* XXX remove? */
00542       sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
00543       if ((sec_asn1d_state *)NULL == child) {
00544         return (sec_asn1d_state *)NULL;
00545       }
00546 
00547       child->allocate = state->allocate;
00548       child->place = beforeChoice;
00549       return child;
00550 #else
00551       state->place = beforeChoice;
00552       return state;
00553 #endif
00554     }
00555 
00556     if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal
00557                                                        && !explicit)) {
00558        const SEC_ASN1Template *subt;
00559        void *dest;
00560        PRBool child_allocate;
00561 
00562        PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
00563 
00564        sec_asn1d_scrub_state (state);
00565        child_allocate = PR_FALSE;
00566 
00567        if (encode_kind & SEC_ASN1_POINTER) {
00568            /*
00569             * A POINTER means we need to allocate the destination for
00570             * this field.  But, since it may also be an optional field,
00571             * we defer the allocation until later; we just record that
00572             * it needs to be done.
00573             *
00574             * There are two possible scenarios here -- one is just a
00575             * plain POINTER (kind of like INLINE, except with allocation)
00576             * and the other is an implicitly-tagged POINTER.  We don't
00577             * need to do anything special here for the two cases, but
00578             * since the template definition can be tricky, we do check
00579             * that there are no extraneous bits set in encode_kind.
00580             *
00581             * XXX The same conditions which assert should set an error.
00582             */
00583            if (universal) {
00584               /*
00585                * "universal" means this entry is a standalone POINTER;
00586                * there should be no other bits set in encode_kind.
00587                */
00588               PORT_Assert (encode_kind == SEC_ASN1_POINTER);
00589            } else {
00590               /*
00591                * If we get here we have an implicitly-tagged field
00592                * that needs to be put into a POINTER.  The subtemplate
00593                * will determine how to decode the field, but encode_kind
00594                * describes the (implicit) tag we are looking for.
00595                * The non-tag bits of encode_kind will be ignored by
00596                * the code below; none of them should be set, however,
00597                * except for the POINTER bit itself -- so check that.
00598                */
00599               PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK)
00600                           == SEC_ASN1_POINTER);
00601            }
00602            if (!state->top->filter_only)
00603               child_allocate = PR_TRUE;
00604            dest = NULL;
00605            state->place = afterPointer;
00606        } else {
00607            dest = state->dest;
00608            if (encode_kind & SEC_ASN1_INLINE) {
00609               /* check that there are no extraneous bits */
00610               PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional);
00611               state->place = afterInline;
00612            } else {
00613               state->place = afterImplicit;
00614            }
00615        }
00616 
00617        state->optional = optional;
00618        subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, PR_FALSE);
00619        state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE);
00620        if (state == NULL)
00621            return NULL;
00622 
00623        state->allocate = child_allocate;
00624 
00625        if (universal) {
00626            state = sec_asn1d_init_state_based_on_template (state);
00627            if (state != NULL) {
00628               /*
00629                * If this field is optional, we need to record that on
00630                * the pushed child so it won't fail if the field isn't
00631                * found.  I can't think of a way that this new state
00632                * could already have optional set (which we would wipe
00633                * out below if our local optional is not set) -- but
00634                * just to be sure, assert that it isn't set.
00635                */
00636               PORT_Assert (!state->optional);
00637               state->optional = optional;
00638            }
00639            return state;
00640        }
00641 
00642        under_kind = state->theTemplate->kind;
00643        under_kind &= ~SEC_ASN1_MAY_STREAM;
00644     } else if (explicit) {
00645        /*
00646         * For explicit, we only need to match the encoding tag next,
00647         * then we will push another state to handle the entire inner
00648         * part.  In this case, there is no underlying kind which plays
00649         * any part in the determination of the outer, explicit tag.
00650         * So we just set under_kind to 0, which is not a valid tag,
00651         * and the rest of the tag matching stuff should be okay.
00652         */
00653        under_kind = 0;
00654     } else {
00655        /*
00656         * Nothing special; the underlying kind and the given encoding
00657         * information are the same.
00658         */
00659        under_kind = encode_kind;
00660     }
00661 
00662     /* XXX is this the right set of bits to test here? */
00663     PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL
00664                             | SEC_ASN1_MAY_STREAM
00665                             | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
00666 
00667     if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
00668        PORT_Assert (encode_kind == under_kind);
00669        if (encode_kind & SEC_ASN1_SKIP) {
00670            PORT_Assert (!optional);
00671            PORT_Assert (encode_kind == SEC_ASN1_SKIP);
00672            state->dest = NULL;
00673        }
00674        check_tag_mask = 0;
00675        expect_tag_modifiers = 0;
00676        expect_tag_number = 0;
00677     } else {
00678        check_tag_mask = SEC_ASN1_TAG_MASK;
00679        expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK
00680                             & ~SEC_ASN1_TAGNUM_MASK;
00681        /*
00682         * XXX This assumes only single-octet identifiers.  To handle
00683         * the HIGH TAG form we would need to do some more work, especially
00684         * in how to specify them in the template, because right now we
00685         * do not provide a way to specify more *tag* bits in encode_kind.
00686         */
00687        expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
00688 
00689        switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
00690          case SEC_ASN1_SET:
00691            /*
00692             * XXX A plain old SET (as opposed to a SET OF) is not implemented.
00693             * If it ever is, remove this assert...
00694             */
00695            PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0);
00696            /* fallthru */
00697          case SEC_ASN1_SEQUENCE:
00698            expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
00699            break;
00700          case SEC_ASN1_BIT_STRING:
00701          case SEC_ASN1_BMP_STRING:
00702          case SEC_ASN1_GENERALIZED_TIME:
00703          case SEC_ASN1_IA5_STRING:
00704          case SEC_ASN1_OCTET_STRING:
00705          case SEC_ASN1_PRINTABLE_STRING:
00706          case SEC_ASN1_T61_STRING:
00707          case SEC_ASN1_UNIVERSAL_STRING:
00708          case SEC_ASN1_UTC_TIME:
00709          case SEC_ASN1_UTF8_STRING:
00710          case SEC_ASN1_VISIBLE_STRING:
00711            check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
00712            break;
00713        }
00714     }
00715 
00716     state->check_tag_mask = check_tag_mask;
00717     state->expect_tag_modifiers = expect_tag_modifiers;
00718     state->expect_tag_number = expect_tag_number;
00719     state->underlying_kind = under_kind;
00720     state->explicit = explicit;
00721     state->optional = optional;
00722 
00723     sec_asn1d_scrub_state (state);
00724 
00725     return state;
00726 }
00727 
00728 static sec_asn1d_state *
00729 sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
00730 {
00731     for (state = state->parent; state; state = state->parent) {
00732        sec_asn1d_parse_place place = state->place;
00733        if (place != afterImplicit      &&
00734            place != afterPointer       &&
00735            place != afterInline        &&
00736            place != afterSaveEncoding  &&
00737            place != duringSaveEncoding &&
00738            place != duringChoice) {
00739 
00740             /* we've walked up the stack to a state that represents
00741             ** the enclosing construct.  
00742            */
00743             break;
00744        }
00745     }
00746     return state;
00747 }
00748 
00749 static PRBool
00750 sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
00751 {
00752     /* get state of enclosing construct. */
00753     state = sec_asn1d_get_enclosing_construct(state);
00754     if (state) {
00755        sec_asn1d_parse_place place = state->place;
00756         /* Is it one of the types that permits an unexpected EOC? */
00757        int eoc_permitted = 
00758            (place == duringGroup ||
00759             place == duringConstructedString ||
00760             state->child->optional);
00761        return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
00762     }
00763     return PR_FALSE;
00764 }
00765 
00766 static unsigned long
00767 sec_asn1d_parse_identifier (sec_asn1d_state *state,
00768                          const char *buf, unsigned long len)
00769 {
00770     unsigned char byte;
00771     unsigned char tag_number;
00772 
00773     PORT_Assert (state->place == beforeIdentifier);
00774 
00775     if (len == 0) {
00776        state->top->status = needBytes;
00777        return 0;
00778     }
00779 
00780     byte = (unsigned char) *buf;
00781 #ifdef DEBUG_ASN1D_STATES
00782     {
00783         char kindBuf[256];
00784         formatKind(byte, kindBuf);
00785         printf("Found tag %02x %s\n", byte, kindBuf);
00786     }
00787 #endif
00788     tag_number = byte & SEC_ASN1_TAGNUM_MASK;
00789 
00790     if (IS_HIGH_TAG_NUMBER (tag_number)) {
00791        state->place = duringIdentifier;
00792        state->found_tag_number = 0;
00793        /*
00794         * Actually, we have no idea how many bytes are pending, but we
00795         * do know that it is at least 1.  That is all we know; we have
00796         * to look at each byte to know if there is another, etc.
00797         */
00798        state->pending = 1;
00799     } else {
00800        if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
00801            /*
00802             * Our parent has indefinite-length encoding, and the
00803             * entire tag found is 0, so it seems that we have hit the
00804             * end-of-contents octets.  To handle this, we just change
00805             * our state to that which expects to get the bytes of the
00806             * end-of-contents octets and let that code re-read this byte
00807             * so that our categorization of field types is correct.
00808             * After that, our parent will then deal with everything else.
00809             */
00810            state->place = duringEndOfContents;
00811            state->pending = 2;
00812            state->found_tag_number = 0;
00813            state->found_tag_modifiers = 0;
00814            /*
00815             * We might be an optional field that is, as we now find out,
00816             * missing.  Give our parent a clue that this happened.
00817             */
00818            if (state->optional)
00819               state->missing = PR_TRUE;
00820            return 0;
00821        }
00822        state->place = afterIdentifier;
00823        state->found_tag_number = tag_number;
00824     }
00825     state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
00826 
00827     return 1;
00828 }
00829 
00830 
00831 static unsigned long
00832 sec_asn1d_parse_more_identifier (sec_asn1d_state *state,
00833                              const char *buf, unsigned long len)
00834 {
00835     unsigned char byte;
00836     int count;
00837 
00838     PORT_Assert (state->pending == 1);
00839     PORT_Assert (state->place == duringIdentifier);
00840 
00841     if (len == 0) {
00842        state->top->status = needBytes;
00843        return 0;
00844     }
00845 
00846     count = 0;
00847 
00848     while (len && state->pending) {
00849        if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) {
00850            /*
00851             * The given high tag number overflows our container;
00852             * just give up.  This is not likely to *ever* happen.
00853             */
00854            PORT_SetError (SEC_ERROR_BAD_DER);
00855            state->top->status = decodeError;
00856            return 0;
00857        }
00858 
00859        state->found_tag_number <<= TAG_NUMBER_BITS;
00860 
00861        byte = (unsigned char) buf[count++];
00862        state->found_tag_number |= (byte & TAG_NUMBER_MASK);
00863 
00864        len--;
00865        if (LAST_TAG_NUMBER_BYTE (byte))
00866            state->pending = 0;
00867     }
00868 
00869     if (state->pending == 0)
00870        state->place = afterIdentifier;
00871 
00872     return count;
00873 }
00874 
00875 
00876 static void
00877 sec_asn1d_confirm_identifier (sec_asn1d_state *state)
00878 {
00879     PRBool match;
00880 
00881     PORT_Assert (state->place == afterIdentifier);
00882 
00883     match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask)
00884             == state->expect_tag_modifiers)
00885            && ((state->found_tag_number & state->check_tag_mask)
00886               == state->expect_tag_number));
00887     if (match) {
00888        state->place = beforeLength;
00889     } else {
00890        if (state->optional) {
00891            state->missing = PR_TRUE;
00892            state->place = afterEndOfContents;
00893        } else {
00894            PORT_SetError (SEC_ERROR_BAD_DER);
00895            state->top->status = decodeError;
00896        }
00897     }
00898 }
00899 
00900 
00901 static unsigned long
00902 sec_asn1d_parse_length (sec_asn1d_state *state,
00903                      const char *buf, unsigned long len)
00904 {
00905     unsigned char byte;
00906 
00907     PORT_Assert (state->place == beforeLength);
00908 
00909     if (len == 0) {
00910        state->top->status = needBytes;
00911        return 0;
00912     }
00913 
00914     /*
00915      * The default/likely outcome.  It may get adjusted below.
00916      */
00917     state->place = afterLength;
00918 
00919     byte = (unsigned char) *buf;
00920 
00921     if (LENGTH_IS_SHORT_FORM (byte)) {
00922        state->contents_length = byte;
00923     } else {
00924        state->contents_length = 0;
00925        state->pending = LONG_FORM_LENGTH (byte);
00926        if (state->pending == 0) {
00927            state->indefinite = PR_TRUE;
00928        } else {
00929            state->place = duringLength;
00930        }
00931     }
00932 
00933     /* If we're parsing an ANY, SKIP, or SAVE template, and 
00934     ** the object being saved is definite length encoded and constructed, 
00935     ** there's no point in decoding that construct's members.
00936     ** So, just forget it's constructed and treat it as primitive.
00937     ** (SAVE appears as an ANY at this point)
00938     */
00939     if (!state->indefinite &&
00940        (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
00941        state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
00942     }
00943 
00944     return 1;
00945 }
00946 
00947 
00948 static unsigned long
00949 sec_asn1d_parse_more_length (sec_asn1d_state *state,
00950                           const char *buf, unsigned long len)
00951 {
00952     int count;
00953 
00954     PORT_Assert (state->pending > 0);
00955     PORT_Assert (state->place == duringLength);
00956 
00957     if (len == 0) {
00958        state->top->status = needBytes;
00959        return 0;
00960     }
00961 
00962     count = 0;
00963 
00964     while (len && state->pending) {
00965        if (HIGH_BITS (state->contents_length, 9) != 0) {
00966            /*
00967             * The given full content length overflows our container;
00968             * just give up.
00969             */
00970            PORT_SetError (SEC_ERROR_BAD_DER);
00971            state->top->status = decodeError;
00972            return 0;
00973        }
00974 
00975        state->contents_length <<= 8;
00976        state->contents_length |= (unsigned char) buf[count++];
00977 
00978        len--;
00979        state->pending--;
00980     }
00981 
00982     if (state->pending == 0)
00983        state->place = afterLength;
00984 
00985     return count;
00986 }
00987 
00988 
00989 static void
00990 sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
00991 {
00992     SECItem *item;
00993     PRArenaPool *poolp;
00994     unsigned long alloc_len;
00995 
00996 #ifdef DEBUG_ASN1D_STATES
00997     {
00998         printf("Found Length %d %s\n", state->contents_length,
00999                state->indefinite ? "indefinite" : "");
01000     }
01001 #endif
01002 
01003     /*
01004      * XXX I cannot decide if this allocation should exclude the case
01005      *     where state->endofcontents is true -- figure it out!
01006      */
01007     if (state->allocate) {
01008        void *dest;
01009 
01010        PORT_Assert (state->dest == NULL);
01011        /*
01012         * We are handling a POINTER or a member of a GROUP, and need to
01013         * allocate for the data structure.
01014         */
01015        dest = sec_asn1d_zalloc (state->top->their_pool,
01016                              state->theTemplate->size);
01017        if (dest == NULL) {
01018            state->top->status = decodeError;
01019            return;
01020        }
01021        state->dest = (char *)dest + state->theTemplate->offset;
01022 
01023        /*
01024         * For a member of a GROUP, our parent will later put the
01025         * pointer wherever it belongs.  But for a POINTER, we need
01026         * to record the destination now, in case notify or filter
01027         * procs need access to it -- they cannot find it otherwise,
01028         * until it is too late (for one-pass processing).
01029         */
01030        if (state->parent->place == afterPointer) {
01031            void **placep;
01032 
01033            placep = state->parent->dest;
01034            *placep = dest;
01035        }
01036     }
01037 
01038     /*
01039      * Remember, length may be indefinite here!  In that case,
01040      * both contents_length and pending will be zero.
01041      */
01042     state->pending = state->contents_length;
01043 
01044     /* If this item has definite length encoding, and 
01045     ** is enclosed by a definite length constructed type,
01046     ** make sure it isn't longer than the remaining space in that 
01047     ** constructed type.  
01048     */
01049     if (state->contents_length > 0) {
01050        sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(state);
01051        if (parent && !parent->indefinite && 
01052            state->consumed + state->contents_length > parent->pending) {
01053            PORT_SetError (SEC_ERROR_BAD_DER);
01054            state->top->status = decodeError;
01055            return;
01056        }
01057     }
01058 
01059     /*
01060      * An EXPLICIT is nothing but an outer header, which we have
01061      * already parsed and accepted.  Now we need to do the inner
01062      * header and its contents.
01063      */
01064     if (state->explicit) {
01065        state->place = afterExplicit;
01066        state = sec_asn1d_push_state (state->top,
01067                                   SEC_ASN1GetSubtemplate(state->theTemplate,
01068                                                       state->dest,
01069                                                       PR_FALSE),
01070                                   state->dest, PR_TRUE);
01071        if (state != NULL)
01072            state = sec_asn1d_init_state_based_on_template (state);
01073        return;
01074     }
01075 
01076     /*
01077      * For GROUP (SET OF, SEQUENCE OF), even if we know the length here
01078      * we cannot tell how many items we will end up with ... so push a
01079      * state that can keep track of "children" (the individual members
01080      * of the group; we will allocate as we go and put them all together
01081      * at the end.
01082      */
01083     if (state->underlying_kind & SEC_ASN1_GROUP) {
01084        /* XXX If this assertion holds (should be able to confirm it via
01085         * inspection, too) then move this code into the switch statement
01086         * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
01087         */
01088        PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF
01089           || state->underlying_kind == SEC_ASN1_SEQUENCE_OF
01090           || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
01091           || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
01092                    );
01093        if (state->contents_length != 0 || state->indefinite) {
01094            const SEC_ASN1Template *subt;
01095 
01096            state->place = duringGroup;
01097            subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest,
01098                                       PR_FALSE);
01099            state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE);
01100            if (state != NULL) {
01101               if (!state->top->filter_only)
01102                   state->allocate = PR_TRUE;     /* XXX propogate this? */
01103               /*
01104                * Do the "before" field notification for next in group.
01105                */
01106               sec_asn1d_notify_before (state->top, state->dest, state->depth);
01107               state = sec_asn1d_init_state_based_on_template (state);
01108            }
01109        } else {
01110            /*
01111             * A group of zero; we are done.
01112             * Set state to afterGroup and let that code plant the NULL.
01113             */
01114            state->place = afterGroup;
01115        }
01116        return;
01117     }
01118 
01119     switch (state->underlying_kind) {
01120       case SEC_ASN1_SEQUENCE:
01121        /*
01122         * We need to push a child to handle the individual fields.
01123         */
01124        state->place = duringSequence;
01125        state = sec_asn1d_push_state (state->top, state->theTemplate + 1,
01126                                   state->dest, PR_TRUE);
01127        if (state != NULL) {
01128            /*
01129             * Do the "before" field notification.
01130             */
01131            sec_asn1d_notify_before (state->top, state->dest, state->depth);
01132            state = sec_asn1d_init_state_based_on_template (state);
01133        }
01134        break;
01135 
01136       case SEC_ASN1_SET:    /* XXX SET is not really implemented */
01137        /*
01138         * XXX A plain SET requires special handling; scanning of a
01139         * template to see where a field should go (because by definition,
01140         * they are not in any particular order, and you have to look at
01141         * each tag to disambiguate what the field is).  We may never
01142         * implement this because in practice, it seems to be unused.
01143         */
01144        PORT_Assert(0);
01145        PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */
01146        state->top->status = decodeError;
01147        break;
01148 
01149       case SEC_ASN1_NULL:
01150        /*
01151         * The NULL type, by definition, is "nothing", content length of zero.
01152         * An indefinite-length encoding is not alloweed.
01153         */
01154        if (state->contents_length || state->indefinite) {
01155            PORT_SetError (SEC_ERROR_BAD_DER);
01156            state->top->status = decodeError;
01157            break;
01158        }
01159        if (state->dest != NULL) {
01160            item = (SECItem *)(state->dest);
01161            item->data = NULL;
01162            item->len = 0;
01163        }
01164        state->place = afterEndOfContents;
01165        break;
01166 
01167       case SEC_ASN1_BMP_STRING:
01168        /* Error if length is not divisable by 2 */
01169        if (state->contents_length % 2) {
01170           PORT_SetError (SEC_ERROR_BAD_DER);
01171           state->top->status = decodeError;
01172           break;
01173        }   
01174        /* otherwise, handle as other string types */
01175        goto regular_string_type;
01176 
01177       case SEC_ASN1_UNIVERSAL_STRING:
01178        /* Error if length is not divisable by 4 */
01179        if (state->contents_length % 4) {
01180           PORT_SetError (SEC_ERROR_BAD_DER);
01181           state->top->status = decodeError;
01182           break;
01183        }   
01184        /* otherwise, handle as other string types */
01185        goto regular_string_type;
01186 
01187       case SEC_ASN1_SKIP:
01188       case SEC_ASN1_ANY:
01189       case SEC_ASN1_ANY_CONTENTS:
01190        /*
01191         * These are not (necessarily) strings, but they need nearly
01192         * identical handling (especially when we need to deal with
01193         * constructed sub-pieces), so we pretend they are.
01194         */
01195        /* fallthru */
01196 regular_string_type:
01197       case SEC_ASN1_BIT_STRING:
01198       case SEC_ASN1_IA5_STRING:
01199       case SEC_ASN1_OCTET_STRING:
01200       case SEC_ASN1_PRINTABLE_STRING:
01201       case SEC_ASN1_T61_STRING:
01202       case SEC_ASN1_UTC_TIME:
01203       case SEC_ASN1_UTF8_STRING:
01204       case SEC_ASN1_VISIBLE_STRING:
01205        /*
01206         * We are allocating for a primitive or a constructed string.
01207         * If it is a constructed string, it may also be indefinite-length.
01208         * If it is primitive, the length can (legally) be zero.
01209         * Our first order of business is to allocate the memory for
01210         * the string, if we can (if we know the length).
01211         */
01212        item = (SECItem *)(state->dest);
01213 
01214        /*
01215         * If the item is a definite-length constructed string, then
01216         * the contents_length is actually larger than what we need
01217         * (because it also counts each intermediate header which we
01218         * will be throwing away as we go), but it is a perfectly good
01219         * upper bound that we just allocate anyway, and then concat
01220         * as we go; we end up wasting a few extra bytes but save a
01221         * whole other copy.
01222         */
01223        alloc_len = state->contents_length;
01224        poolp = NULL; /* quiet compiler warnings about unused... */
01225 
01226        if (item == NULL || state->top->filter_only) {
01227            if (item != NULL) {
01228               item->data = NULL;
01229               item->len = 0;
01230            }
01231            alloc_len = 0;
01232        } else if (state->substring) {
01233            /*
01234             * If we are a substring of a constructed string, then we may
01235             * not have to allocate anything (because our parent, the
01236             * actual constructed string, did it for us).  If we are a
01237             * substring and we *do* have to allocate, that means our
01238             * parent is an indefinite-length, so we allocate from our pool;
01239             * later our parent will copy our string into the aggregated
01240             * whole and free our pool allocation.
01241             */
01242            if (item->data == NULL) {
01243               PORT_Assert (item->len == 0);
01244               poolp = state->top->our_pool;
01245            } else {
01246               alloc_len = 0;
01247            }
01248        } else {
01249            item->len = 0;
01250            item->data = NULL;
01251            poolp = state->top->their_pool;
01252        }
01253 
01254        if (alloc_len || ((! state->indefinite)
01255                        && (state->subitems_head != NULL))) {
01256            struct subitem *subitem;
01257            int len;
01258 
01259            PORT_Assert (item);
01260            if (!item) {
01261               PORT_SetError (SEC_ERROR_BAD_DER);
01262               state->top->status = decodeError;
01263               return;
01264            }
01265            PORT_Assert (item->len == 0 && item->data == NULL);
01266            /*
01267             * Check for and handle an ANY which has stashed aside the
01268             * header (identifier and length) bytes for us to include
01269             * in the saved contents.
01270             */
01271            if (state->subitems_head != NULL) {
01272               PORT_Assert (state->underlying_kind == SEC_ASN1_ANY);
01273               for (subitem = state->subitems_head;
01274                    subitem != NULL; subitem = subitem->next)
01275                   alloc_len += subitem->len;
01276            }
01277 
01278            item->data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len);
01279            if (item->data == NULL) {
01280               state->top->status = decodeError;
01281               break;
01282            }
01283 
01284            len = 0;
01285            for (subitem = state->subitems_head;
01286                subitem != NULL; subitem = subitem->next) {
01287               PORT_Memcpy (item->data + len, subitem->data, subitem->len);
01288               len += subitem->len;
01289            }
01290            item->len = len;
01291 
01292            /*
01293             * Because we use arenas and have a mark set, we later free
01294             * everything we have allocated, so this does *not* present
01295             * a memory leak (it is just temporarily left dangling).
01296             */
01297            state->subitems_head = state->subitems_tail = NULL;
01298        }
01299 
01300        if (state->contents_length == 0 && (! state->indefinite)) {
01301            /*
01302             * A zero-length simple or constructed string; we are done.
01303             */
01304            state->place = afterEndOfContents;
01305        } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
01306            const SEC_ASN1Template *sub;
01307 
01308            switch (state->underlying_kind) {
01309              case SEC_ASN1_ANY:
01310              case SEC_ASN1_ANY_CONTENTS:
01311               sub = SEC_AnyTemplate;
01312               break;
01313              case SEC_ASN1_BIT_STRING:
01314               sub = SEC_BitStringTemplate;
01315               break;
01316              case SEC_ASN1_BMP_STRING:
01317               sub = SEC_BMPStringTemplate;
01318               break;
01319              case SEC_ASN1_GENERALIZED_TIME:
01320               sub = SEC_GeneralizedTimeTemplate;
01321               break;
01322              case SEC_ASN1_IA5_STRING:
01323               sub = SEC_IA5StringTemplate;
01324               break;
01325              case SEC_ASN1_OCTET_STRING:
01326               sub = SEC_OctetStringTemplate;
01327               break;
01328              case SEC_ASN1_PRINTABLE_STRING:
01329               sub = SEC_PrintableStringTemplate;
01330               break;
01331              case SEC_ASN1_T61_STRING:
01332               sub = SEC_T61StringTemplate;
01333               break;
01334              case SEC_ASN1_UNIVERSAL_STRING:
01335               sub = SEC_UniversalStringTemplate;
01336               break;
01337              case SEC_ASN1_UTC_TIME:
01338               sub = SEC_UTCTimeTemplate;
01339               break;
01340              case SEC_ASN1_UTF8_STRING:
01341               sub = SEC_UTF8StringTemplate;
01342               break;
01343              case SEC_ASN1_VISIBLE_STRING:
01344               sub = SEC_VisibleStringTemplate;
01345               break;
01346              case SEC_ASN1_SKIP:
01347               sub = SEC_SkipTemplate;
01348               break;
01349              default:              /* redundant given outer switch cases, but */
01350               PORT_Assert(0);      /* the compiler does not seem to know that, */
01351               sub = NULL;   /* so just do enough to quiet it. */
01352               break;
01353            }
01354 
01355            state->place = duringConstructedString;
01356            state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE);
01357            if (state != NULL) {
01358               state->substring = PR_TRUE; /* XXX propogate? */
01359               state = sec_asn1d_init_state_based_on_template (state);
01360            }
01361        } else if (state->indefinite) {
01362            /*
01363             * An indefinite-length string *must* be constructed!
01364             */
01365            PORT_SetError (SEC_ERROR_BAD_DER);
01366            state->top->status = decodeError;
01367        } else {
01368            /*
01369             * A non-zero-length simple string.
01370             */
01371            if (state->underlying_kind == SEC_ASN1_BIT_STRING)
01372               state->place = beforeBitString;
01373            else
01374               state->place = duringLeaf;
01375        }
01376        break;
01377 
01378       default:
01379        /*
01380         * We are allocating for a simple leaf item.
01381         */
01382        if (state->contents_length) {
01383            if (state->dest != NULL) {
01384               item = (SECItem *)(state->dest);
01385               item->len = 0;
01386               if (state->top->filter_only) {
01387                   item->data = NULL;
01388               } else {
01389                   item->data = (unsigned char*)
01390                                 sec_asn1d_zalloc (state->top->their_pool,
01391                                              state->contents_length);
01392                   if (item->data == NULL) {
01393                      state->top->status = decodeError;
01394                      return;
01395                   }
01396               }
01397            }
01398            state->place = duringLeaf;
01399        } else {
01400            /*
01401             * An indefinite-length or zero-length item is not allowed.
01402             * (All legal cases of such were handled above.)
01403             */
01404            PORT_SetError (SEC_ERROR_BAD_DER);
01405            state->top->status = decodeError;
01406        }
01407     }
01408 }
01409 
01410 
01411 static void
01412 sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
01413 {
01414     if (state->child != NULL) {
01415        PORT_Assert (error || state->child->consumed == 0);
01416        PORT_Assert (state->our_mark != NULL);
01417        PORT_ArenaZRelease (state->top->our_pool, state->our_mark);
01418        if (error && state->top->their_pool == NULL) {
01419            /*
01420             * XXX We need to free anything allocated.
01421              * At this point, we failed in the middle of decoding. But we
01422              * can't free the data we previously allocated with PR_Malloc
01423              * unless we keep track of every pointer. So instead we have a
01424              * memory leak when decoding fails half-way, unless an arena is
01425              * used. See bug 95311 .
01426             */
01427        }
01428        state->child = NULL;
01429        state->our_mark = NULL;
01430     } else {
01431        /*
01432         * It is important that we do not leave a mark unreleased/unmarked.
01433         * But I do not think we should ever have one set in this case, only
01434         * if we had a child (handled above).  So check for that.  If this
01435         * assertion should ever get hit, then we probably need to add code
01436         * here to release back to our_mark (and then set our_mark to NULL).
01437         */
01438        PORT_Assert (state->our_mark == NULL);
01439     }
01440     state->place = beforeEndOfContents;
01441 }
01442 
01443 /* We have just saved an entire encoded ASN.1 object (type) for a SAVE 
01444 ** template, and now in the next template, we are going to decode that 
01445 ** saved data  by calling SEC_ASN1DecoderUpdate recursively.
01446 ** If that recursive call fails with needBytes, it is a fatal error,
01447 ** because the encoded object should have been complete.
01448 ** If that recursive call fails with decodeError, it will have already
01449 ** cleaned up the state stack, so we must bail out quickly.
01450 **
01451 ** These checks of the status returned by the recursive call are now
01452 ** done in the caller of this function, immediately after it returns.
01453 */
01454 static void
01455 sec_asn1d_reuse_encoding (sec_asn1d_state *state)
01456 {
01457     sec_asn1d_state *child;
01458     unsigned long consumed;
01459     SECItem *item;
01460     void *dest;
01461 
01462 
01463     child = state->child;
01464     PORT_Assert (child != NULL);
01465 
01466     consumed = child->consumed;
01467     child->consumed = 0;
01468 
01469     item = (SECItem *)(state->dest);
01470     PORT_Assert (item != NULL);
01471 
01472     PORT_Assert (item->len == consumed);
01473 
01474     /*
01475      * Free any grandchild.
01476      */
01477     sec_asn1d_free_child (child, PR_FALSE);
01478 
01479     /*
01480      * Notify after the SAVE field.
01481      */
01482     sec_asn1d_notify_after (state->top, state->dest, state->depth);
01483 
01484     /*
01485      * Adjust to get new dest and move forward.
01486      */
01487     dest = (char *)state->dest - state->theTemplate->offset;
01488     state->theTemplate++;
01489     child->dest = (char *)dest + state->theTemplate->offset;
01490     child->theTemplate = state->theTemplate;
01491 
01492     /*
01493      * Notify before the "real" field.
01494      */
01495     PORT_Assert (state->depth == child->depth);
01496     sec_asn1d_notify_before (state->top, child->dest, child->depth);
01497 
01498     /*
01499      * This will tell DecoderUpdate to return when it is done.
01500      */
01501     state->place = afterSaveEncoding;
01502 
01503     /*
01504      * We already have a child; "push" it by making it current.
01505      */
01506     state->top->current = child;
01507 
01508     /*
01509      * And initialize it so it is ready to parse.
01510      */
01511     (void) sec_asn1d_init_state_based_on_template(child);
01512 
01513     /*
01514      * Now parse that out of our data.
01515      */
01516     if (SEC_ASN1DecoderUpdate (state->top,
01517                             (char *) item->data, item->len) != SECSuccess)
01518        return;
01519     if (state->top->status == needBytes) {
01520        return;
01521     }
01522 
01523     PORT_Assert (state->top->current == state);
01524     PORT_Assert (state->child == child);
01525 
01526     /*
01527      * That should have consumed what we consumed before.
01528      */
01529     PORT_Assert (consumed == child->consumed);
01530     child->consumed = 0;
01531 
01532     /*
01533      * Done.
01534      */
01535     state->consumed += consumed;
01536     child->place = notInUse;
01537     state->place = afterEndOfContents;
01538 }
01539 
01540 
01541 static unsigned long
01542 sec_asn1d_parse_leaf (sec_asn1d_state *state,
01543                     const char *buf, unsigned long len)
01544 {
01545     SECItem *item;
01546     unsigned long bufLen;
01547 
01548     if (len == 0) {
01549        state->top->status = needBytes;
01550        return 0;
01551     }
01552 
01553     if (state->pending < len)
01554        len = state->pending;
01555 
01556     bufLen = len;
01557 
01558     item = (SECItem *)(state->dest);
01559     if (item != NULL && item->data != NULL) {
01560        /* Strip leading zeroes when target is unsigned integer */
01561        if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER   */
01562            item->len == 0 &&                             /* MSB       */
01563            item->type == siUnsignedInteger)              /* unsigned  */
01564        {
01565            while (len > 1 && buf[0] == 0) {              /* leading 0 */
01566               buf++;
01567               len--;
01568            }
01569        }
01570        PORT_Memcpy (item->data + item->len, buf, len);
01571        item->len += len;
01572     }
01573     state->pending -= bufLen;
01574     if (state->pending == 0)
01575        state->place = beforeEndOfContents;
01576 
01577     return bufLen;
01578 }
01579 
01580 
01581 static unsigned long
01582 sec_asn1d_parse_bit_string (sec_asn1d_state *state,
01583                          const char *buf, unsigned long len)
01584 {
01585     unsigned char byte;
01586 
01587     /*PORT_Assert (state->pending > 0); */
01588     PORT_Assert (state->place == beforeBitString);
01589 
01590     if (state->pending == 0) {
01591        if (state->dest != NULL) {
01592            SECItem *item = (SECItem *)(state->dest);
01593            item->data = NULL;
01594            item->len = 0;
01595            state->place = beforeEndOfContents;
01596            return 0;
01597        }
01598     }
01599 
01600     if (len == 0) {
01601        state->top->status = needBytes;
01602        return 0;
01603     }
01604 
01605     byte = (unsigned char) *buf;
01606     if (byte > 7) {
01607        PORT_SetError (SEC_ERROR_BAD_DER);
01608        state->top->status = decodeError;
01609        return 0;
01610     }
01611 
01612     state->bit_string_unused_bits = byte;
01613     state->place = duringBitString;
01614     state->pending -= 1;
01615 
01616     return 1;
01617 }
01618 
01619 
01620 static unsigned long
01621 sec_asn1d_parse_more_bit_string (sec_asn1d_state *state,
01622                              const char *buf, unsigned long len)
01623 {
01624     PORT_Assert (state->place == duringBitString);
01625     if (state->pending == 0) {
01626        /* An empty bit string with some unused bits is invalid. */
01627        if (state->bit_string_unused_bits) {
01628            PORT_SetError (SEC_ERROR_BAD_DER);
01629            state->top->status = decodeError;
01630        } else {
01631            /* An empty bit string with no unused bits is OK. */
01632            state->place = beforeEndOfContents;
01633        }
01634        return 0;
01635     }
01636 
01637     len = sec_asn1d_parse_leaf (state, buf, len);
01638     if (state->place == beforeEndOfContents && state->dest != NULL) {
01639        SECItem *item;
01640 
01641        item = (SECItem *)(state->dest);
01642        if (item->len)
01643            item->len = (item->len << 3) - state->bit_string_unused_bits;
01644     }
01645 
01646     return len;
01647 }
01648 
01649 
01650 /*
01651  * XXX All callers should be looking at return value to detect
01652  * out-of-memory errors (and stop!).
01653  */
01654 static struct subitem *
01655 sec_asn1d_add_to_subitems (sec_asn1d_state *state,
01656                         const void *data, unsigned long len,
01657                         PRBool copy_data)
01658 {
01659     struct subitem *thing;
01660 
01661     thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool,
01662                             sizeof (struct subitem));
01663     if (thing == NULL) {
01664        state->top->status = decodeError;
01665        return NULL;
01666     }
01667 
01668     if (copy_data) {
01669        void *copy;
01670        copy = sec_asn1d_alloc (state->top->our_pool, len);
01671        if (copy == NULL) {
01672            state->top->status = decodeError;
01673            if (!state->top->our_pool)
01674               PORT_Free(thing);
01675            return NULL;
01676        }
01677        PORT_Memcpy (copy, data, len);
01678        thing->data = copy;
01679     } else {
01680        thing->data = data;
01681     }
01682     thing->len = len;
01683     thing->next = NULL;
01684 
01685     if (state->subitems_head == NULL) {
01686        PORT_Assert (state->subitems_tail == NULL);
01687        state->subitems_head = state->subitems_tail = thing;
01688     } else {
01689        state->subitems_tail->next = thing;
01690        state->subitems_tail = thing;
01691     }
01692 
01693     return thing;
01694 }
01695 
01696 
01697 static void
01698 sec_asn1d_record_any_header (sec_asn1d_state *state,
01699                           const char *buf,
01700                           unsigned long len)
01701 {
01702     SECItem *item;
01703 
01704     item = (SECItem *)(state->dest);
01705     if (item != NULL && item->data != NULL) {
01706        PORT_Assert (state->substring);
01707        PORT_Memcpy (item->data + item->len, buf, len);
01708        item->len += len;
01709     } else {
01710        sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE);
01711     }
01712 }
01713 
01714 
01715 /*
01716  * We are moving along through the substrings of a constructed string,
01717  * and have just finished parsing one -- we need to save our child data
01718  * (if the child was not already writing directly into the destination)
01719  * and then move forward by one.
01720  *
01721  * We also have to detect when we are done:
01722  *     - a definite-length encoding stops when our pending value hits 0
01723  *     - an indefinite-length encoding stops when our child is empty
01724  *       (which means it was the end-of-contents octets)
01725  */
01726 static void
01727 sec_asn1d_next_substring (sec_asn1d_state *state)
01728 {
01729     sec_asn1d_state *child;
01730     SECItem *item;
01731     unsigned long child_consumed;
01732     PRBool done;
01733 
01734     PORT_Assert (state->place == duringConstructedString);
01735     PORT_Assert (state->child != NULL);
01736 
01737     child = state->child;
01738 
01739     child_consumed = child->consumed;
01740     child->consumed = 0;
01741     state->consumed += child_consumed;
01742 
01743     done = PR_FALSE;
01744 
01745     if (state->pending) {
01746        PORT_Assert (!state->indefinite);
01747        if (child_consumed > state->pending) {
01748            PORT_SetError (SEC_ERROR_BAD_DER);
01749            state->top->status = decodeError;
01750            return;
01751        }
01752 
01753        state->pending -= child_consumed;
01754        if (state->pending == 0)
01755            done = PR_TRUE;
01756     } else {
01757        PORT_Assert (state->indefinite);
01758 
01759        item = (SECItem *)(child->dest);
01760        if (item != NULL && item->data != NULL) {
01761            /*
01762             * Save the string away for later concatenation.
01763             */
01764            PORT_Assert (item->data != NULL);
01765            sec_asn1d_add_to_subitems (state, item->data, item->len, PR_FALSE);
01766            /*
01767             * Clear the child item for the next round.
01768             */
01769            item->data = NULL;
01770            item->len = 0;
01771        }
01772 
01773        /*
01774         * If our child was just our end-of-contents octets, we are done.
01775         */
01776        if (child->endofcontents)
01777            done = PR_TRUE;
01778     }
01779 
01780     /*
01781      * Stop or do the next one.
01782      */
01783     if (done) {
01784        child->place = notInUse;
01785        state->place = afterConstructedString;
01786     } else {
01787        sec_asn1d_scrub_state (child);
01788        state->top->current = child;
01789     }
01790 }
01791 
01792 
01793 /*
01794  * We are doing a SET OF or SEQUENCE OF, and have just finished an item.
01795  */
01796 static void
01797 sec_asn1d_next_in_group (sec_asn1d_state *state)
01798 {
01799     sec_asn1d_state *child;
01800     unsigned long child_consumed;
01801 
01802     PORT_Assert (state->place == duringGroup);
01803     PORT_Assert (state->child != NULL);
01804 
01805     child = state->child;
01806 
01807     child_consumed = child->consumed;
01808     child->consumed = 0;
01809     state->consumed += child_consumed;
01810 
01811     /*
01812      * If our child was just our end-of-contents octets, we are done.
01813      */
01814     if (child->endofcontents) {
01815        /* XXX I removed the PORT_Assert (child->dest == NULL) because there
01816         * was a bug in that a template that was a sequence of which also had
01817         * a child of a sequence of, in an indefinite group was not working 
01818         * properly.  This fix seems to work, (added the if statement below),
01819         * and nothing appears broken, but I am putting this note here just
01820         * in case. */
01821        /*
01822         * XXX No matter how many times I read that comment,
01823         * I cannot figure out what case he was fixing.  I believe what he
01824         * did was deliberate, so I am loathe to touch it.  I need to
01825         * understand how it could ever be that child->dest != NULL but
01826         * child->endofcontents is true, and why it is important to check
01827         * that state->subitems_head is NULL.  This really needs to be
01828         * figured out, as I am not sure if the following code should be
01829         * compensating for "offset", as is done a little farther below
01830         * in the more normal case.
01831         */
01832        PORT_Assert (state->indefinite);
01833        PORT_Assert (state->pending == 0);
01834        if(child->dest && !state->subitems_head) {
01835            sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE);
01836            child->dest = NULL;
01837        }
01838 
01839        child->place = notInUse;
01840        state->place = afterGroup;
01841        return;
01842     }
01843 
01844     /* 
01845      * Do the "after" field notification for next in group.
01846      */
01847     sec_asn1d_notify_after (state->top, child->dest, child->depth);
01848 
01849     /*
01850      * Save it away (unless we are not storing).
01851      */
01852     if (child->dest != NULL) {
01853        void *dest;
01854 
01855        dest = child->dest;
01856        dest = (char *)dest - child->theTemplate->offset;
01857        sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE);
01858        child->dest = NULL;
01859     }
01860 
01861     /*
01862      * Account for those bytes; see if we are done.
01863      */
01864     if (state->pending) {
01865        PORT_Assert (!state->indefinite);
01866        if (child_consumed > state->pending) {
01867            PORT_SetError (SEC_ERROR_BAD_DER);
01868            state->top->status = decodeError;
01869            return;
01870        }
01871 
01872        state->pending -= child_consumed;
01873        if (state->pending == 0) {
01874            child->place = notInUse;
01875            state->place = afterGroup;
01876            return;
01877        }
01878     }
01879 
01880     /*
01881      * Do the "before" field notification for next item in group.
01882      */
01883     sec_asn1d_notify_before (state->top, child->dest, child->depth);
01884 
01885     /*
01886      * Now we do the next one.
01887      */
01888     sec_asn1d_scrub_state (child);
01889 
01890     /* Initialize child state from the template */
01891     sec_asn1d_init_state_based_on_template(child);
01892 
01893     state->top->current = child;
01894 }
01895 
01896 
01897 /*
01898  * We are moving along through a sequence; move forward by one,
01899  * (detecting end-of-sequence when it happens).
01900  * XXX The handling of "missing" is ugly.  Fix it.
01901  */
01902 static void
01903 sec_asn1d_next_in_sequence (sec_asn1d_state *state)
01904 {
01905     sec_asn1d_state *child;
01906     unsigned long child_consumed;
01907     PRBool child_missing;
01908 
01909     PORT_Assert (state->place == duringSequence);
01910     PORT_Assert (state->child != NULL);
01911 
01912     child = state->child;
01913 
01914     /*
01915      * Do the "after" field notification.
01916      */
01917     sec_asn1d_notify_after (state->top, child->dest, child->depth);
01918 
01919     child_missing = (PRBool) child->missing;
01920     child_consumed = child->consumed;
01921     child->consumed = 0;
01922 
01923     /*
01924      * Take care of accounting.
01925      */
01926     if (child_missing) {
01927        PORT_Assert (child->optional);
01928     } else {
01929        state->consumed += child_consumed;
01930        /*
01931         * Free any grandchild.
01932         */
01933        sec_asn1d_free_child (child, PR_FALSE);
01934        if (state->pending) {
01935            PORT_Assert (!state->indefinite);
01936            if (child_consumed > state->pending) {
01937               PORT_SetError (SEC_ERROR_BAD_DER);
01938               state->top->status = decodeError;
01939               return;
01940            }
01941            state->pending -= child_consumed;
01942            if (state->pending == 0) {
01943               child->theTemplate++;
01944               while (child->theTemplate->kind != 0) {
01945                   if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
01946                      PORT_SetError (SEC_ERROR_BAD_DER);
01947                      state->top->status = decodeError;
01948                      return;
01949                   }
01950                   child->theTemplate++;
01951               }
01952               child->place = notInUse;
01953               state->place = afterEndOfContents;
01954               return;
01955            }
01956        }
01957     }
01958 
01959     /*
01960      * Move forward.
01961      */
01962     child->theTemplate++;
01963     if (child->theTemplate->kind == 0) {
01964        /*
01965         * We are done with this sequence.
01966         */
01967        child->place = notInUse;
01968        if (state->pending) {
01969            PORT_SetError (SEC_ERROR_BAD_DER);
01970            state->top->status = decodeError;
01971        } else if (child_missing) {
01972            /*
01973             * We got to the end, but have a child that started parsing
01974             * and ended up "missing".  The only legitimate reason for
01975             * this is that we had one or more optional fields at the
01976             * end of our sequence, and we were encoded indefinite-length,
01977             * so when we went looking for those optional fields we
01978             * found our end-of-contents octets instead.
01979             * (Yes, this is ugly; dunno a better way to handle it.)
01980             * So, first confirm the situation, and then mark that we
01981             * are done.
01982             */
01983            if (state->indefinite && child->endofcontents) {
01984               PORT_Assert (child_consumed == 2);
01985               if (child_consumed != 2) {
01986                   PORT_SetError (SEC_ERROR_BAD_DER);
01987                   state->top->status = decodeError;
01988               } else {
01989                   state->consumed += child_consumed;
01990                   state->place = afterEndOfContents;
01991               }
01992            } else {
01993               PORT_SetError (SEC_ERROR_BAD_DER);
01994               state->top->status = decodeError;
01995            }
01996        } else {
01997            /*
01998             * We have to finish out, maybe reading end-of-contents octets;
01999             * let the normal logic do the right thing.
02000             */
02001            state->place = beforeEndOfContents;
02002        }
02003     } else {
02004        unsigned char child_found_tag_modifiers = 0;
02005        unsigned long child_found_tag_number = 0;
02006 
02007        /*
02008         * Reset state and push.
02009         */
02010        if (state->dest != NULL)
02011            child->dest = (char *)state->dest + child->theTemplate->offset;
02012 
02013        /*
02014         * Do the "before" field notification.
02015         */
02016        sec_asn1d_notify_before (state->top, child->dest, child->depth);
02017 
02018        if (child_missing) { /* if previous child was missing, copy the tag data we already have */
02019            child_found_tag_modifiers = child->found_tag_modifiers;
02020            child_found_tag_number = child->found_tag_number;
02021        }
02022        state->top->current = child;
02023        child = sec_asn1d_init_state_based_on_template (child);
02024        if (child_missing) {
02025            child->place = afterIdentifier;
02026            child->found_tag_modifiers = child_found_tag_modifiers;
02027            child->found_tag_number = child_found_tag_number;
02028            child->consumed = child_consumed;
02029            if (child->underlying_kind == SEC_ASN1_ANY
02030               && !child->top->filter_only) {
02031               /*
02032                * If the new field is an ANY, and we are storing, then
02033                * we need to save the tag out.  We would have done this
02034                * already in the normal case, but since we were looking
02035                * for an optional field, and we did not find it, we only
02036                * now realize we need to save the tag.
02037                */
02038               unsigned char identifier;
02039 
02040               /*
02041                * Check that we did not end up with a high tag; for that
02042                * we need to re-encode the tag into multiple bytes in order
02043                * to store it back to look like what we parsed originally.
02044                * In practice this does not happen, but for completeness
02045                * sake it should probably be made to work at some point.
02046                */
02047               PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
02048               identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
02049               sec_asn1d_record_any_header (child, (char *) &identifier, 1);
02050            }
02051        }
02052     }
02053 }
02054 
02055 
02056 static void
02057 sec_asn1d_concat_substrings (sec_asn1d_state *state)
02058 {
02059     PORT_Assert (state->place == afterConstructedString);
02060 
02061     if (state->subitems_head != NULL) {
02062        struct subitem *substring;
02063        unsigned long alloc_len, item_len;
02064        unsigned char *where;
02065        SECItem *item;
02066        PRBool is_bit_string;
02067 
02068        item_len = 0;
02069        is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
02070                      ? PR_TRUE : PR_FALSE;
02071 
02072        substring = state->subitems_head;
02073        while (substring != NULL) {
02074            /*
02075             * All bit-string substrings except the last one should be
02076             * a clean multiple of 8 bits.
02077             */
02078            if (is_bit_string && (substring->next == NULL)
02079                            && (substring->len & 0x7)) {
02080               PORT_SetError (SEC_ERROR_BAD_DER);
02081               state->top->status = decodeError;
02082               return;
02083            }
02084            item_len += substring->len;
02085            substring = substring->next;
02086        }
02087 
02088        if (is_bit_string) {
02089 #ifdef XP_WIN16             /* win16 compiler gets an internal error otherwise */
02090            alloc_len = (((long)item_len + 7) / 8);
02091 #else
02092            alloc_len = ((item_len + 7) >> 3);
02093 #endif
02094        } else {
02095            /*
02096             * Add 2 for the end-of-contents octets of an indefinite-length
02097             * ANY that is *not* also an INNER.  Because we zero-allocate
02098             * below, all we need to do is increase the length here.
02099             */
02100            if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
02101               item_len += 2; 
02102            alloc_len = item_len;
02103        }
02104 
02105        item = (SECItem *)(state->dest);
02106        PORT_Assert (item != NULL);
02107        PORT_Assert (item->data == NULL);
02108        item->data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool, 
02109                                                  alloc_len);
02110        if (item->data == NULL) {
02111            state->top->status = decodeError;
02112            return;
02113        }
02114        item->len = item_len;
02115 
02116        where = item->data;
02117        substring = state->subitems_head;
02118        while (substring != NULL) {
02119            if (is_bit_string)
02120               item_len = (substring->len + 7) >> 3;
02121            else
02122               item_len = substring->len;
02123            PORT_Memcpy (where, substring->data, item_len);
02124            where += item_len;
02125            substring = substring->next;
02126        }
02127 
02128        /*
02129         * Because we use arenas and have a mark set, we later free
02130         * everything we have allocated, so this does *not* present
02131         * a memory leak (it is just temporarily left dangling).
02132         */
02133        state->subitems_head = state->subitems_tail = NULL;
02134     }
02135 
02136     state->place = afterEndOfContents;
02137 }
02138 
02139 
02140 static void
02141 sec_asn1d_concat_group (sec_asn1d_state *state)
02142 {
02143     const void ***placep;
02144 
02145     PORT_Assert (state->place == afterGroup);
02146 
02147     placep = (const void***)state->dest;
02148     PORT_Assert(state->subitems_head == NULL || placep != NULL);
02149     if (placep != NULL) {
02150        struct subitem *item;
02151        const void **group;
02152        int count;
02153 
02154        count = 0;
02155        item = state->subitems_head;
02156        while (item != NULL) {
02157            PORT_Assert (item->next != NULL || item == state->subitems_tail);
02158            count++;
02159            item = item->next;
02160        }
02161 
02162        group = (const void**)sec_asn1d_zalloc (state->top->their_pool,
02163                               (count + 1) * (sizeof(void *)));
02164        if (group == NULL) {
02165            state->top->status = decodeError;
02166            return;
02167        }
02168 
02169        *placep = group;
02170 
02171        item = state->subitems_head;
02172        while (item != NULL) {
02173            *group++ = item->data;
02174            item = item->next;
02175        }
02176        *group = NULL;
02177 
02178        /*
02179         * Because we use arenas and have a mark set, we later free
02180         * everything we have allocated, so this does *not* present
02181         * a memory leak (it is just temporarily left dangling).
02182         */
02183        state->subitems_head = state->subitems_tail = NULL;
02184     }
02185 
02186     state->place = afterEndOfContents;
02187 }
02188 
02189 
02190 /*
02191  * For those states that push a child to handle a subtemplate,
02192  * "absorb" that child (transfer necessary information).
02193  */
02194 static void
02195 sec_asn1d_absorb_child (sec_asn1d_state *state)
02196 {
02197     /*
02198      * There is absolutely supposed to be a child there.
02199      */
02200     PORT_Assert (state->child != NULL);
02201 
02202     /*
02203      * Inherit the missing status of our child, and do the ugly
02204      * backing-up if necessary.
02205      */
02206     state->missing = state->child->missing;
02207     if (state->missing) {
02208        state->found_tag_number = state->child->found_tag_number;
02209        state->found_tag_modifiers = state->child->found_tag_modifiers;
02210        state->endofcontents = state->child->endofcontents;
02211     }
02212 
02213     /*
02214      * Add in number of bytes consumed by child.
02215      * (Only EXPLICIT should have already consumed bytes itself.)
02216      */
02217     PORT_Assert (state->place == afterExplicit || state->consumed == 0);
02218     state->consumed += state->child->consumed;
02219 
02220     /*
02221      * Subtract from bytes pending; this only applies to a definite-length
02222      * EXPLICIT field.
02223      */
02224     if (state->pending) {
02225        PORT_Assert (!state->indefinite);
02226        PORT_Assert (state->place == afterExplicit);
02227 
02228        /*
02229         * If we had a definite-length explicit, then what the child
02230         * consumed should be what was left pending.
02231         */
02232        if (state->pending != state->child->consumed) {
02233            if (state->pending < state->child->consumed) {
02234               PORT_SetError (SEC_ERROR_BAD_DER);
02235               state->top->status = decodeError;
02236               return;
02237            }
02238            /*
02239             * Okay, this is a hack.  It *should* be an error whether
02240             * pending is too big or too small, but it turns out that
02241             * we had a bug in our *old* DER encoder that ended up
02242             * counting an explicit header twice in the case where
02243             * the underlying type was an ANY.  So, because we cannot
02244             * prevent receiving these (our own certificate server can
02245             * send them to us), we need to be lenient and accept them.
02246             * To do so, we need to pretend as if we read all of the
02247             * bytes that the header said we would find, even though
02248             * we actually came up short.
02249             */
02250            state->consumed += (state->pending - state->child->consumed);
02251        }
02252        state->pending = 0;
02253     }
02254 
02255     /*
02256      * Indicate that we are done with child.
02257      */
02258     state->child->consumed = 0;
02259 
02260     /*
02261      * And move on to final state.
02262      * (Technically everybody could move to afterEndOfContents except
02263      * for an indefinite-length EXPLICIT; for simplicity though we assert
02264      * that but let the end-of-contents code do the real determination.)
02265      */
02266     PORT_Assert (state->place == afterExplicit || (! state->indefinite));
02267     state->place = beforeEndOfContents;
02268 }
02269 
02270 
02271 static void
02272 sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state)
02273 {
02274     PORT_Assert (state->place == beforeEndOfContents);
02275 
02276     if (state->indefinite) {
02277        state->place = duringEndOfContents;
02278        state->pending = 2;
02279     } else {
02280        state->place = afterEndOfContents;
02281     }
02282 }
02283 
02284 
02285 static unsigned long
02286 sec_asn1d_parse_end_of_contents (sec_asn1d_state *state,
02287                              const char *buf, unsigned long len)
02288 {
02289     unsigned int i;
02290 
02291     PORT_Assert (state->pending <= 2);
02292     PORT_Assert (state->place == duringEndOfContents);
02293 
02294     if (len == 0) {
02295        state->top->status = needBytes;
02296        return 0;
02297     }
02298 
02299     if (state->pending < len)
02300        len = state->pending;
02301 
02302     for (i = 0; i < len; i++) {
02303        if (buf[i] != 0) {
02304            /*
02305             * We expect to find only zeros; if not, just give up.
02306             */
02307            PORT_SetError (SEC_ERROR_BAD_DER);
02308            state->top->status = decodeError;
02309            return 0;
02310        }
02311     }
02312 
02313     state->pending -= len;
02314 
02315     if (state->pending == 0) {
02316        state->place = afterEndOfContents;
02317        state->endofcontents = PR_TRUE;
02318     }
02319 
02320     return len;
02321 }
02322 
02323 
02324 static void
02325 sec_asn1d_pop_state (sec_asn1d_state *state)
02326 {
02327 #if 0  /* XXX I think this should always be handled explicitly by parent? */
02328     /*
02329      * Account for our child.
02330      */
02331     if (state->child != NULL) {
02332        state->consumed += state->child->consumed;
02333        if (state->pending) {
02334            PORT_Assert (!state->indefinite);
02335            if (state->child->consumed > state->pending) {
02336               PORT_SetError (SEC_ERROR_BAD_DER);
02337               state->top->status = decodeError;
02338            } else {
02339               state->pending -= state->child->consumed;
02340            }
02341        }
02342        state->child->consumed = 0;
02343     }
02344 #endif /* XXX */
02345 
02346     /*
02347      * Free our child.
02348      */
02349     sec_asn1d_free_child (state, PR_FALSE);
02350 
02351     /*
02352      * Just make my parent be the current state.  It will then clean
02353      * up after me and free me (or reuse me).
02354      */
02355     state->top->current = state->parent;
02356 }
02357 
02358 static sec_asn1d_state *
02359 sec_asn1d_before_choice (sec_asn1d_state *state)
02360 {
02361     sec_asn1d_state *child;
02362 
02363     if (state->allocate) {
02364        void *dest;
02365 
02366        dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
02367        if ((void *)NULL == dest) {
02368            state->top->status = decodeError;
02369            return (sec_asn1d_state *)NULL;
02370        }
02371 
02372        state->dest = (char *)dest + state->theTemplate->offset;
02373     }
02374 
02375     child = sec_asn1d_push_state(state->top, state->theTemplate + 1, 
02376                              (char *)state->dest - state->theTemplate->offset, 
02377                              PR_FALSE);
02378     if ((sec_asn1d_state *)NULL == child) {
02379        return (sec_asn1d_state *)NULL;
02380     }
02381 
02382     sec_asn1d_scrub_state(child);
02383     child = sec_asn1d_init_state_based_on_template(child);
02384     if ((sec_asn1d_state *)NULL == child) {
02385        return (sec_asn1d_state *)NULL;
02386     }
02387 
02388     child->optional = PR_TRUE;
02389 
02390     state->place = duringChoice;
02391 
02392     return child;
02393 }
02394 
02395 static sec_asn1d_state *
02396 sec_asn1d_during_choice (sec_asn1d_state *state)
02397 {
02398     sec_asn1d_state *child = state->child;
02399     
02400     PORT_Assert((sec_asn1d_state *)NULL != child);
02401 
02402     if (child->missing) {
02403        unsigned char child_found_tag_modifiers = 0;
02404        unsigned long child_found_tag_number = 0;
02405        void *        dest;
02406 
02407        state->consumed += child->consumed;
02408 
02409        if (child->endofcontents) {
02410            /* This choice is probably the first item in a GROUP
02411            ** (e.g. SET_OF) that was indefinite-length encoded.
02412            ** We're actually at the end of that GROUP.
02413            ** We look up the stack to be sure that we find
02414            ** a state with indefinite length encoding before we
02415            ** find a state (like a SEQUENCE) that is definite.
02416            */
02417            child->place = notInUse;
02418            state->place = afterChoice;
02419            state->endofcontents = PR_TRUE;  /* propagate this up */
02420            if (sec_asn1d_parent_allows_EOC(state))
02421               return state;
02422            PORT_SetError(SEC_ERROR_BAD_DER);
02423            state->top->status = decodeError;
02424            return NULL;
02425        }
02426 
02427        dest = (char *)child->dest - child->theTemplate->offset;
02428        child->theTemplate++;
02429 
02430        if (0 == child->theTemplate->kind) {
02431            /* Ran out of choices */
02432            PORT_SetError(SEC_ERROR_BAD_DER);
02433            state->top->status = decodeError;
02434            return (sec_asn1d_state *)NULL;
02435        }
02436        child->dest = (char *)dest + child->theTemplate->offset;
02437 
02438        /* cargo'd from next_in_sequence innards */
02439        if (state->pending) {
02440            PORT_Assert(!state->indefinite);
02441            if (child->consumed > state->pending) {
02442               PORT_SetError (SEC_ERROR_BAD_DER);
02443               state->top->status = decodeError;
02444               return NULL;
02445            }
02446            state->pending -= child->consumed;
02447            if (0 == state->pending) {
02448               /* XXX uh.. not sure if I should have stopped this
02449                * from happening before. */
02450               PORT_Assert(0);
02451               PORT_SetError(SEC_ERROR_BAD_DER);
02452               state->top->status = decodeError;
02453               return (sec_asn1d_state *)NULL;
02454            }
02455        }
02456 
02457        child->consumed = 0;
02458        sec_asn1d_scrub_state(child);
02459 
02460        /* move it on top again */
02461        state->top->current = child;
02462 
02463        child_found_tag_modifiers = child->found_tag_modifiers;
02464        child_found_tag_number = child->found_tag_number;
02465 
02466        child = sec_asn1d_init_state_based_on_template(child);
02467        if ((sec_asn1d_state *)NULL == child) {
02468            return (sec_asn1d_state *)NULL;
02469        }
02470 
02471        /* copy our findings to the new top */
02472        child->found_tag_modifiers = child_found_tag_modifiers;
02473        child->found_tag_number = child_found_tag_number;
02474 
02475        child->optional = PR_TRUE;
02476        child->place = afterIdentifier;
02477 
02478        return child;
02479     } 
02480     if ((void *)NULL != state->dest) {
02481        /* Store the enum */
02482        int *which = (int *)state->dest;
02483        *which = (int)child->theTemplate->size;
02484     }
02485 
02486     child->place = notInUse;
02487 
02488     state->place = afterChoice;
02489     return state;
02490 }
02491 
02492 static void
02493 sec_asn1d_after_choice (sec_asn1d_state *state)
02494 {
02495     state->consumed += state->child->consumed;
02496     state->child->consumed = 0;
02497     state->place = afterEndOfContents;
02498     sec_asn1d_pop_state(state);
02499 }
02500 
02501 unsigned long
02502 sec_asn1d_uinteger(SECItem *src)
02503 {
02504     unsigned long value;
02505     int len;
02506 
02507     if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
02508        return 0;
02509 
02510     value = 0;
02511     len = src->len;
02512     while (len) {
02513        value <<= 8;
02514        value |= src->data[--len];
02515     }
02516     return value;
02517 }
02518 
02519 SECStatus
02520 SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
02521 {
02522     unsigned long v;
02523     unsigned int i;
02524     
02525     if (src == NULL) {
02526        PORT_SetError(SEC_ERROR_INVALID_ARGS);
02527        return SECFailure;
02528     }
02529 
02530     if (src->len > sizeof(unsigned long)) {
02531        PORT_SetError(SEC_ERROR_INVALID_ARGS);
02532        return SECFailure;
02533     }
02534 
02535     if (src->data == NULL) {
02536        PORT_SetError(SEC_ERROR_INVALID_ARGS);
02537        return SECFailure;
02538     }
02539 
02540     if (src->data[0] & 0x80)
02541        v = -1;              /* signed and negative - start with all 1's */
02542     else
02543        v = 0;
02544 
02545     for (i= 0; i < src->len; i++) {
02546        /* shift in next byte */
02547        v <<= 8;
02548        v |= src->data[i];
02549     }
02550     *value = v;
02551     return SECSuccess;
02552 }
02553 
02554 #ifdef DEBUG_ASN1D_STATES
02555 static void
02556 dump_states(SEC_ASN1DecoderContext *cx)
02557 {
02558     sec_asn1d_state *state;
02559     char kindBuf[256];
02560 
02561     for (state = cx->current; state->parent; state = state->parent) {
02562         ;
02563     }
02564 
02565     for (; state; state = state->child) {
02566         int i;
02567         for (i = 0; i < state->depth; i++) {
02568             printf("  ");
02569         }
02570 
02571         i = formatKind(state->theTemplate->kind, kindBuf);
02572         printf("%s: tmpl %08x, kind%s",
02573                (state == cx->current) ? "STATE" : "State",
02574                state->theTemplate,
02575                kindBuf);
02576         printf(" %s", (state->place >= 0 && state->place <= notInUse)
02577                        ? place_names[ state->place ]
02578                        : "(undefined)");
02579         if (!i)
02580             printf(", expect 0x%02x",
02581                    state->expect_tag_number | state->expect_tag_modifiers);
02582 
02583         printf("%s%s%s %d\n",
02584                state->indefinite    ? ", indef"   : "",
02585                state->missing       ? ", miss"    : "",
02586                state->endofcontents ? ", EOC"     : "",
02587                state->pending
02588                );
02589     }
02590 
02591     return;
02592 }
02593 #endif /* DEBUG_ASN1D_STATES */
02594 
02595 SECStatus
02596 SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,
02597                      const char *buf, unsigned long len)
02598 {
02599     sec_asn1d_state *state = NULL;
02600     unsigned long consumed;
02601     SEC_ASN1EncodingPart what;
02602     sec_asn1d_state *stateEnd = cx->current;
02603 
02604     if (cx->status == needBytes)
02605        cx->status = keepGoing;
02606 
02607     while (cx->status == keepGoing) {
02608        state = cx->current;
02609        what = SEC_ASN1_Contents;
02610        consumed = 0;
02611 #ifdef DEBUG_ASN1D_STATES
02612         printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
02613                (state->place >= 0 && state->place <= notInUse) ?
02614                place_names[ state->place ] : "(undefined)",
02615                (unsigned int)((unsigned char *)buf)[ consumed ],
02616                buf, consumed);
02617         dump_states(cx);
02618 #endif /* DEBUG_ASN1D_STATES */
02619        switch (state->place) {
02620          case beforeIdentifier:
02621            consumed = sec_asn1d_parse_identifier (state, buf, len);
02622            what = SEC_ASN1_Identifier;
02623            break;
02624          case duringIdentifier:
02625            consumed = sec_asn1d_parse_more_identifier (state, buf, len);
02626            what = SEC_ASN1_Identifier;
02627            break;
02628          case afterIdentifier:
02629            sec_asn1d_confirm_identifier (state);
02630            break;
02631          case beforeLength:
02632            consumed = sec_asn1d_parse_length (state, buf, len);
02633            what = SEC_ASN1_Length;
02634            break;
02635          case duringLength:
02636            consumed = sec_asn1d_parse_more_length (state, buf, len);
02637            what = SEC_ASN1_Length;
02638            break;
02639          case afterLength:
02640            sec_asn1d_prepare_for_contents (state);
02641            break;
02642          case beforeBitString:
02643            consumed = sec_asn1d_parse_bit_string (state, buf, len);
02644            break;
02645          case duringBitString:
02646            consumed = sec_asn1d_parse_more_bit_string (state, buf, len);
02647            break;
02648          case duringConstructedString:
02649            sec_asn1d_next_substring (state);
02650            break;
02651          case duringGroup:
02652            sec_asn1d_next_in_group (state);
02653            break;
02654          case duringLeaf:
02655            consumed = sec_asn1d_parse_leaf (state, buf, len);
02656            break;
02657          case duringSaveEncoding:
02658            sec_asn1d_reuse_encoding (state);
02659            if (cx->status == decodeError) {
02660               /* recursive call has already popped all states from stack.
02661               ** Bail out quickly.
02662               */
02663               return SECFailure;
02664            }
02665            if (cx->status == needBytes) {
02666               /* recursive call wanted more data. Fatal. Clean up below. */
02667               PORT_SetError (SEC_ERROR_BAD_DER);
02668               cx->status = decodeError;
02669            }
02670            break;
02671          case duringSequence:
02672            sec_asn1d_next_in_sequence (state);
02673            break;
02674          case afterConstructedString:
02675            sec_asn1d_concat_substrings (state);
02676            break;
02677          case afterExplicit:
02678          case afterImplicit:
02679          case afterInline:
02680          case afterPointer:
02681            sec_asn1d_absorb_child (state);
02682            break;
02683          case afterGroup:
02684            sec_asn1d_concat_group (state);
02685            break;
02686          case afterSaveEncoding:
02687            /* SEC_ASN1DecoderUpdate has called itself recursively to 
02688            ** decode SAVEd encoded data, and now is done decoding that.
02689            ** Return to the calling copy of SEC_ASN1DecoderUpdate.
02690            */
02691            return SECSuccess;
02692          case beforeEndOfContents:
02693            sec_asn1d_prepare_for_end_of_contents (state);
02694            break;
02695          case duringEndOfContents:
02696            consumed = sec_asn1d_parse_end_of_contents (state, buf, len);
02697            what = SEC_ASN1_EndOfContents;
02698            break;
02699          case afterEndOfContents:
02700            sec_asn1d_pop_state (state);
02701            break;
02702           case beforeChoice:
02703             state = sec_asn1d_before_choice(state);
02704             break;
02705           case duringChoice:
02706             state = sec_asn1d_during_choice(state);
02707             break;
02708           case afterChoice:
02709             sec_asn1d_after_choice(state);
02710             break;
02711          case notInUse:
02712          default:
02713            /* This is not an error, but rather a plain old BUG! */
02714            PORT_Assert (0);
02715            PORT_SetError (SEC_ERROR_BAD_DER);
02716            cx->status = decodeError;
02717            break;
02718        }
02719 
02720        if (cx->status == decodeError)
02721            break;
02722 
02723        /* We should not consume more than we have.  */
02724        PORT_Assert (consumed <= len);
02725        if (consumed > len) {
02726            PORT_SetError (SEC_ERROR_BAD_DER);
02727            cx->status = decodeError;
02728            break;
02729        }
02730 
02731        /* It might have changed, so we have to update our local copy.  */
02732        state = cx->current;
02733 
02734        /* If it is NULL, we have popped all the way to the top.  */
02735        if (state == NULL) {
02736            PORT_Assert (consumed == 0);
02737 #if 0  /* XXX I want this here, but it seems that we have situations (like
02738         * downloading a pkcs7 cert chain from some issuers) that give us a
02739         * length which is greater than the entire encoding.  So, we cannot
02740         * have this be an error.
02741         */
02742            if (len > 0) {
02743               PORT_SetError (SEC_ERROR_BAD_DER);
02744               cx->status = decodeError;
02745            } else
02746 #endif
02747               cx->status = allDone;
02748            break;
02749        }
02750        else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
02751            cx->status = allDone;
02752            break;
02753        }
02754          
02755        if (consumed == 0)
02756            continue;
02757 
02758        /*
02759         * The following check is specifically looking for an ANY
02760         * that is *not* also an INNER, because we need to save aside
02761         * all bytes in that case -- the contents parts will get
02762         * handled like all other contents, and the end-of-contents
02763         * bytes are added by the concat code, but the outer header
02764         * bytes need to get saved too, so we do them explicitly here.
02765         */
02766        if (state->underlying_kind == SEC_ASN1_ANY
02767            && !cx->filter_only && (what == SEC_ASN1_Identifier
02768                                 || what == SEC_ASN1_Length)) {
02769            sec_asn1d_record_any_header (state, buf, consumed);
02770        }
02771 
02772        /*
02773         * We had some number of good, accepted bytes.  If the caller
02774         * has registered to see them, pass them along.
02775         */
02776        if (state->top->filter_proc != NULL) {
02777            int depth;
02778 
02779            depth = state->depth;
02780            if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
02781               PORT_Assert (state->parent != NULL
02782                           && state->parent->indefinite);
02783               depth--;
02784               PORT_Assert (depth == state->parent->depth);
02785            }
02786            (* state->top->filter_proc) (state->top->filter_arg,
02787                                     buf, consumed, depth, what);
02788        }
02789 
02790        state->consumed += consumed;
02791        buf += consumed;
02792        len -= consumed;
02793     }
02794 
02795     if (cx->status == decodeError) {
02796        while (state != NULL && stateEnd->parent!=state) {
02797            sec_asn1d_free_child (state, PR_TRUE);
02798            state = state->parent;
02799        }
02800 #ifdef SEC_ASN1D_FREE_ON_ERROR     /*
02801                              * XXX This does not work because we can
02802                              * end up leaving behind dangling pointers
02803                              * to stuff that was allocated.  In order
02804                              * to make this really work (which would
02805                              * be a good thing, I think), we need to
02806                              * keep track of every place/pointer that
02807                              * was allocated and make sure to NULL it
02808                              * out before we then free back to the mark.     
02809                              */
02810        if (cx->their_pool != NULL) {
02811            PORT_Assert (cx->their_mark != NULL);
02812            PORT_ArenaRelease (cx->their_pool, cx->their_mark);
02813        }
02814 #endif
02815        return SECFailure;
02816     }
02817 
02818 #if 0  /* XXX This is what I want, but cannot have because it seems we
02819         * have situations (like when downloading a pkcs7 cert chain from
02820         * some issuers) that give us a total length which is greater than
02821         * the entire encoding.  So, we have to allow allDone to have a
02822         * remaining length greater than zero.  I wanted to catch internal
02823         * bugs with this, noticing when we do not have the right length.
02824         * Oh well.
02825         */
02826     PORT_Assert (len == 0
02827                && (cx->status == needBytes || cx->status == allDone));
02828 #else
02829     PORT_Assert ((len == 0 && cx->status == needBytes)
02830                || cx->status == allDone);
02831 #endif
02832     return SECSuccess;
02833 }
02834 
02835 
02836 SECStatus
02837 SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx)
02838 {
02839     SECStatus rv;
02840 
02841     if (cx->status == needBytes) {
02842        PORT_SetError (SEC_ERROR_BAD_DER);
02843        rv = SECFailure;
02844     } else {
02845        rv = SECSuccess;
02846     }
02847 
02848     /*
02849      * XXX anything else that needs to be finished?
02850      */
02851 
02852     PORT_FreeArena (cx->our_pool, PR_TRUE);
02853 
02854     return rv;
02855 }
02856 
02857 
02858 SEC_ASN1DecoderContext *
02859 SEC_ASN1DecoderStart (PRArenaPool *their_pool, void *dest,
02860                     const SEC_ASN1Template *theTemplate)
02861 {
02862     PRArenaPool *our_pool;
02863     SEC_ASN1DecoderContext *cx;
02864 
02865     our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
02866     if (our_pool == NULL)
02867        return NULL;
02868 
02869     cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx));
02870     if (cx == NULL) {
02871        PORT_FreeArena (our_pool, PR_FALSE);
02872        return NULL;
02873     }
02874 
02875     cx->our_pool = our_pool;
02876     if (their_pool != NULL) {
02877        cx->their_pool = their_pool;
02878 #ifdef SEC_ASN1D_FREE_ON_ERROR
02879        cx->their_mark = PORT_ArenaMark (their_pool);
02880 #endif
02881     }
02882 
02883     cx->status = needBytes;
02884 
02885     if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL
02886        || sec_asn1d_init_state_based_on_template (cx->current) == NULL) {
02887        /*
02888         * Trouble initializing (probably due to failed allocations)
02889         * requires that we just give up.
02890         */
02891        PORT_FreeArena (our_pool, PR_FALSE);
02892        return NULL;
02893     }
02894 
02895     return cx;
02896 }
02897 
02898 
02899 void
02900 SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx,
02901                            SEC_ASN1WriteProc fn, void *arg,
02902                            PRBool only)
02903 {
02904     /* check that we are "between" fields here */
02905     PORT_Assert (cx->during_notify);
02906 
02907     cx->filter_proc = fn;
02908     cx->filter_arg = arg;
02909     cx->filter_only = only;
02910 }
02911 
02912 
02913 void
02914 SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx)
02915 {
02916     /* check that we are "between" fields here */
02917     PORT_Assert (cx->during_notify);
02918 
02919     cx->filter_proc = NULL;
02920     cx->filter_arg = NULL;
02921     cx->filter_only = PR_FALSE;
02922 }
02923 
02924 
02925 void
02926 SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx,
02927                            SEC_ASN1NotifyProc fn, void *arg)
02928 {
02929     cx->notify_proc = fn;
02930     cx->notify_arg = arg;
02931 }
02932 
02933 
02934 void
02935 SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx)
02936 {
02937     cx->notify_proc = NULL;
02938     cx->notify_arg = NULL;  /* not necessary; just being clean */
02939 }
02940 
02941 void
02942 SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
02943 {
02944     PORT_Assert(cx);
02945     PORT_SetError(error);
02946     cx->status = decodeError;
02947 }
02948 
02949 
02950 SECStatus
02951 SEC_ASN1Decode (PRArenaPool *poolp, void *dest,
02952               const SEC_ASN1Template *theTemplate,
02953               const char *buf, long len)
02954 {
02955     SEC_ASN1DecoderContext *dcx;
02956     SECStatus urv, frv;
02957 
02958     dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate);
02959     if (dcx == NULL)
02960        return SECFailure;
02961 
02962     urv = SEC_ASN1DecoderUpdate (dcx, buf, len);
02963     frv = SEC_ASN1DecoderFinish (dcx);
02964 
02965     if (urv != SECSuccess)
02966        return urv;
02967 
02968     return frv;
02969 }
02970 
02971 
02972 SECStatus
02973 SEC_ASN1DecodeItem (PRArenaPool *poolp, void *dest,
02974                   const SEC_ASN1Template *theTemplate,
02975                   const SECItem *src)
02976 {
02977     return SEC_ASN1Decode (poolp, dest, theTemplate,
02978                         (const char *)src->data, src->len);
02979 }
02980 
02981 #ifdef DEBUG_ASN1D_STATES
02982 void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
02983 {
02984     printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
02985     fflush(stdout);
02986 }
02987 #endif
02988 
02989 /*
02990  * Generic templates for individual/simple items and pointers to
02991  * and sets of same.
02992  *
02993  * If you need to add a new one, please note the following:
02994  *      - For each new basic type you should add *four* templates:
02995  *     one plain, one PointerTo, one SequenceOf and one SetOf.
02996  *      - If the new type can be constructed (meaning, it is a
02997  *     *string* type according to BER/DER rules), then you should
02998  *     or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
02999  *     See the definition of the OctetString template for an example.
03000  *      - It may not be obvious, but these are in *alphabetical*
03001  *     order based on the SEC_ASN1_XXX name; so put new ones in
03002  *     the appropriate place.
03003  */
03004 
03005 const SEC_ASN1Template SEC_AnyTemplate[] = {
03006     { SEC_ASN1_ANY | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03007 };
03008 
03009 const SEC_ASN1Template SEC_PointerToAnyTemplate[] = {
03010     { SEC_ASN1_POINTER, 0, SEC_AnyTemplate }
03011 };
03012 
03013 const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
03014     { SEC_ASN1_SEQUENCE_OF, 0, SEC_AnyTemplate }
03015 };
03016 
03017 const SEC_ASN1Template SEC_SetOfAnyTemplate[] = {
03018     { SEC_ASN1_SET_OF, 0, SEC_AnyTemplate }
03019 };
03020 
03021 const SEC_ASN1Template SEC_BitStringTemplate[] = {
03022     { SEC_ASN1_BIT_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03023 };
03024 
03025 const SEC_ASN1Template SEC_PointerToBitStringTemplate[] = {
03026     { SEC_ASN1_POINTER, 0, SEC_BitStringTemplate }
03027 };
03028 
03029 const SEC_ASN1Template SEC_SequenceOfBitStringTemplate[] = {
03030     { SEC_ASN1_SEQUENCE_OF, 0, SEC_BitStringTemplate }
03031 };
03032 
03033 const SEC_ASN1Template SEC_SetOfBitStringTemplate[] = {
03034     { SEC_ASN1_SET_OF, 0, SEC_BitStringTemplate }
03035 };
03036 
03037 const SEC_ASN1Template SEC_BMPStringTemplate[] = {
03038     { SEC_ASN1_BMP_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03039 };
03040 
03041 const SEC_ASN1Template SEC_PointerToBMPStringTemplate[] = {
03042     { SEC_ASN1_POINTER, 0, SEC_BMPStringTemplate }
03043 };
03044 
03045 const SEC_ASN1Template SEC_SequenceOfBMPStringTemplate[] = {
03046     { SEC_ASN1_SEQUENCE_OF, 0, SEC_BMPStringTemplate }
03047 };
03048 
03049 const SEC_ASN1Template SEC_SetOfBMPStringTemplate[] = {
03050     { SEC_ASN1_SET_OF, 0, SEC_BMPStringTemplate }
03051 };
03052 
03053 const SEC_ASN1Template SEC_BooleanTemplate[] = {
03054     { SEC_ASN1_BOOLEAN, 0, NULL, sizeof(SECItem) }
03055 };
03056 
03057 const SEC_ASN1Template SEC_PointerToBooleanTemplate[] = {
03058     { SEC_ASN1_POINTER, 0, SEC_BooleanTemplate }
03059 };
03060 
03061 const SEC_ASN1Template SEC_SequenceOfBooleanTemplate[] = {
03062     { SEC_ASN1_SEQUENCE_OF, 0, SEC_BooleanTemplate }
03063 };
03064 
03065 const SEC_ASN1Template SEC_SetOfBooleanTemplate[] = {
03066     { SEC_ASN1_SET_OF, 0, SEC_BooleanTemplate }
03067 };
03068 
03069 const SEC_ASN1Template SEC_EnumeratedTemplate[] = {
03070     { SEC_ASN1_ENUMERATED, 0, NULL, sizeof(SECItem) }
03071 };
03072 
03073 const SEC_ASN1Template SEC_PointerToEnumeratedTemplate[] = {
03074     { SEC_ASN1_POINTER, 0, SEC_EnumeratedTemplate }
03075 };
03076 
03077 const SEC_ASN1Template SEC_SequenceOfEnumeratedTemplate[] = {
03078     { SEC_ASN1_SEQUENCE_OF, 0, SEC_EnumeratedTemplate }
03079 };
03080 
03081 const SEC_ASN1Template SEC_SetOfEnumeratedTemplate[] = {
03082     { SEC_ASN1_SET_OF, 0, SEC_EnumeratedTemplate }
03083 };
03084 
03085 const SEC_ASN1Template SEC_GeneralizedTimeTemplate[] = {
03086     { SEC_ASN1_GENERALIZED_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
03087 };
03088 
03089 const SEC_ASN1Template SEC_PointerToGeneralizedTimeTemplate[] = {
03090     { SEC_ASN1_POINTER, 0, SEC_GeneralizedTimeTemplate }
03091 };
03092 
03093 const SEC_ASN1Template SEC_SequenceOfGeneralizedTimeTemplate[] = {
03094     { SEC_ASN1_SEQUENCE_OF, 0, SEC_GeneralizedTimeTemplate }
03095 };
03096 
03097 const SEC_ASN1Template SEC_SetOfGeneralizedTimeTemplate[] = {
03098     { SEC_ASN1_SET_OF, 0, SEC_GeneralizedTimeTemplate }
03099 };
03100 
03101 const SEC_ASN1Template SEC_IA5StringTemplate[] = {
03102     { SEC_ASN1_IA5_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03103 };
03104 
03105 const SEC_ASN1Template SEC_PointerToIA5StringTemplate[] = {
03106     { SEC_ASN1_POINTER, 0, SEC_IA5StringTemplate }
03107 };
03108 
03109 const SEC_ASN1Template SEC_SequenceOfIA5StringTemplate[] = {
03110     { SEC_ASN1_SEQUENCE_OF, 0, SEC_IA5StringTemplate }
03111 };
03112 
03113 const SEC_ASN1Template SEC_SetOfIA5StringTemplate[] = {
03114     { SEC_ASN1_SET_OF, 0, SEC_IA5StringTemplate }
03115 };
03116 
03117 const SEC_ASN1Template SEC_IntegerTemplate[] = {
03118     { SEC_ASN1_INTEGER, 0, NULL, sizeof(SECItem) }
03119 };
03120 
03121 const SEC_ASN1Template SEC_PointerToIntegerTemplate[] = {
03122     { SEC_ASN1_POINTER, 0, SEC_IntegerTemplate }
03123 };
03124 
03125 const SEC_ASN1Template SEC_SequenceOfIntegerTemplate[] = {
03126     { SEC_ASN1_SEQUENCE_OF, 0, SEC_IntegerTemplate }
03127 };
03128 
03129 const SEC_ASN1Template SEC_SetOfIntegerTemplate[] = {
03130     { SEC_ASN1_SET_OF, 0, SEC_IntegerTemplate }
03131 };
03132 
03133 const SEC_ASN1Template SEC_NullTemplate[] = {
03134     { SEC_ASN1_NULL, 0, NULL, sizeof(SECItem) }
03135 };
03136 
03137 const SEC_ASN1Template SEC_PointerToNullTemplate[] = {
03138     { SEC_ASN1_POINTER, 0, SEC_NullTemplate }
03139 };
03140 
03141 const SEC_ASN1Template SEC_SequenceOfNullTemplate[] = {
03142     { SEC_ASN1_SEQUENCE_OF, 0, SEC_NullTemplate }
03143 };
03144 
03145 const SEC_ASN1Template SEC_SetOfNullTemplate[] = {
03146     { SEC_ASN1_SET_OF, 0, SEC_NullTemplate }
03147 };
03148 
03149 const SEC_ASN1Template SEC_ObjectIDTemplate[] = {
03150     { SEC_ASN1_OBJECT_ID, 0, NULL, sizeof(SECItem) }
03151 };
03152 
03153 const SEC_ASN1Template SEC_PointerToObjectIDTemplate[] = {
03154     { SEC_ASN1_POINTER, 0, SEC_ObjectIDTemplate }
03155 };
03156 
03157 const SEC_ASN1Template SEC_SequenceOfObjectIDTemplate[] = {
03158     { SEC_ASN1_SEQUENCE_OF, 0, SEC_ObjectIDTemplate }
03159 };
03160 
03161 const SEC_ASN1Template SEC_SetOfObjectIDTemplate[] = {
03162     { SEC_ASN1_SET_OF, 0, SEC_ObjectIDTemplate }
03163 };
03164 
03165 const SEC_ASN1Template SEC_OctetStringTemplate[] = {
03166     { SEC_ASN1_OCTET_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03167 };
03168 
03169 const SEC_ASN1Template SEC_PointerToOctetStringTemplate[] = {
03170     { SEC_ASN1_POINTER | SEC_ASN1_MAY_STREAM, 0, SEC_OctetStringTemplate }
03171 };
03172 
03173 const SEC_ASN1Template SEC_SequenceOfOctetStringTemplate[] = {
03174     { SEC_ASN1_SEQUENCE_OF, 0, SEC_OctetStringTemplate }
03175 };
03176 
03177 const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
03178     { SEC_ASN1_SET_OF, 0, SEC_OctetStringTemplate }
03179 };
03180 
03181 const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
03182     { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
03183 };
03184 
03185 const SEC_ASN1Template SEC_PointerToPrintableStringTemplate[] = {
03186     { SEC_ASN1_POINTER, 0, SEC_PrintableStringTemplate }
03187 };
03188 
03189 const SEC_ASN1Template SEC_SequenceOfPrintableStringTemplate[] = {
03190     { SEC_ASN1_SEQUENCE_OF, 0, SEC_PrintableStringTemplate }
03191 };
03192 
03193 const SEC_ASN1Template SEC_SetOfPrintableStringTemplate[] = {
03194     { SEC_ASN1_SET_OF, 0, SEC_PrintableStringTemplate }
03195 };
03196 
03197 const SEC_ASN1Template SEC_T61StringTemplate[] = {
03198     { SEC_ASN1_T61_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03199 };
03200 
03201 const SEC_ASN1Template SEC_PointerToT61StringTemplate[] = {
03202     { SEC_ASN1_POINTER, 0, SEC_T61StringTemplate }
03203 };
03204 
03205 const SEC_ASN1Template SEC_SequenceOfT61StringTemplate[] = {
03206     { SEC_ASN1_SEQUENCE_OF, 0, SEC_T61StringTemplate }
03207 };
03208 
03209 const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
03210     { SEC_ASN1_SET_OF, 0, SEC_T61StringTemplate }
03211 };
03212 
03213 const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
03214     { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
03215 };
03216 
03217 const SEC_ASN1Template SEC_PointerToUniversalStringTemplate[] = {
03218     { SEC_ASN1_POINTER, 0, SEC_UniversalStringTemplate }
03219 };
03220 
03221 const SEC_ASN1Template SEC_SequenceOfUniversalStringTemplate[] = {
03222     { SEC_ASN1_SEQUENCE_OF, 0, SEC_UniversalStringTemplate }
03223 };
03224 
03225 const SEC_ASN1Template SEC_SetOfUniversalStringTemplate[] = {
03226     { SEC_ASN1_SET_OF, 0, SEC_UniversalStringTemplate }
03227 };
03228 
03229 const SEC_ASN1Template SEC_UTCTimeTemplate[] = {
03230     { SEC_ASN1_UTC_TIME | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03231 };
03232 
03233 const SEC_ASN1Template SEC_PointerToUTCTimeTemplate[] = {
03234     { SEC_ASN1_POINTER, 0, SEC_UTCTimeTemplate }
03235 };
03236 
03237 const SEC_ASN1Template SEC_SequenceOfUTCTimeTemplate[] = {
03238     { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTCTimeTemplate }
03239 };
03240 
03241 const SEC_ASN1Template SEC_SetOfUTCTimeTemplate[] = {
03242     { SEC_ASN1_SET_OF, 0, SEC_UTCTimeTemplate }
03243 };
03244 
03245 const SEC_ASN1Template SEC_UTF8StringTemplate[] = {
03246     { SEC_ASN1_UTF8_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
03247 };
03248 
03249 const SEC_ASN1Template SEC_PointerToUTF8StringTemplate[] = {
03250     { SEC_ASN1_POINTER, 0, SEC_UTF8StringTemplate }
03251 };
03252 
03253 const SEC_ASN1Template SEC_SequenceOfUTF8StringTemplate[] = {
03254     { SEC_ASN1_SEQUENCE_OF, 0, SEC_UTF8StringTemplate }
03255 };
03256 
03257 const SEC_ASN1Template SEC_SetOfUTF8StringTemplate[] = {
03258     { SEC_ASN1_SET_OF, 0, SEC_UTF8StringTemplate }
03259 };
03260 
03261 const SEC_ASN1Template SEC_VisibleStringTemplate[] = {
03262     { SEC_ASN1_VISIBLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
03263 };
03264 
03265 const SEC_ASN1Template SEC_PointerToVisibleStringTemplate[] = {
03266     { SEC_ASN1_POINTER, 0, SEC_VisibleStringTemplate }
03267 };
03268 
03269 const SEC_ASN1Template SEC_SequenceOfVisibleStringTemplate[] = {
03270     { SEC_ASN1_SEQUENCE_OF, 0, SEC_VisibleStringTemplate }
03271 };
03272 
03273 const SEC_ASN1Template SEC_SetOfVisibleStringTemplate[] = {
03274     { SEC_ASN1_SET_OF, 0, SEC_VisibleStringTemplate }
03275 };
03276 
03277 
03278 /*
03279  * Template for skipping a subitem.
03280  *
03281  * Note that it only makes sense to use this for decoding (when you want
03282  * to decode something where you are only interested in one or two of
03283  * the fields); you cannot encode a SKIP!
03284  */
03285 const SEC_ASN1Template SEC_SkipTemplate[] = {
03286     { SEC_ASN1_SKIP }
03287 };
03288 
03289 
03290 /* These functions simply return the address of the above-declared templates.
03291 ** This is necessary for Windows DLLs.  Sigh.
03292 */
03293 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_AnyTemplate)
03294 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BMPStringTemplate)
03295 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BooleanTemplate)
03296 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_BitStringTemplate)
03297 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IA5StringTemplate)
03298 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_GeneralizedTimeTemplate)
03299 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_IntegerTemplate)
03300 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_NullTemplate)
03301 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_ObjectIDTemplate)
03302 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_OctetStringTemplate)
03303 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToAnyTemplate)
03304 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToOctetStringTemplate)
03305 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_SetOfAnyTemplate)
03306 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTCTimeTemplate)
03307 SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UTF8StringTemplate)
03308