summaryrefslogtreecommitdiff
path: root/nss/lib/util/secasn1d.c
diff options
context:
space:
mode:
authorLorry Tar Creator <lorry-tar-importer@lorry>2017-01-04 14:24:24 +0000
committerLorry Tar Creator <lorry-tar-importer@lorry>2017-01-04 14:24:24 +0000
commitdc1565216a5d20ae0d75872151523252309a1292 (patch)
treed57454ba9a40386552179eddf60d28bd1e8f3d54 /nss/lib/util/secasn1d.c
parent26c046fbc57d53136b4fb3b5e0d18298318125d4 (diff)
downloadnss-dc1565216a5d20ae0d75872151523252309a1292.tar.gz
nss-3.28.1nss-3.28.1
Diffstat (limited to 'nss/lib/util/secasn1d.c')
-rw-r--r--nss/lib/util/secasn1d.c3610
1 files changed, 1790 insertions, 1820 deletions
diff --git a/nss/lib/util/secasn1d.c b/nss/lib/util/secasn1d.c
index 7a5bcfd..797640d 100644
--- a/nss/lib/util/secasn1d.c
+++ b/nss/lib/util/secasn1d.c
@@ -14,6 +14,8 @@
#define PR_Assert sec_asn1d_Assert
#endif
+#include <limits.h>
+
#include "secasn1.h"
#include "secerr.h"
@@ -48,7 +50,7 @@ typedef enum {
} sec_asn1d_parse_place;
#ifdef DEBUG_ASN1D_STATES
-static const char * const place_names[] = {
+static const char *const place_names[] = {
"beforeIdentifier",
"duringIdentifier",
"afterIdentifier",
@@ -78,16 +80,16 @@ static const char * const place_names[] = {
"notInUse"
};
-static const char * const class_names[] = {
+static const char *const class_names[] = {
"UNIVERSAL",
"APPLICATION",
"CONTEXT_SPECIFIC",
"PRIVATE"
};
-static const char * const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
+static const char *const method_names[] = { "PRIMITIVE", "CONSTRUCTED" };
-static const char * const type_names[] = {
+static const char *const type_names[] = {
"END_OF_CONTENTS",
"BOOLEAN",
"INTEGER",
@@ -122,7 +124,8 @@ static const char * const type_names[] = {
"HIGH_TAG_VALUE"
};
-static const char * const flag_names[] = { /* flags, right to left */
+static const char *const flag_names[] = {
+ /* flags, right to left */
"OPTIONAL",
"EXPLICIT",
"ANY",
@@ -133,7 +136,7 @@ static const char * const flag_names[] = { /* flags, right to left */
"SKIP",
"INNER",
"SAVE",
- "", /* decoder ignores "MAY_STREAM", */
+ "", /* decoder ignores "MAY_STREAM", */
"SKIP_REST",
"CHOICE",
"NO_STREAM",
@@ -146,16 +149,16 @@ static const char * const flag_names[] = { /* flags, right to left */
};
static int /* bool */
-formatKind(unsigned long kind, char * buf)
+ formatKind(unsigned long kind, char *buf)
{
int i;
unsigned long k = kind & SEC_ASN1_TAGNUM_MASK;
unsigned long notag = kind & (SEC_ASN1_CHOICE | SEC_ASN1_POINTER |
- SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
+ SEC_ASN1_INLINE | SEC_ASN1_ANY | SEC_ASN1_SAVE);
buf[0] = 0;
if ((kind & SEC_ASN1_CLASS_MASK) != SEC_ASN1_UNIVERSAL) {
- sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6] );
+ sprintf(buf, " %s", class_names[(kind & SEC_ASN1_CLASS_MASK) >> 6]);
buf += strlen(buf);
}
if (kind & SEC_ASN1_METHOD_MASK) {
@@ -164,7 +167,7 @@ formatKind(unsigned long kind, char * buf)
}
if ((kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) {
if (k || !notag) {
- sprintf(buf, " %s", type_names[k] );
+ sprintf(buf, " %s", type_names[k]);
if ((k == SEC_ASN1_SET || k == SEC_ASN1_SEQUENCE) &&
(kind & SEC_ASN1_GROUP)) {
buf += strlen(buf);
@@ -196,7 +199,7 @@ typedef enum {
struct subitem {
const void *data;
- unsigned long len; /* only used for substrings */
+ unsigned long len; /* only used for substrings */
struct subitem *next;
};
@@ -205,10 +208,10 @@ typedef struct sec_asn1d_state_struct {
const SEC_ASN1Template *theTemplate;
void *dest;
- void *our_mark; /* free on completion */
+ void *our_mark; /* free on completion */
- struct sec_asn1d_state_struct *parent; /* aka prev */
- struct sec_asn1d_state_struct *child; /* aka next */
+ struct sec_asn1d_state_struct *parent; /* aka prev */
+ struct sec_asn1d_state_struct *child; /* aka next */
sec_asn1d_parse_place place;
@@ -244,26 +247,25 @@ typedef struct sec_asn1d_state_struct {
struct subitem *subitems_tail;
PRPackedBool
- allocate, /* when true, need to allocate the destination */
- endofcontents, /* this state ended up parsing end-of-contents octets */
- explicit, /* we are handling an explicit header */
- indefinite, /* the current item has indefinite-length encoding */
- missing, /* an optional field that was not present */
- optional, /* the template says this field may be omitted */
- substring; /* this is a substring of a constructed string */
+ allocate, /* when true, need to allocate the destination */
+ endofcontents, /* this state ended up parsing end-of-contents octets */
+ explicit, /* we are handling an explicit header */
+ indefinite, /* the current item has indefinite-length encoding */
+ missing, /* an optional field that was not present */
+ optional, /* the template says this field may be omitted */
+ substring; /* this is a substring of a constructed string */
} sec_asn1d_state;
-#define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
-#define LAST_TAG_NUMBER_BYTE(b) (((b) & 0x80) == 0)
-#define TAG_NUMBER_BITS 7
-#define TAG_NUMBER_MASK 0x7f
-
-#define LENGTH_IS_SHORT_FORM(b) (((b) & 0x80) == 0)
-#define LONG_FORM_LENGTH(b) ((b) & 0x7f)
+#define IS_HIGH_TAG_NUMBER(n) ((n) == SEC_ASN1_HIGH_TAG_NUMBER)
+#define LAST_TAG_NUMBER_BYTE(b) (((b)&0x80) == 0)
+#define TAG_NUMBER_BITS 7
+#define TAG_NUMBER_MASK 0x7f
-#define HIGH_BITS(field,cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
+#define LENGTH_IS_SHORT_FORM(b) (((b)&0x80) == 0)
+#define LONG_FORM_LENGTH(b) ((b)&0x7f)
+#define HIGH_BITS(field, cnt) ((field) >> ((sizeof(field) * 8) - (cnt)))
/*
* An "outsider" will have an opaque pointer to this, created by calling
@@ -272,111 +274,108 @@ typedef struct sec_asn1d_state_struct {
* SEC_ASN1DecoderFinish().
*/
struct sec_DecoderContext_struct {
- PLArenaPool *our_pool; /* for our internal allocs */
- PLArenaPool *their_pool; /* for destination structure allocs */
-#ifdef SEC_ASN1D_FREE_ON_ERROR /*
- * XXX see comment below (by same
- * ifdef) that explains why this
- * does not work (need more smarts
- * in order to free back to mark)
- */
+ PLArenaPool *our_pool; /* for our internal allocs */
+ PLArenaPool *their_pool; /* for destination structure allocs */
+#ifdef SEC_ASN1D_FREE_ON_ERROR /* \
+ * XXX see comment below (by same \
+ * ifdef) that explains why this \
+ * does not work (need more smarts \
+ * in order to free back to mark) \
+ */
/*
* XXX how to make their_mark work in the case where they do NOT
* give us a pool pointer?
*/
- void *their_mark; /* free on error */
+ void *their_mark; /* free on error */
#endif
sec_asn1d_state *current;
sec_asn1d_parse_status status;
- SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
- void *notify_arg; /* argument to notify_proc */
- PRBool during_notify; /* true during call to notify_proc */
+ SEC_ASN1NotifyProc notify_proc; /* call before/after handling field */
+ void *notify_arg; /* argument to notify_proc */
+ PRBool during_notify; /* true during call to notify_proc */
- SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */
- void *filter_arg; /* argument to that function */
- PRBool filter_only; /* do not allocate/store fields */
+ SEC_ASN1WriteProc filter_proc; /* pass field bytes to this */
+ void *filter_arg; /* argument to that function */
+ PRBool filter_only; /* do not allocate/store fields */
};
-
/*
* XXX this is a fairly generic function that may belong elsewhere
*/
static void *
-sec_asn1d_alloc (PLArenaPool *poolp, unsigned long len)
+sec_asn1d_alloc(PLArenaPool *poolp, unsigned long len)
{
void *thing;
if (poolp != NULL) {
- /*
- * Allocate from the pool.
- */
- thing = PORT_ArenaAlloc (poolp, len);
+ /*
+ * Allocate from the pool.
+ */
+ thing = PORT_ArenaAlloc(poolp, len);
} else {
- /*
- * Allocate generically.
- */
- thing = PORT_Alloc (len);
+ /*
+ * Allocate generically.
+ */
+ thing = PORT_Alloc(len);
}
return thing;
}
-
/*
* XXX this is a fairly generic function that may belong elsewhere
*/
static void *
-sec_asn1d_zalloc (PLArenaPool *poolp, unsigned long len)
+sec_asn1d_zalloc(PLArenaPool *poolp, unsigned long len)
{
void *thing;
- thing = sec_asn1d_alloc (poolp, len);
+ thing = sec_asn1d_alloc(poolp, len);
if (thing != NULL)
- PORT_Memset (thing, 0, len);
+ PORT_Memset(thing, 0, len);
return thing;
}
-
static sec_asn1d_state *
-sec_asn1d_push_state (SEC_ASN1DecoderContext *cx,
- const SEC_ASN1Template *theTemplate,
- void *dest, PRBool new_depth)
+sec_asn1d_push_state(SEC_ASN1DecoderContext *cx,
+ const SEC_ASN1Template *theTemplate,
+ void *dest, PRBool new_depth)
{
sec_asn1d_state *state, *new_state;
state = cx->current;
- PORT_Assert (state == NULL || state->child == NULL);
+ PORT_Assert(state == NULL || state->child == NULL);
if (state != NULL) {
- PORT_Assert (state->our_mark == NULL);
- state->our_mark = PORT_ArenaMark (cx->our_pool);
+ PORT_Assert(state->our_mark == NULL);
+ state->our_mark = PORT_ArenaMark(cx->our_pool);
}
- new_state = (sec_asn1d_state*)sec_asn1d_zalloc (cx->our_pool,
- sizeof(*new_state));
+ new_state = (sec_asn1d_state *)sec_asn1d_zalloc(cx->our_pool,
+ sizeof(*new_state));
if (new_state == NULL) {
- goto loser;
+ goto loser;
}
- new_state->top = cx;
- new_state->parent = state;
+ new_state->top = cx;
+ new_state->parent = state;
new_state->theTemplate = theTemplate;
- new_state->place = notInUse;
+ new_state->place = notInUse;
if (dest != NULL)
- new_state->dest = (char *)dest + theTemplate->offset;
+ new_state->dest = (char *)dest + theTemplate->offset;
if (state != NULL) {
- new_state->depth = state->depth;
- if (new_depth) {
- if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- goto loser;
- }
- }
- state->child = new_state;
+ new_state->depth = state->depth;
+ if (new_depth) {
+ if (++new_state->depth > SEC_ASN1D_MAX_DEPTH) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ goto loser;
+ }
+ }
+ state->child = new_state;
}
cx->current = new_state;
@@ -385,15 +384,14 @@ sec_asn1d_push_state (SEC_ASN1DecoderContext *cx,
loser:
cx->status = decodeError;
if (state != NULL) {
- PORT_ArenaRelease(cx->our_pool, state->our_mark);
- state->our_mark = NULL;
+ PORT_ArenaRelease(cx->our_pool, state->our_mark);
+ state->our_mark = NULL;
}
return NULL;
}
-
static void
-sec_asn1d_scrub_state (sec_asn1d_state *state)
+sec_asn1d_scrub_state(sec_asn1d_state *state)
{
/*
* Some default "scrubbing".
@@ -403,94 +401,90 @@ sec_asn1d_scrub_state (sec_asn1d_state *state)
state->endofcontents = PR_FALSE;
state->indefinite = PR_FALSE;
state->missing = PR_FALSE;
- PORT_Assert (state->consumed == 0);
+ PORT_Assert(state->consumed == 0);
}
-
static void
-sec_asn1d_notify_before (SEC_ASN1DecoderContext *cx, void *dest, int depth)
+sec_asn1d_notify_before(SEC_ASN1DecoderContext *cx, void *dest, int depth)
{
if (cx->notify_proc == NULL)
- return;
+ return;
cx->during_notify = PR_TRUE;
- (* cx->notify_proc) (cx->notify_arg, PR_TRUE, dest, depth);
+ (*cx->notify_proc)(cx->notify_arg, PR_TRUE, dest, depth);
cx->during_notify = PR_FALSE;
}
-
static void
-sec_asn1d_notify_after (SEC_ASN1DecoderContext *cx, void *dest, int depth)
+sec_asn1d_notify_after(SEC_ASN1DecoderContext *cx, void *dest, int depth)
{
if (cx->notify_proc == NULL)
- return;
+ return;
cx->during_notify = PR_TRUE;
- (* cx->notify_proc) (cx->notify_arg, PR_FALSE, dest, depth);
+ (*cx->notify_proc)(cx->notify_arg, PR_FALSE, dest, depth);
cx->during_notify = PR_FALSE;
}
-
static sec_asn1d_state *
-sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
+sec_asn1d_init_state_based_on_template(sec_asn1d_state *state)
{
PRBool explicit, optional, universal;
unsigned char expect_tag_modifiers;
unsigned long encode_kind, under_kind;
unsigned long check_tag_mask, expect_tag_number;
-
/* XXX Check that both of these tests are really needed/appropriate. */
if (state == NULL || state->top->status == decodeError)
- return state;
+ return state;
encode_kind = state->theTemplate->kind;
if (encode_kind & SEC_ASN1_SAVE) {
- /*
- * This is a "magic" field that saves away all bytes, allowing
- * the immediately following field to still be decoded from this
- * same spot -- sort of a fork.
- */
- /* check that there are no extraneous bits */
- PORT_Assert (encode_kind == SEC_ASN1_SAVE);
- if (state->top->filter_only) {
- /*
- * If we are not storing, then we do not do the SAVE field
- * at all. Just move ahead to the "real" field instead,
- * doing the appropriate notify calls before and after.
- */
- sec_asn1d_notify_after (state->top, state->dest, state->depth);
- /*
- * Since we are not storing, allow for our current dest value
- * to be NULL. (This might not actually occur, but right now I
- * cannot convince myself one way or the other.) If it is NULL,
- * assume that our parent dest can help us out.
- */
- if (state->dest == NULL)
- state->dest = state->parent->dest;
- else
- state->dest = (char *)state->dest - state->theTemplate->offset;
- state->theTemplate++;
- if (state->dest != NULL)
- state->dest = (char *)state->dest + state->theTemplate->offset;
- sec_asn1d_notify_before (state->top, state->dest, state->depth);
- encode_kind = state->theTemplate->kind;
- PORT_Assert ((encode_kind & SEC_ASN1_SAVE) == 0);
- } else {
- sec_asn1d_scrub_state (state);
- state->place = duringSaveEncoding;
- state = sec_asn1d_push_state (state->top, SEC_AnyTemplate,
- state->dest, PR_FALSE);
- if (state != NULL)
- state = sec_asn1d_init_state_based_on_template (state);
- return state;
- }
+ /*
+ * This is a "magic" field that saves away all bytes, allowing
+ * the immediately following field to still be decoded from this
+ * same spot -- sort of a fork.
+ */
+ /* check that there are no extraneous bits */
+ PORT_Assert(encode_kind == SEC_ASN1_SAVE);
+ if (state->top->filter_only) {
+ /*
+ * If we are not storing, then we do not do the SAVE field
+ * at all. Just move ahead to the "real" field instead,
+ * doing the appropriate notify calls before and after.
+ */
+ sec_asn1d_notify_after(state->top, state->dest, state->depth);
+ /*
+ * Since we are not storing, allow for our current dest value
+ * to be NULL. (This might not actually occur, but right now I
+ * cannot convince myself one way or the other.) If it is NULL,
+ * assume that our parent dest can help us out.
+ */
+ if (state->dest == NULL)
+ state->dest = state->parent->dest;
+ else
+ state->dest = (char *)state->dest - state->theTemplate->offset;
+ state->theTemplate++;
+ if (state->dest != NULL)
+ state->dest = (char *)state->dest + state->theTemplate->offset;
+ sec_asn1d_notify_before(state->top, state->dest, state->depth);
+ encode_kind = state->theTemplate->kind;
+ PORT_Assert((encode_kind & SEC_ASN1_SAVE) == 0);
+ } else {
+ sec_asn1d_scrub_state(state);
+ state->place = duringSaveEncoding;
+ state = sec_asn1d_push_state(state->top, SEC_AnyTemplate,
+ state->dest, PR_FALSE);
+ if (state != NULL)
+ state = sec_asn1d_init_state_based_on_template(state);
+ return state;
+ }
}
-
universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL)
- ? PR_TRUE : PR_FALSE;
+ ? PR_TRUE
+ : PR_FALSE;
explicit = (encode_kind & SEC_ASN1_EXPLICIT) ? PR_TRUE : PR_FALSE;
encode_kind &= ~SEC_ASN1_EXPLICIT;
@@ -498,13 +492,13 @@ sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
optional = (encode_kind & SEC_ASN1_OPTIONAL) ? PR_TRUE : PR_FALSE;
encode_kind &= ~SEC_ASN1_OPTIONAL;
- PORT_Assert (!(explicit && universal)); /* bad templates */
+ PORT_Assert(!(explicit && universal)); /* bad templates */
encode_kind &= ~SEC_ASN1_DYNAMIC;
encode_kind &= ~SEC_ASN1_MAY_STREAM;
if (encode_kind & SEC_ASN1_CHOICE) {
-#if 0 /* XXX remove? */
+#if 0 /* XXX remove? */
sec_asn1d_state *child = sec_asn1d_push_state(state->top, state->theTemplate, state->dest, PR_FALSE);
if ((sec_asn1d_state *)NULL == child) {
return (sec_asn1d_state *)NULL;
@@ -514,169 +508,164 @@ sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
child->place = beforeChoice;
return child;
#else
- state->place = beforeChoice;
- return state;
+ state->place = beforeChoice;
+ return state;
#endif
}
- if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal
- && !explicit)) {
- const SEC_ASN1Template *subt;
- void *dest;
- PRBool child_allocate;
-
- PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
-
- sec_asn1d_scrub_state (state);
- child_allocate = PR_FALSE;
-
- if (encode_kind & SEC_ASN1_POINTER) {
- /*
- * A POINTER means we need to allocate the destination for
- * this field. But, since it may also be an optional field,
- * we defer the allocation until later; we just record that
- * it needs to be done.
- *
- * There are two possible scenarios here -- one is just a
- * plain POINTER (kind of like INLINE, except with allocation)
- * and the other is an implicitly-tagged POINTER. We don't
- * need to do anything special here for the two cases, but
- * since the template definition can be tricky, we do check
- * that there are no extraneous bits set in encode_kind.
- *
- * XXX The same conditions which assert should set an error.
- */
- if (universal) {
- /*
- * "universal" means this entry is a standalone POINTER;
- * there should be no other bits set in encode_kind.
- */
- PORT_Assert (encode_kind == SEC_ASN1_POINTER);
- } else {
- /*
- * If we get here we have an implicitly-tagged field
- * that needs to be put into a POINTER. The subtemplate
- * will determine how to decode the field, but encode_kind
- * describes the (implicit) tag we are looking for.
- * The non-tag bits of encode_kind will be ignored by
- * the code below; none of them should be set, however,
- * except for the POINTER bit itself -- so check that.
- */
- PORT_Assert ((encode_kind & ~SEC_ASN1_TAG_MASK)
- == SEC_ASN1_POINTER);
- }
- if (!state->top->filter_only)
- child_allocate = PR_TRUE;
- dest = NULL;
- state->place = afterPointer;
- } else {
- dest = state->dest;
- if (encode_kind & SEC_ASN1_INLINE) {
- /* check that there are no extraneous bits */
- PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional);
- state->place = afterInline;
- } else {
- state->place = afterImplicit;
- }
- }
-
- state->optional = optional;
- subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest, PR_FALSE);
- state = sec_asn1d_push_state (state->top, subt, dest, PR_FALSE);
- if (state == NULL)
- return NULL;
-
- state->allocate = child_allocate;
-
- if (universal) {
- state = sec_asn1d_init_state_based_on_template (state);
- if (state != NULL) {
- /*
- * If this field is optional, we need to record that on
- * the pushed child so it won't fail if the field isn't
- * found. I can't think of a way that this new state
- * could already have optional set (which we would wipe
- * out below if our local optional is not set) -- but
- * just to be sure, assert that it isn't set.
- */
- PORT_Assert (!state->optional);
- state->optional = optional;
- }
- return state;
- }
-
- under_kind = state->theTemplate->kind;
- under_kind &= ~SEC_ASN1_MAY_STREAM;
+ if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal && !explicit)) {
+ const SEC_ASN1Template *subt;
+ void *dest;
+ PRBool child_allocate;
+
+ PORT_Assert((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0);
+
+ sec_asn1d_scrub_state(state);
+ child_allocate = PR_FALSE;
+
+ if (encode_kind & SEC_ASN1_POINTER) {
+ /*
+ * A POINTER means we need to allocate the destination for
+ * this field. But, since it may also be an optional field,
+ * we defer the allocation until later; we just record that
+ * it needs to be done.
+ *
+ * There are two possible scenarios here -- one is just a
+ * plain POINTER (kind of like INLINE, except with allocation)
+ * and the other is an implicitly-tagged POINTER. We don't
+ * need to do anything special here for the two cases, but
+ * since the template definition can be tricky, we do check
+ * that there are no extraneous bits set in encode_kind.
+ *
+ * XXX The same conditions which assert should set an error.
+ */
+ if (universal) {
+ /*
+ * "universal" means this entry is a standalone POINTER;
+ * there should be no other bits set in encode_kind.
+ */
+ PORT_Assert(encode_kind == SEC_ASN1_POINTER);
+ } else {
+ /*
+ * If we get here we have an implicitly-tagged field
+ * that needs to be put into a POINTER. The subtemplate
+ * will determine how to decode the field, but encode_kind
+ * describes the (implicit) tag we are looking for.
+ * The non-tag bits of encode_kind will be ignored by
+ * the code below; none of them should be set, however,
+ * except for the POINTER bit itself -- so check that.
+ */
+ PORT_Assert((encode_kind & ~SEC_ASN1_TAG_MASK) == SEC_ASN1_POINTER);
+ }
+ if (!state->top->filter_only)
+ child_allocate = PR_TRUE;
+ dest = NULL;
+ state->place = afterPointer;
+ } else {
+ dest = state->dest;
+ if (encode_kind & SEC_ASN1_INLINE) {
+ /* check that there are no extraneous bits */
+ PORT_Assert(encode_kind == SEC_ASN1_INLINE && !optional);
+ state->place = afterInline;
+ } else {
+ state->place = afterImplicit;
+ }
+ }
+
+ state->optional = optional;
+ subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->dest, PR_FALSE);
+ state = sec_asn1d_push_state(state->top, subt, dest, PR_FALSE);
+ if (state == NULL)
+ return NULL;
+
+ state->allocate = child_allocate;
+
+ if (universal) {
+ state = sec_asn1d_init_state_based_on_template(state);
+ if (state != NULL) {
+ /*
+ * If this field is optional, we need to record that on
+ * the pushed child so it won't fail if the field isn't
+ * found. I can't think of a way that this new state
+ * could already have optional set (which we would wipe
+ * out below if our local optional is not set) -- but
+ * just to be sure, assert that it isn't set.
+ */
+ PORT_Assert(!state->optional);
+ state->optional = optional;
+ }
+ return state;
+ }
+
+ under_kind = state->theTemplate->kind;
+ under_kind &= ~SEC_ASN1_MAY_STREAM;
} else if (explicit) {
- /*
- * For explicit, we only need to match the encoding tag next,
- * then we will push another state to handle the entire inner
- * part. In this case, there is no underlying kind which plays
- * any part in the determination of the outer, explicit tag.
- * So we just set under_kind to 0, which is not a valid tag,
- * and the rest of the tag matching stuff should be okay.
- */
- under_kind = 0;
+ /*
+ * For explicit, we only need to match the encoding tag next,
+ * then we will push another state to handle the entire inner
+ * part. In this case, there is no underlying kind which plays
+ * any part in the determination of the outer, explicit tag.
+ * So we just set under_kind to 0, which is not a valid tag,
+ * and the rest of the tag matching stuff should be okay.
+ */
+ under_kind = 0;
} else {
- /*
- * Nothing special; the underlying kind and the given encoding
- * information are the same.
- */
- under_kind = encode_kind;
+ /*
+ * Nothing special; the underlying kind and the given encoding
+ * information are the same.
+ */
+ under_kind = encode_kind;
}
/* XXX is this the right set of bits to test here? */
- PORT_Assert ((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL
- | SEC_ASN1_MAY_STREAM
- | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
+ PORT_Assert((under_kind & (SEC_ASN1_EXPLICIT | SEC_ASN1_OPTIONAL | SEC_ASN1_MAY_STREAM | SEC_ASN1_INLINE | SEC_ASN1_POINTER)) == 0);
if (encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) {
- PORT_Assert (encode_kind == under_kind);
- if (encode_kind & SEC_ASN1_SKIP) {
- PORT_Assert (!optional);
- PORT_Assert (encode_kind == SEC_ASN1_SKIP);
- state->dest = NULL;
- }
- check_tag_mask = 0;
- expect_tag_modifiers = 0;
- expect_tag_number = 0;
+ PORT_Assert(encode_kind == under_kind);
+ if (encode_kind & SEC_ASN1_SKIP) {
+ PORT_Assert(!optional);
+ PORT_Assert(encode_kind == SEC_ASN1_SKIP);
+ state->dest = NULL;
+ }
+ check_tag_mask = 0;
+ expect_tag_modifiers = 0;
+ expect_tag_number = 0;
} else {
- check_tag_mask = SEC_ASN1_TAG_MASK;
- expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK
- & ~SEC_ASN1_TAGNUM_MASK;
- /*
- * XXX This assumes only single-octet identifiers. To handle
- * the HIGH TAG form we would need to do some more work, especially
- * in how to specify them in the template, because right now we
- * do not provide a way to specify more *tag* bits in encode_kind.
- */
- expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
-
- switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
- case SEC_ASN1_SET:
- /*
- * XXX A plain old SET (as opposed to a SET OF) is not implemented.
- * If it ever is, remove this assert...
- */
- PORT_Assert ((under_kind & SEC_ASN1_GROUP) != 0);
- /* fallthru */
- case SEC_ASN1_SEQUENCE:
- expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
- break;
- case SEC_ASN1_BIT_STRING:
- case SEC_ASN1_BMP_STRING:
- case SEC_ASN1_GENERALIZED_TIME:
- case SEC_ASN1_IA5_STRING:
- case SEC_ASN1_OCTET_STRING:
- case SEC_ASN1_PRINTABLE_STRING:
- case SEC_ASN1_T61_STRING:
- case SEC_ASN1_UNIVERSAL_STRING:
- case SEC_ASN1_UTC_TIME:
- case SEC_ASN1_UTF8_STRING:
- case SEC_ASN1_VISIBLE_STRING:
- check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
- break;
- }
+ check_tag_mask = SEC_ASN1_TAG_MASK;
+ expect_tag_modifiers = (unsigned char)encode_kind & SEC_ASN1_TAG_MASK & ~SEC_ASN1_TAGNUM_MASK;
+ /*
+ * XXX This assumes only single-octet identifiers. To handle
+ * the HIGH TAG form we would need to do some more work, especially
+ * in how to specify them in the template, because right now we
+ * do not provide a way to specify more *tag* bits in encode_kind.
+ */
+ expect_tag_number = encode_kind & SEC_ASN1_TAGNUM_MASK;
+
+ switch (under_kind & SEC_ASN1_TAGNUM_MASK) {
+ case SEC_ASN1_SET:
+ /*
+ * XXX A plain old SET (as opposed to a SET OF) is not implemented.
+ * If it ever is, remove this assert...
+ */
+ PORT_Assert((under_kind & SEC_ASN1_GROUP) != 0);
+ /* fallthru */
+ case SEC_ASN1_SEQUENCE:
+ expect_tag_modifiers |= SEC_ASN1_CONSTRUCTED;
+ break;
+ case SEC_ASN1_BIT_STRING:
+ case SEC_ASN1_BMP_STRING:
+ case SEC_ASN1_GENERALIZED_TIME:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_T61_STRING:
+ case SEC_ASN1_UNIVERSAL_STRING:
+ case SEC_ASN1_UTC_TIME:
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ check_tag_mask &= ~SEC_ASN1_CONSTRUCTED;
+ break;
+ }
}
state->check_tag_mask = check_tag_mask;
@@ -686,7 +675,7 @@ sec_asn1d_init_state_based_on_template (sec_asn1d_state *state)
state->explicit = explicit;
state->optional = optional;
- sec_asn1d_scrub_state (state);
+ sec_asn1d_scrub_state(state);
return state;
}
@@ -695,19 +684,19 @@ static sec_asn1d_state *
sec_asn1d_get_enclosing_construct(sec_asn1d_state *state)
{
for (state = state->parent; state; state = state->parent) {
- sec_asn1d_parse_place place = state->place;
- if (place != afterImplicit &&
- place != afterPointer &&
- place != afterInline &&
- place != afterSaveEncoding &&
- place != duringSaveEncoding &&
- place != duringChoice) {
+ sec_asn1d_parse_place place = state->place;
+ if (place != afterImplicit &&
+ place != afterPointer &&
+ place != afterInline &&
+ place != afterSaveEncoding &&
+ place != duringSaveEncoding &&
+ place != duringChoice) {
/* we've walked up the stack to a state that represents
- ** the enclosing construct.
- */
+ ** the enclosing construct.
+ */
break;
- }
+ }
}
return state;
}
@@ -718,32 +707,32 @@ sec_asn1d_parent_allows_EOC(sec_asn1d_state *state)
/* get state of enclosing construct. */
state = sec_asn1d_get_enclosing_construct(state);
if (state) {
- sec_asn1d_parse_place place = state->place;
+ sec_asn1d_parse_place place = state->place;
/* Is it one of the types that permits an unexpected EOC? */
- int eoc_permitted =
- (place == duringGroup ||
- place == duringConstructedString ||
- state->child->optional);
- return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
+ int eoc_permitted =
+ (place == duringGroup ||
+ place == duringConstructedString ||
+ state->child->optional);
+ return (state->indefinite && eoc_permitted) ? PR_TRUE : PR_FALSE;
}
return PR_FALSE;
}
static unsigned long
-sec_asn1d_parse_identifier (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_identifier(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
unsigned char byte;
unsigned char tag_number;
- PORT_Assert (state->place == beforeIdentifier);
+ PORT_Assert(state->place == beforeIdentifier);
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
- byte = (unsigned char) *buf;
+ byte = (unsigned char)*buf;
#ifdef DEBUG_ASN1D_STATES
{
char kindBuf[256];
@@ -753,128 +742,122 @@ sec_asn1d_parse_identifier (sec_asn1d_state *state,
#endif
tag_number = byte & SEC_ASN1_TAGNUM_MASK;
- if (IS_HIGH_TAG_NUMBER (tag_number)) {
- state->place = duringIdentifier;
- state->found_tag_number = 0;
- /*
- * Actually, we have no idea how many bytes are pending, but we
- * do know that it is at least 1. That is all we know; we have
- * to look at each byte to know if there is another, etc.
- */
- state->pending = 1;
+ if (IS_HIGH_TAG_NUMBER(tag_number)) {
+ state->place = duringIdentifier;
+ state->found_tag_number = 0;
+ /*
+ * Actually, we have no idea how many bytes are pending, but we
+ * do know that it is at least 1. That is all we know; we have
+ * to look at each byte to know if there is another, etc.
+ */
+ state->pending = 1;
} else {
- if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
- /*
- * Our parent has indefinite-length encoding, and the
- * entire tag found is 0, so it seems that we have hit the
- * end-of-contents octets. To handle this, we just change
- * our state to that which expects to get the bytes of the
- * end-of-contents octets and let that code re-read this byte
- * so that our categorization of field types is correct.
- * After that, our parent will then deal with everything else.
- */
- state->place = duringEndOfContents;
- state->pending = 2;
- state->found_tag_number = 0;
- state->found_tag_modifiers = 0;
- /*
- * We might be an optional field that is, as we now find out,
- * missing. Give our parent a clue that this happened.
- */
- if (state->optional)
- state->missing = PR_TRUE;
- return 0;
- }
- state->place = afterIdentifier;
- state->found_tag_number = tag_number;
+ if (byte == 0 && sec_asn1d_parent_allows_EOC(state)) {
+ /*
+ * Our parent has indefinite-length encoding, and the
+ * entire tag found is 0, so it seems that we have hit the
+ * end-of-contents octets. To handle this, we just change
+ * our state to that which expects to get the bytes of the
+ * end-of-contents octets and let that code re-read this byte
+ * so that our categorization of field types is correct.
+ * After that, our parent will then deal with everything else.
+ */
+ state->place = duringEndOfContents;
+ state->pending = 2;
+ state->found_tag_number = 0;
+ state->found_tag_modifiers = 0;
+ /*
+ * We might be an optional field that is, as we now find out,
+ * missing. Give our parent a clue that this happened.
+ */
+ if (state->optional)
+ state->missing = PR_TRUE;
+ return 0;
+ }
+ state->place = afterIdentifier;
+ state->found_tag_number = tag_number;
}
state->found_tag_modifiers = byte & ~SEC_ASN1_TAGNUM_MASK;
return 1;
}
-
static unsigned long
-sec_asn1d_parse_more_identifier (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_more_identifier(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
unsigned char byte;
int count;
- PORT_Assert (state->pending == 1);
- PORT_Assert (state->place == duringIdentifier);
+ PORT_Assert(state->pending == 1);
+ PORT_Assert(state->place == duringIdentifier);
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
count = 0;
while (len && state->pending) {
- if (HIGH_BITS (state->found_tag_number, TAG_NUMBER_BITS) != 0) {
- /*
- * The given high tag number overflows our container;
- * just give up. This is not likely to *ever* happen.
- */
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return 0;
- }
+ if (HIGH_BITS(state->found_tag_number, TAG_NUMBER_BITS) != 0) {
+ /*
+ * The given high tag number overflows our container;
+ * just give up. This is not likely to *ever* happen.
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
- state->found_tag_number <<= TAG_NUMBER_BITS;
+ state->found_tag_number <<= TAG_NUMBER_BITS;
- byte = (unsigned char) buf[count++];
- state->found_tag_number |= (byte & TAG_NUMBER_MASK);
+ byte = (unsigned char)buf[count++];
+ state->found_tag_number |= (byte & TAG_NUMBER_MASK);
- len--;
- if (LAST_TAG_NUMBER_BYTE (byte))
- state->pending = 0;
+ len--;
+ if (LAST_TAG_NUMBER_BYTE(byte))
+ state->pending = 0;
}
if (state->pending == 0)
- state->place = afterIdentifier;
+ state->place = afterIdentifier;
return count;
}
-
static void
-sec_asn1d_confirm_identifier (sec_asn1d_state *state)
+sec_asn1d_confirm_identifier(sec_asn1d_state *state)
{
PRBool match;
- PORT_Assert (state->place == afterIdentifier);
+ PORT_Assert(state->place == afterIdentifier);
- match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask)
- == state->expect_tag_modifiers)
- && ((state->found_tag_number & state->check_tag_mask)
- == state->expect_tag_number));
+ match = (PRBool)(((state->found_tag_modifiers & state->check_tag_mask) == state->expect_tag_modifiers) && ((state->found_tag_number & state->check_tag_mask) == state->expect_tag_number));
if (match) {
- state->place = beforeLength;
+ state->place = beforeLength;
} else {
- if (state->optional) {
- state->missing = PR_TRUE;
- state->place = afterEndOfContents;
- } else {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- }
+ if (state->optional) {
+ state->missing = PR_TRUE;
+ state->place = afterEndOfContents;
+ } else {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ }
}
}
-
static unsigned long
-sec_asn1d_parse_length (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_length(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
unsigned char byte;
- PORT_Assert (state->place == beforeLength);
+ PORT_Assert(state->place == beforeLength);
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
/*
@@ -882,71 +865,70 @@ sec_asn1d_parse_length (sec_asn1d_state *state,
*/
state->place = afterLength;
- byte = (unsigned char) *buf;
+ byte = (unsigned char)*buf;
- if (LENGTH_IS_SHORT_FORM (byte)) {
- state->contents_length = byte;
+ if (LENGTH_IS_SHORT_FORM(byte)) {
+ state->contents_length = byte;
} else {
- state->contents_length = 0;
- state->pending = LONG_FORM_LENGTH (byte);
- if (state->pending == 0) {
- state->indefinite = PR_TRUE;
- } else {
- state->place = duringLength;
- }
+ state->contents_length = 0;
+ state->pending = LONG_FORM_LENGTH(byte);
+ if (state->pending == 0) {
+ state->indefinite = PR_TRUE;
+ } else {
+ state->place = duringLength;
+ }
}
- /* If we're parsing an ANY, SKIP, or SAVE template, and
- ** the object being saved is definite length encoded and constructed,
+ /* If we're parsing an ANY, SKIP, or SAVE template, and
+ ** the object being saved is definite length encoded and constructed,
** there's no point in decoding that construct's members.
** So, just forget it's constructed and treat it as primitive.
** (SAVE appears as an ANY at this point)
*/
if (!state->indefinite &&
- (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
- state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
+ (state->underlying_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP))) {
+ state->found_tag_modifiers &= ~SEC_ASN1_CONSTRUCTED;
}
return 1;
}
-
static unsigned long
-sec_asn1d_parse_more_length (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_more_length(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
int count;
- PORT_Assert (state->pending > 0);
- PORT_Assert (state->place == duringLength);
+ PORT_Assert(state->pending > 0);
+ PORT_Assert(state->place == duringLength);
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
count = 0;
while (len && state->pending) {
- if (HIGH_BITS (state->contents_length, 9) != 0) {
- /*
- * The given full content length overflows our container;
- * just give up.
- */
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return 0;
- }
+ if (HIGH_BITS(state->contents_length, 9) != 0) {
+ /*
+ * The given full content length overflows our container;
+ * just give up.
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
- state->contents_length <<= 8;
- state->contents_length |= (unsigned char) buf[count++];
+ state->contents_length <<= 8;
+ state->contents_length |= (unsigned char)buf[count++];
- len--;
- state->pending--;
+ len--;
+ state->pending--;
}
if (state->pending == 0)
- state->place = afterLength;
+ state->place = afterLength;
return count;
}
@@ -959,19 +941,19 @@ sec_asn1d_parse_more_length (sec_asn1d_state *state,
* decoding error in the given SEC_ASN1DecoderContext, and returns PR_FALSE.
*/
static PRBool
-sec_asn1d_check_and_subtract_length (unsigned long *remaining,
- unsigned long consumed,
- SEC_ASN1DecoderContext *cx)
+sec_asn1d_check_and_subtract_length(unsigned long *remaining,
+ unsigned long consumed,
+ SEC_ASN1DecoderContext *cx)
{
PORT_Assert(remaining);
PORT_Assert(cx);
if (!remaining || !cx) {
- PORT_SetError (SEC_ERROR_INVALID_ARGS);
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
cx->status = decodeError;
return PR_FALSE;
}
if (*remaining < consumed) {
- PORT_SetError (SEC_ERROR_BAD_DER);
+ PORT_SetError(SEC_ERROR_BAD_DER);
cx->status = decodeError;
return PR_FALSE;
}
@@ -980,7 +962,7 @@ sec_asn1d_check_and_subtract_length (unsigned long *remaining,
}
static void
-sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
+sec_asn1d_prepare_for_contents(sec_asn1d_state *state)
{
SECItem *item;
PLArenaPool *poolp;
@@ -1034,15 +1016,14 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
parent = state;
do {
if (!sec_asn1d_check_and_subtract_length(
- &remaining, parent->consumed, state->top) ||
+ &remaining, parent->consumed, state->top) ||
/* If parent->indefinite is true, parent->contents_length is
* zero and this is a no-op. */
!sec_asn1d_check_and_subtract_length(
- &remaining, parent->contents_length, state->top) ||
+ &remaining, parent->contents_length, state->top) ||
/* If parent->indefinite is true, then ensure there is enough
* space for an EOC tag of 2 bytes. */
- (parent->indefinite && !sec_asn1d_check_and_subtract_length(
- &remaining, 2, state->top))) {
+ (parent->indefinite && !sec_asn1d_check_and_subtract_length(&remaining, 2, state->top))) {
/* This element is larger than its enclosing element, which is
* invalid. */
return;
@@ -1056,34 +1037,34 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
* where state->endofcontents is true -- figure it out!
*/
if (state->allocate) {
- void *dest;
-
- PORT_Assert (state->dest == NULL);
- /*
- * We are handling a POINTER or a member of a GROUP, and need to
- * allocate for the data structure.
- */
- dest = sec_asn1d_zalloc (state->top->their_pool,
- state->theTemplate->size);
- if (dest == NULL) {
- state->top->status = decodeError;
- return;
- }
- state->dest = (char *)dest + state->theTemplate->offset;
-
- /*
- * For a member of a GROUP, our parent will later put the
- * pointer wherever it belongs. But for a POINTER, we need
- * to record the destination now, in case notify or filter
- * procs need access to it -- they cannot find it otherwise,
- * until it is too late (for one-pass processing).
- */
- if (state->parent->place == afterPointer) {
- void **placep;
-
- placep = state->parent->dest;
- *placep = dest;
- }
+ void *dest;
+
+ PORT_Assert(state->dest == NULL);
+ /*
+ * We are handling a POINTER or a member of a GROUP, and need to
+ * allocate for the data structure.
+ */
+ dest = sec_asn1d_zalloc(state->top->their_pool,
+ state->theTemplate->size);
+ if (dest == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+ state->dest = (char *)dest + state->theTemplate->offset;
+
+ /*
+ * For a member of a GROUP, our parent will later put the
+ * pointer wherever it belongs. But for a POINTER, we need
+ * to record the destination now, in case notify or filter
+ * procs need access to it -- they cannot find it otherwise,
+ * until it is too late (for one-pass processing).
+ */
+ if (state->parent->place == afterPointer) {
+ void **placep;
+
+ placep = state->parent->dest;
+ *placep = dest;
+ }
}
/*
@@ -1098,15 +1079,16 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
* header and its contents.
*/
if (state->explicit) {
- state->place = afterExplicit;
- state = sec_asn1d_push_state (state->top,
- SEC_ASN1GetSubtemplate(state->theTemplate,
- state->dest,
- PR_FALSE),
- state->dest, PR_TRUE);
- if (state != NULL)
- state = sec_asn1d_init_state_based_on_template (state);
- return;
+ state->place = afterExplicit;
+ state = sec_asn1d_push_state(state->top,
+ SEC_ASN1GetSubtemplate(state->theTemplate,
+ state->dest,
+ PR_FALSE),
+ state->dest, PR_TRUE);
+ if (state != NULL) {
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ return;
}
/*
@@ -1117,367 +1099,361 @@ sec_asn1d_prepare_for_contents (sec_asn1d_state *state)
* at the end.
*/
if (state->underlying_kind & SEC_ASN1_GROUP) {
- /* XXX If this assertion holds (should be able to confirm it via
- * inspection, too) then move this code into the switch statement
- * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
- */
- PORT_Assert (state->underlying_kind == SEC_ASN1_SET_OF
- || state->underlying_kind == SEC_ASN1_SEQUENCE_OF
- || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
- || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF|SEC_ASN1_DYNAMIC)
- );
- if (state->contents_length != 0 || state->indefinite) {
- const SEC_ASN1Template *subt;
-
- state->place = duringGroup;
- subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->dest,
- PR_FALSE);
- state = sec_asn1d_push_state (state->top, subt, NULL, PR_TRUE);
- if (state != NULL) {
- if (!state->top->filter_only)
- state->allocate = PR_TRUE; /* XXX propogate this? */
- /*
- * Do the "before" field notification for next in group.
- */
- sec_asn1d_notify_before (state->top, state->dest, state->depth);
- state = sec_asn1d_init_state_based_on_template (state);
- }
- } else {
- /*
- * A group of zero; we are done.
- * Set state to afterGroup and let that code plant the NULL.
- */
- state->place = afterGroup;
- }
- return;
+ /* XXX If this assertion holds (should be able to confirm it via
+ * inspection, too) then move this code into the switch statement
+ * below under cases SET_OF and SEQUENCE_OF; it will be cleaner.
+ */
+ PORT_Assert(state->underlying_kind == SEC_ASN1_SET_OF || state->underlying_kind == SEC_ASN1_SEQUENCE_OF || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC) || state->underlying_kind == (SEC_ASN1_SEQUENCE_OF | SEC_ASN1_DYNAMIC));
+ if (state->contents_length != 0 || state->indefinite) {
+ const SEC_ASN1Template *subt;
+
+ state->place = duringGroup;
+ subt = SEC_ASN1GetSubtemplate(state->theTemplate, state->dest,
+ PR_FALSE);
+ state = sec_asn1d_push_state(state->top, subt, NULL, PR_TRUE);
+ if (state != NULL) {
+ if (!state->top->filter_only)
+ state->allocate = PR_TRUE; /* XXX propogate this? */
+ /*
+ * Do the "before" field notification for next in group.
+ */
+ sec_asn1d_notify_before(state->top, state->dest, state->depth);
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ } else {
+ /*
+ * A group of zero; we are done.
+ * Set state to afterGroup and let that code plant the NULL.
+ */
+ state->place = afterGroup;
+ }
+ return;
}
switch (state->underlying_kind) {
- case SEC_ASN1_SEQUENCE:
- /*
- * We need to push a child to handle the individual fields.
- */
- state->place = duringSequence;
- state = sec_asn1d_push_state (state->top, state->theTemplate + 1,
- state->dest, PR_TRUE);
- if (state != NULL) {
- /*
- * Do the "before" field notification.
- */
- sec_asn1d_notify_before (state->top, state->dest, state->depth);
- state = sec_asn1d_init_state_based_on_template (state);
- }
- break;
-
- case SEC_ASN1_SET: /* XXX SET is not really implemented */
- /*
- * XXX A plain SET requires special handling; scanning of a
- * template to see where a field should go (because by definition,
- * they are not in any particular order, and you have to look at
- * each tag to disambiguate what the field is). We may never
- * implement this because in practice, it seems to be unused.
- */
- PORT_Assert(0);
- PORT_SetError (SEC_ERROR_BAD_DER); /* XXX */
- state->top->status = decodeError;
- break;
-
- case SEC_ASN1_NULL:
- /*
- * The NULL type, by definition, is "nothing", content length of zero.
- * An indefinite-length encoding is not alloweed.
- */
- if (state->contents_length || state->indefinite) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- break;
- }
- if (state->dest != NULL) {
- item = (SECItem *)(state->dest);
- item->data = NULL;
- item->len = 0;
- }
- state->place = afterEndOfContents;
- break;
-
- case SEC_ASN1_BMP_STRING:
- /* Error if length is not divisable by 2 */
- if (state->contents_length % 2) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- break;
- }
- /* otherwise, handle as other string types */
- goto regular_string_type;
-
- case SEC_ASN1_UNIVERSAL_STRING:
- /* Error if length is not divisable by 4 */
- if (state->contents_length % 4) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- break;
- }
- /* otherwise, handle as other string types */
- goto regular_string_type;
-
- case SEC_ASN1_SKIP:
- case SEC_ASN1_ANY:
- case SEC_ASN1_ANY_CONTENTS:
- /*
- * These are not (necessarily) strings, but they need nearly
- * identical handling (especially when we need to deal with
- * constructed sub-pieces), so we pretend they are.
- */
- /* fallthru */
-regular_string_type:
- case SEC_ASN1_BIT_STRING:
- case SEC_ASN1_IA5_STRING:
- case SEC_ASN1_OCTET_STRING:
- case SEC_ASN1_PRINTABLE_STRING:
- case SEC_ASN1_T61_STRING:
- case SEC_ASN1_UTC_TIME:
- case SEC_ASN1_UTF8_STRING:
- case SEC_ASN1_VISIBLE_STRING:
- /*
- * We are allocating for a primitive or a constructed string.
- * If it is a constructed string, it may also be indefinite-length.
- * If it is primitive, the length can (legally) be zero.
- * Our first order of business is to allocate the memory for
- * the string, if we can (if we know the length).
- */
- item = (SECItem *)(state->dest);
-
- /*
- * If the item is a definite-length constructed string, then
- * the contents_length is actually larger than what we need
- * (because it also counts each intermediate header which we
- * will be throwing away as we go), but it is a perfectly good
- * upper bound that we just allocate anyway, and then concat
- * as we go; we end up wasting a few extra bytes but save a
- * whole other copy.
- */
- alloc_len = state->contents_length;
- poolp = NULL; /* quiet compiler warnings about unused... */
-
- if (item == NULL || state->top->filter_only) {
- if (item != NULL) {
- item->data = NULL;
- item->len = 0;
- }
- alloc_len = 0;
- } else if (state->substring) {
- /*
- * If we are a substring of a constructed string, then we may
- * not have to allocate anything (because our parent, the
- * actual constructed string, did it for us). If we are a
- * substring and we *do* have to allocate, that means our
- * parent is an indefinite-length, so we allocate from our pool;
- * later our parent will copy our string into the aggregated
- * whole and free our pool allocation.
- */
- if (item->data == NULL) {
- PORT_Assert (item->len == 0);
- poolp = state->top->our_pool;
- } else {
- alloc_len = 0;
- }
- } else {
- item->len = 0;
- item->data = NULL;
- poolp = state->top->their_pool;
- }
-
- if (alloc_len || ((! state->indefinite)
- && (state->subitems_head != NULL))) {
- struct subitem *subitem;
- int len;
-
- PORT_Assert (item);
- if (!item) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
- PORT_Assert (item->len == 0 && item->data == NULL);
- /*
- * Check for and handle an ANY which has stashed aside the
- * header (identifier and length) bytes for us to include
- * in the saved contents.
- */
- if (state->subitems_head != NULL) {
- PORT_Assert (state->underlying_kind == SEC_ASN1_ANY);
- for (subitem = state->subitems_head;
- subitem != NULL; subitem = subitem->next)
- alloc_len += subitem->len;
- }
-
- item->data = (unsigned char*)sec_asn1d_zalloc (poolp, alloc_len);
- if (item->data == NULL) {
- state->top->status = decodeError;
- break;
- }
-
- len = 0;
- for (subitem = state->subitems_head;
- subitem != NULL; subitem = subitem->next) {
- PORT_Memcpy (item->data + len, subitem->data, subitem->len);
- len += subitem->len;
- }
- item->len = len;
-
- /*
- * Because we use arenas and have a mark set, we later free
- * everything we have allocated, so this does *not* present
- * a memory leak (it is just temporarily left dangling).
- */
- state->subitems_head = state->subitems_tail = NULL;
- }
-
- if (state->contents_length == 0 && (! state->indefinite)) {
- /*
- * A zero-length simple or constructed string; we are done.
- */
- state->place = afterEndOfContents;
- } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
- const SEC_ASN1Template *sub;
-
- switch (state->underlying_kind) {
- case SEC_ASN1_ANY:
- case SEC_ASN1_ANY_CONTENTS:
- sub = SEC_AnyTemplate;
- break;
- case SEC_ASN1_BIT_STRING:
- sub = SEC_BitStringTemplate;
- break;
- case SEC_ASN1_BMP_STRING:
- sub = SEC_BMPStringTemplate;
- break;
- case SEC_ASN1_GENERALIZED_TIME:
- sub = SEC_GeneralizedTimeTemplate;
- break;
- case SEC_ASN1_IA5_STRING:
- sub = SEC_IA5StringTemplate;
- break;
- case SEC_ASN1_OCTET_STRING:
- sub = SEC_OctetStringTemplate;
- break;
- case SEC_ASN1_PRINTABLE_STRING:
- sub = SEC_PrintableStringTemplate;
- break;
- case SEC_ASN1_T61_STRING:
- sub = SEC_T61StringTemplate;
- break;
- case SEC_ASN1_UNIVERSAL_STRING:
- sub = SEC_UniversalStringTemplate;
- break;
- case SEC_ASN1_UTC_TIME:
- sub = SEC_UTCTimeTemplate;
- break;
- case SEC_ASN1_UTF8_STRING:
- sub = SEC_UTF8StringTemplate;
- break;
- case SEC_ASN1_VISIBLE_STRING:
- sub = SEC_VisibleStringTemplate;
- break;
- case SEC_ASN1_SKIP:
- sub = SEC_SkipTemplate;
- break;
- default: /* redundant given outer switch cases, but */
- PORT_Assert(0); /* the compiler does not seem to know that, */
- sub = NULL; /* so just do enough to quiet it. */
- break;
- }
-
- state->place = duringConstructedString;
- state = sec_asn1d_push_state (state->top, sub, item, PR_TRUE);
- if (state != NULL) {
- state->substring = PR_TRUE; /* XXX propogate? */
- state = sec_asn1d_init_state_based_on_template (state);
- }
- } else if (state->indefinite) {
- /*
- * An indefinite-length string *must* be constructed!
- */
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- } else {
- /*
- * A non-zero-length simple string.
- */
- if (state->underlying_kind == SEC_ASN1_BIT_STRING)
- state->place = beforeBitString;
- else
- state->place = duringLeaf;
- }
- break;
-
- default:
- /*
- * We are allocating for a simple leaf item.
- */
- if (state->contents_length) {
- if (state->dest != NULL) {
- item = (SECItem *)(state->dest);
- item->len = 0;
- if (state->top->filter_only) {
- item->data = NULL;
- } else {
- item->data = (unsigned char*)
- sec_asn1d_zalloc (state->top->their_pool,
- state->contents_length);
- if (item->data == NULL) {
- state->top->status = decodeError;
- return;
- }
- }
- }
- state->place = duringLeaf;
- } else {
- /*
- * An indefinite-length or zero-length item is not allowed.
- * (All legal cases of such were handled above.)
- */
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- }
+ case SEC_ASN1_SEQUENCE:
+ /*
+ * We need to push a child to handle the individual fields.
+ */
+ state->place = duringSequence;
+ state = sec_asn1d_push_state(state->top, state->theTemplate + 1,
+ state->dest, PR_TRUE);
+ if (state != NULL) {
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1d_notify_before(state->top, state->dest, state->depth);
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ break;
+
+ case SEC_ASN1_SET: /* XXX SET is not really implemented */
+ /*
+ * XXX A plain SET requires special handling; scanning of a
+ * template to see where a field should go (because by definition,
+ * they are not in any particular order, and you have to look at
+ * each tag to disambiguate what the field is). We may never
+ * implement this because in practice, it seems to be unused.
+ */
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_BAD_DER); /* XXX */
+ state->top->status = decodeError;
+ break;
+
+ case SEC_ASN1_NULL:
+ /*
+ * The NULL type, by definition, is "nothing", content length of zero.
+ * An indefinite-length encoding is not alloweed.
+ */
+ if (state->contents_length || state->indefinite) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ break;
+ }
+ if (state->dest != NULL) {
+ item = (SECItem *)(state->dest);
+ item->data = NULL;
+ item->len = 0;
+ }
+ state->place = afterEndOfContents;
+ break;
+
+ case SEC_ASN1_BMP_STRING:
+ /* Error if length is not divisable by 2 */
+ if (state->contents_length % 2) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ break;
+ }
+ /* otherwise, handle as other string types */
+ goto regular_string_type;
+
+ case SEC_ASN1_UNIVERSAL_STRING:
+ /* Error if length is not divisable by 4 */
+ if (state->contents_length % 4) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ break;
+ }
+ /* otherwise, handle as other string types */
+ goto regular_string_type;
+
+ case SEC_ASN1_SKIP:
+ case SEC_ASN1_ANY:
+ case SEC_ASN1_ANY_CONTENTS:
+ /*
+ * These are not (necessarily) strings, but they need nearly
+ * identical handling (especially when we need to deal with
+ * constructed sub-pieces), so we pretend they are.
+ */
+ /* fallthru */
+ regular_string_type:
+ case SEC_ASN1_BIT_STRING:
+ case SEC_ASN1_IA5_STRING:
+ case SEC_ASN1_OCTET_STRING:
+ case SEC_ASN1_PRINTABLE_STRING:
+ case SEC_ASN1_T61_STRING:
+ case SEC_ASN1_UTC_TIME:
+ case SEC_ASN1_UTF8_STRING:
+ case SEC_ASN1_VISIBLE_STRING:
+ /*
+ * We are allocating for a primitive or a constructed string.
+ * If it is a constructed string, it may also be indefinite-length.
+ * If it is primitive, the length can (legally) be zero.
+ * Our first order of business is to allocate the memory for
+ * the string, if we can (if we know the length).
+ */
+ item = (SECItem *)(state->dest);
+
+ /*
+ * If the item is a definite-length constructed string, then
+ * the contents_length is actually larger than what we need
+ * (because it also counts each intermediate header which we
+ * will be throwing away as we go), but it is a perfectly good
+ * upper bound that we just allocate anyway, and then concat
+ * as we go; we end up wasting a few extra bytes but save a
+ * whole other copy.
+ */
+ alloc_len = state->contents_length;
+ poolp = NULL; /* quiet compiler warnings about unused... */
+
+ if (item == NULL || state->top->filter_only) {
+ if (item != NULL) {
+ item->data = NULL;
+ item->len = 0;
+ }
+ alloc_len = 0;
+ } else if (state->substring) {
+ /*
+ * If we are a substring of a constructed string, then we may
+ * not have to allocate anything (because our parent, the
+ * actual constructed string, did it for us). If we are a
+ * substring and we *do* have to allocate, that means our
+ * parent is an indefinite-length, so we allocate from our pool;
+ * later our parent will copy our string into the aggregated
+ * whole and free our pool allocation.
+ */
+ if (item->data == NULL) {
+ PORT_Assert(item->len == 0);
+ poolp = state->top->our_pool;
+ } else {
+ alloc_len = 0;
+ }
+ } else {
+ item->len = 0;
+ item->data = NULL;
+ poolp = state->top->their_pool;
+ }
+
+ if (alloc_len || ((!state->indefinite) && (state->subitems_head != NULL))) {
+ struct subitem *subitem;
+ int len;
+
+ PORT_Assert(item);
+ if (!item) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ PORT_Assert(item->len == 0 && item->data == NULL);
+ /*
+ * Check for and handle an ANY which has stashed aside the
+ * header (identifier and length) bytes for us to include
+ * in the saved contents.
+ */
+ if (state->subitems_head != NULL) {
+ PORT_Assert(state->underlying_kind == SEC_ASN1_ANY);
+ for (subitem = state->subitems_head;
+ subitem != NULL; subitem = subitem->next)
+ alloc_len += subitem->len;
+ }
+
+ item->data = (unsigned char *)sec_asn1d_zalloc(poolp, alloc_len);
+ if (item->data == NULL) {
+ state->top->status = decodeError;
+ break;
+ }
+
+ len = 0;
+ for (subitem = state->subitems_head;
+ subitem != NULL; subitem = subitem->next) {
+ PORT_Memcpy(item->data + len, subitem->data, subitem->len);
+ len += subitem->len;
+ }
+ item->len = len;
+
+ /*
+ * Because we use arenas and have a mark set, we later free
+ * everything we have allocated, so this does *not* present
+ * a memory leak (it is just temporarily left dangling).
+ */
+ state->subitems_head = state->subitems_tail = NULL;
+ }
+
+ if (state->contents_length == 0 && (!state->indefinite)) {
+ /*
+ * A zero-length simple or constructed string; we are done.
+ */
+ state->place = afterEndOfContents;
+ } else if (state->found_tag_modifiers & SEC_ASN1_CONSTRUCTED) {
+ const SEC_ASN1Template *sub;
+
+ switch (state->underlying_kind) {
+ case SEC_ASN1_ANY:
+ case SEC_ASN1_ANY_CONTENTS:
+ sub = SEC_AnyTemplate;
+ break;
+ case SEC_ASN1_BIT_STRING:
+ sub = SEC_BitStringTemplate;
+ break;
+ case SEC_ASN1_BMP_STRING:
+ sub = SEC_BMPStringTemplate;
+ break;
+ case SEC_ASN1_GENERALIZED_TIME:
+ sub = SEC_GeneralizedTimeTemplate;
+ break;
+ case SEC_ASN1_IA5_STRING:
+ sub = SEC_IA5StringTemplate;
+ break;
+ case SEC_ASN1_OCTET_STRING:
+ sub = SEC_OctetStringTemplate;
+ break;
+ case SEC_ASN1_PRINTABLE_STRING:
+ sub = SEC_PrintableStringTemplate;
+ break;
+ case SEC_ASN1_T61_STRING:
+ sub = SEC_T61StringTemplate;
+ break;
+ case SEC_ASN1_UNIVERSAL_STRING:
+ sub = SEC_UniversalStringTemplate;
+ break;
+ case SEC_ASN1_UTC_TIME:
+ sub = SEC_UTCTimeTemplate;
+ break;
+ case SEC_ASN1_UTF8_STRING:
+ sub = SEC_UTF8StringTemplate;
+ break;
+ case SEC_ASN1_VISIBLE_STRING:
+ sub = SEC_VisibleStringTemplate;
+ break;
+ case SEC_ASN1_SKIP:
+ sub = SEC_SkipTemplate;
+ break;
+ default: /* redundant given outer switch cases, but */
+ PORT_Assert(0); /* the compiler does not seem to know that, */
+ sub = NULL; /* so just do enough to quiet it. */
+ break;
+ }
+
+ state->place = duringConstructedString;
+ state = sec_asn1d_push_state(state->top, sub, item, PR_TRUE);
+ if (state != NULL) {
+ state->substring = PR_TRUE; /* XXX propogate? */
+ (void)sec_asn1d_init_state_based_on_template(state);
+ }
+ } else if (state->indefinite) {
+ /*
+ * An indefinite-length string *must* be constructed!
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ /*
+ * A non-zero-length simple string.
+ */
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING)
+ state->place = beforeBitString;
+ else
+ state->place = duringLeaf;
+ }
+ break;
+
+ default:
+ /*
+ * We are allocating for a simple leaf item.
+ */
+ if (state->contents_length) {
+ if (state->dest != NULL) {
+ item = (SECItem *)(state->dest);
+ item->len = 0;
+ if (state->top->filter_only) {
+ item->data = NULL;
+ } else {
+ item->data = (unsigned char *)
+ sec_asn1d_zalloc(state->top->their_pool,
+ state->contents_length);
+ if (item->data == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+ }
+ }
+ state->place = duringLeaf;
+ } else {
+ /*
+ * An indefinite-length or zero-length item is not allowed.
+ * (All legal cases of such were handled above.)
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ }
}
}
-
static void
-sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
+sec_asn1d_free_child(sec_asn1d_state *state, PRBool error)
{
if (state->child != NULL) {
- PORT_Assert (error || state->child->consumed == 0);
- PORT_Assert (state->our_mark != NULL);
- PORT_ArenaZRelease (state->top->our_pool, state->our_mark);
- if (error && state->top->their_pool == NULL) {
- /*
- * XXX We need to free anything allocated.
+ PORT_Assert(error || state->child->consumed == 0);
+ PORT_Assert(state->our_mark != NULL);
+ PORT_ArenaZRelease(state->top->our_pool, state->our_mark);
+ if (error && state->top->their_pool == NULL) {
+ /*
+ * XXX We need to free anything allocated.
* At this point, we failed in the middle of decoding. But we
* can't free the data we previously allocated with PR_Malloc
* unless we keep track of every pointer. So instead we have a
* memory leak when decoding fails half-way, unless an arena is
* used. See bug 95311 .
- */
- }
- state->child = NULL;
- state->our_mark = NULL;
+ */
+ }
+ state->child = NULL;
+ state->our_mark = NULL;
} else {
- /*
- * It is important that we do not leave a mark unreleased/unmarked.
- * But I do not think we should ever have one set in this case, only
- * if we had a child (handled above). So check for that. If this
- * assertion should ever get hit, then we probably need to add code
- * here to release back to our_mark (and then set our_mark to NULL).
- */
- PORT_Assert (state->our_mark == NULL);
+ /*
+ * It is important that we do not leave a mark unreleased/unmarked.
+ * But I do not think we should ever have one set in this case, only
+ * if we had a child (handled above). So check for that. If this
+ * assertion should ever get hit, then we probably need to add code
+ * here to release back to our_mark (and then set our_mark to NULL).
+ */
+ PORT_Assert(state->our_mark == NULL);
}
state->place = beforeEndOfContents;
}
-/* We have just saved an entire encoded ASN.1 object (type) for a SAVE
-** template, and now in the next template, we are going to decode that
+/* We have just saved an entire encoded ASN.1 object (type) for a SAVE
+** template, and now in the next template, we are going to decode that
** saved data by calling SEC_ASN1DecoderUpdate recursively.
** If that recursive call fails with needBytes, it is a fatal error,
** because the encoded object should have been complete.
@@ -1488,34 +1464,33 @@ sec_asn1d_free_child (sec_asn1d_state *state, PRBool error)
** done in the caller of this function, immediately after it returns.
*/
static void
-sec_asn1d_reuse_encoding (sec_asn1d_state *state)
+sec_asn1d_reuse_encoding(sec_asn1d_state *state)
{
sec_asn1d_state *child;
unsigned long consumed;
SECItem *item;
void *dest;
-
child = state->child;
- PORT_Assert (child != NULL);
+ PORT_Assert(child != NULL);
consumed = child->consumed;
child->consumed = 0;
item = (SECItem *)(state->dest);
- PORT_Assert (item != NULL);
+ PORT_Assert(item != NULL);
- PORT_Assert (item->len == consumed);
+ PORT_Assert(item->len == consumed);
/*
* Free any grandchild.
*/
- sec_asn1d_free_child (child, PR_FALSE);
+ sec_asn1d_free_child(child, PR_FALSE);
/*
* Notify after the SAVE field.
*/
- sec_asn1d_notify_after (state->top, state->dest, state->depth);
+ sec_asn1d_notify_after(state->top, state->dest, state->depth);
/*
* Adjust to get new dest and move forward.
@@ -1528,8 +1503,8 @@ sec_asn1d_reuse_encoding (sec_asn1d_state *state)
/*
* Notify before the "real" field.
*/
- PORT_Assert (state->depth == child->depth);
- sec_asn1d_notify_before (state->top, child->dest, child->depth);
+ PORT_Assert(state->depth == child->depth);
+ sec_asn1d_notify_before(state->top, child->dest, child->depth);
/*
* This will tell DecoderUpdate to return when it is done.
@@ -1544,25 +1519,25 @@ sec_asn1d_reuse_encoding (sec_asn1d_state *state)
/*
* And initialize it so it is ready to parse.
*/
- (void) sec_asn1d_init_state_based_on_template(child);
+ (void)sec_asn1d_init_state_based_on_template(child);
/*
* Now parse that out of our data.
*/
- if (SEC_ASN1DecoderUpdate (state->top,
- (char *) item->data, item->len) != SECSuccess)
- return;
+ if (SEC_ASN1DecoderUpdate(state->top,
+ (char *)item->data, item->len) != SECSuccess)
+ return;
if (state->top->status == needBytes) {
- return;
+ return;
}
- PORT_Assert (state->top->current == state);
- PORT_Assert (state->child == child);
+ PORT_Assert(state->top->current == state);
+ PORT_Assert(state->child == child);
/*
* That should have consumed what we consumed before.
*/
- PORT_Assert (consumed == child->consumed);
+ PORT_Assert(consumed == child->consumed);
child->consumed = 0;
/*
@@ -1573,76 +1548,109 @@ sec_asn1d_reuse_encoding (sec_asn1d_state *state)
state->place = afterEndOfContents;
}
-
static unsigned long
-sec_asn1d_parse_leaf (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_leaf(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
SECItem *item;
unsigned long bufLen;
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
if (state->pending < len)
- len = state->pending;
+ len = state->pending;
bufLen = len;
item = (SECItem *)(state->dest);
if (item != NULL && item->data != NULL) {
- /* Strip leading zeroes when target is unsigned integer */
- if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
- item->len == 0 && /* MSB */
- item->type == siUnsignedInteger) /* unsigned */
- {
- while (len > 1 && buf[0] == 0) { /* leading 0 */
- buf++;
- len--;
- }
- }
- PORT_Memcpy (item->data + item->len, buf, len);
- item->len += len;
+ unsigned long offset;
+ /* Strip leading zeroes when target is unsigned integer */
+ if (state->underlying_kind == SEC_ASN1_INTEGER && /* INTEGER */
+ item->len == 0 && /* MSB */
+ item->type == siUnsignedInteger) /* unsigned */
+ {
+ while (len > 1 && buf[0] == 0) { /* leading 0 */
+ buf++;
+ len--;
+ }
+ }
+ offset = item->len;
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
+ // The previous bit string must have no unused bits.
+ if (item->len & 0x7) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ // If this is a bit string, the length is bits, not bytes.
+ offset = item->len >> 3;
+ }
+ if (state->underlying_kind == SEC_ASN1_BIT_STRING) {
+ unsigned long len_in_bits;
+ // Protect against overflow during the bytes-to-bits conversion.
+ if (len >= (ULONG_MAX >> 3) + 1) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ len_in_bits = (len << 3) - state->bit_string_unused_bits;
+ // Protect against overflow when computing the total length in bits.
+ if (UINT_MAX - item->len < len_in_bits) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ item->len += len_in_bits;
+ } else {
+ if (UINT_MAX - item->len < len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
+ item->len += len;
+ }
+ PORT_Memcpy(item->data + offset, buf, len);
}
state->pending -= bufLen;
if (state->pending == 0)
- state->place = beforeEndOfContents;
+ state->place = beforeEndOfContents;
return bufLen;
}
-
static unsigned long
-sec_asn1d_parse_bit_string (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_bit_string(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
unsigned char byte;
/*PORT_Assert (state->pending > 0); */
- PORT_Assert (state->place == beforeBitString);
+ PORT_Assert(state->place == beforeBitString);
if (state->pending == 0) {
- if (state->dest != NULL) {
- SECItem *item = (SECItem *)(state->dest);
- item->data = NULL;
- item->len = 0;
- state->place = beforeEndOfContents;
- return 0;
- }
+ if (state->dest != NULL) {
+ SECItem *item = (SECItem *)(state->dest);
+ item->data = NULL;
+ item->len = 0;
+ state->place = beforeEndOfContents;
+ return 0;
+ }
}
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
- byte = (unsigned char) *buf;
+ byte = (unsigned char)*buf;
if (byte > 7) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return 0;
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
}
state->bit_string_unused_bits = byte;
@@ -1652,102 +1660,90 @@ sec_asn1d_parse_bit_string (sec_asn1d_state *state,
return 1;
}
-
static unsigned long
-sec_asn1d_parse_more_bit_string (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_more_bit_string(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
- PORT_Assert (state->place == duringBitString);
+ PORT_Assert(state->place == duringBitString);
if (state->pending == 0) {
- /* An empty bit string with some unused bits is invalid. */
- if (state->bit_string_unused_bits) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- } else {
- /* An empty bit string with no unused bits is OK. */
- state->place = beforeEndOfContents;
- }
- return 0;
- }
-
- len = sec_asn1d_parse_leaf (state, buf, len);
- if (state->place == beforeEndOfContents && state->dest != NULL) {
- SECItem *item;
-
- item = (SECItem *)(state->dest);
- if (item->len)
- item->len = (item->len << 3) - state->bit_string_unused_bits;
+ /* An empty bit string with some unused bits is invalid. */
+ if (state->bit_string_unused_bits) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ /* An empty bit string with no unused bits is OK. */
+ state->place = beforeEndOfContents;
+ }
+ return 0;
}
+ len = sec_asn1d_parse_leaf(state, buf, len);
return len;
}
-
/*
* XXX All callers should be looking at return value to detect
* out-of-memory errors (and stop!).
*/
static struct subitem *
-sec_asn1d_add_to_subitems (sec_asn1d_state *state,
- const void *data, unsigned long len,
- PRBool copy_data)
+sec_asn1d_add_to_subitems(sec_asn1d_state *state,
+ const void *data, unsigned long len,
+ PRBool copy_data)
{
struct subitem *thing;
- thing = (struct subitem*)sec_asn1d_zalloc (state->top->our_pool,
- sizeof (struct subitem));
+ thing = (struct subitem *)sec_asn1d_zalloc(state->top->our_pool,
+ sizeof(struct subitem));
if (thing == NULL) {
- state->top->status = decodeError;
- return NULL;
+ state->top->status = decodeError;
+ return NULL;
}
if (copy_data) {
- void *copy;
- copy = sec_asn1d_alloc (state->top->our_pool, len);
- if (copy == NULL) {
- state->top->status = decodeError;
- if (!state->top->our_pool)
- PORT_Free(thing);
- return NULL;
- }
- PORT_Memcpy (copy, data, len);
- thing->data = copy;
+ void *copy;
+ copy = sec_asn1d_alloc(state->top->our_pool, len);
+ if (copy == NULL) {
+ state->top->status = decodeError;
+ if (!state->top->our_pool)
+ PORT_Free(thing);
+ return NULL;
+ }
+ PORT_Memcpy(copy, data, len);
+ thing->data = copy;
} else {
- thing->data = data;
+ thing->data = data;
}
thing->len = len;
thing->next = NULL;
if (state->subitems_head == NULL) {
- PORT_Assert (state->subitems_tail == NULL);
- state->subitems_head = state->subitems_tail = thing;
+ PORT_Assert(state->subitems_tail == NULL);
+ state->subitems_head = state->subitems_tail = thing;
} else {
- state->subitems_tail->next = thing;
- state->subitems_tail = thing;
+ state->subitems_tail->next = thing;
+ state->subitems_tail = thing;
}
return thing;
}
-
static void
-sec_asn1d_record_any_header (sec_asn1d_state *state,
- const char *buf,
- unsigned long len)
+sec_asn1d_record_any_header(sec_asn1d_state *state,
+ const char *buf,
+ unsigned long len)
{
SECItem *item;
item = (SECItem *)(state->dest);
if (item != NULL && item->data != NULL) {
- PORT_Assert (state->substring);
- PORT_Memcpy (item->data + item->len, buf, len);
- item->len += len;
+ PORT_Assert(state->substring);
+ PORT_Memcpy(item->data + item->len, buf, len);
+ item->len += len;
} else {
- sec_asn1d_add_to_subitems (state, buf, len, PR_TRUE);
+ sec_asn1d_add_to_subitems(state, buf, len, PR_TRUE);
}
}
-
/*
* We are moving along through the substrings of a constructed string,
* and have just finished parsing one -- we need to save our child data
@@ -1755,20 +1751,20 @@ sec_asn1d_record_any_header (sec_asn1d_state *state,
* and then move forward by one.
*
* We also have to detect when we are done:
- * - a definite-length encoding stops when our pending value hits 0
- * - an indefinite-length encoding stops when our child is empty
- * (which means it was the end-of-contents octets)
+ * - a definite-length encoding stops when our pending value hits 0
+ * - an indefinite-length encoding stops when our child is empty
+ * (which means it was the end-of-contents octets)
*/
static void
-sec_asn1d_next_substring (sec_asn1d_state *state)
+sec_asn1d_next_substring(sec_asn1d_state *state)
{
sec_asn1d_state *child;
SECItem *item;
unsigned long child_consumed;
PRBool done;
- PORT_Assert (state->place == duringConstructedString);
- PORT_Assert (state->child != NULL);
+ PORT_Assert(state->place == duringConstructedString);
+ PORT_Assert(state->child != NULL);
child = state->child;
@@ -1779,161 +1775,160 @@ sec_asn1d_next_substring (sec_asn1d_state *state)
done = PR_FALSE;
if (state->pending) {
- PORT_Assert (!state->indefinite);
- if (child_consumed > state->pending) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
-
- state->pending -= child_consumed;
- if (state->pending == 0)
- done = PR_TRUE;
+ PORT_Assert(!state->indefinite);
+ if (child_consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+
+ state->pending -= child_consumed;
+ if (state->pending == 0)
+ done = PR_TRUE;
} else {
- PRBool preallocatedString;
- sec_asn1d_state *temp_state;
- PORT_Assert (state->indefinite);
-
- item = (SECItem *)(child->dest);
-
- /**
- * At this point, there's three states at play:
- * child: The element that was just parsed
- * state: The currently processed element
- * 'parent' (aka state->parent): The enclosing construct
- * of state, or NULL if this is the top-most element.
- *
- * This state handles both substrings of a constructed string AND
- * child elements of items whose template type was that of
- * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
- * template, as described in sec_asn1d_prepare_for_contents. For
- * brevity, these will be referred to as 'string' and 'any' types.
- *
- * This leads to the following possibilities:
- * 1: This element is an indefinite length string, part of a
- * definite length string.
- * 2: This element is an indefinite length string, part of an
- * indefinite length string.
- * 3: This element is an indefinite length any, part of a
- * definite length any.
- * 4: This element is an indefinite length any, part of an
- * indefinite length any.
- * 5: This element is an indefinite length any and does not
- * meet any of the above criteria. Note that this would include
- * an indefinite length string type matching an indefinite
- * length any template.
- *
- * In Cases #1 and #3, the definite length 'parent' element will
- * have allocated state->dest based on the parent elements definite
- * size. During the processing of 'child', sec_asn1d_parse_leaf will
- * have copied the (string, any) data directly into the offset of
- * dest, as appropriate, so there's no need for this class to still
- * store the child - it's already been processed.
- *
- * In Cases #2 and #4, dest will be set to the parent element's dest,
- * but dest->data will not have been allocated yet, due to the
- * indefinite length encoding. In this situation, it's necessary to
- * hold onto child (and all other children) until the EOC, at which
- * point, it becomes possible to compute 'state's overall length. Once
- * 'state' has a computed length, this can then be fed to 'parent' (via
- * this state), and then 'parent' can similarly compute the length of
- * all of its children up to the EOC, which will ultimately transit to
- * sec_asn1d_concat_substrings, determine the overall size needed,
- * allocate, and copy the contents (of all of parent's children, which
- * would include 'state', just as 'state' will have copied all of its
- * children via sec_asn1d_concat_substrings)
- *
- * The final case, Case #5, will manifest in that item->data and
- * item->len will be NULL/0, respectively, since this element was
- * indefinite-length encoded. In that case, both the tag and length will
- * already exist in state's subitems, via sec_asn1d_record_any_header,
- * and so the contents (aka 'child') should be added to that list of
- * items to concatenate in sec_asn1d_concat_substrings once the EOC
- * is encountered.
- *
- * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
- * tree. If the current type is a string type, then the enclosing
- * construct will be that same type (#1/#2). If the current type is an
- * any type, then the enclosing construct is either an any type (#3/#4)
- * or some other type (#5). Since this is BER, this nesting relationship
- * between 'state' and 'parent' may go through several levels of
- * constructed encoding, so continue walking the ancestor chain until a
- * clear determination can be made.
- *
- * The variable preallocatedString is used to indicate Case #1/#3,
- * indicating an in-place copy has already occurred, and Cases #2, #4,
- * and #5 all have the same behaviour of adding a new substring.
- */
- preallocatedString = PR_FALSE;
- temp_state = state;
- while (temp_state && item == temp_state->dest && temp_state->indefinite) {
- sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
- if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
- /* Case #5 - Either this is a top-level construct or it is part
- * of some other element (e.g. a SEQUENCE), in which case, a
- * new item should be allocated. */
- break;
- }
- if (!parent->indefinite) {
- /* Cases #1 / #3 - A definite length ancestor exists, for which
- * this is a substring that has already copied into dest. */
- preallocatedString = PR_TRUE;
- break;
- }
- if (!parent->substring) {
- /* Cases #2 / #4 - If the parent is not a substring, but is
- * indefinite, then there's nothing further up that may have
- * preallocated dest, thus child will not have already
- * been copied in place, therefore it's necessary to save child
- * as a subitem. */
- break;
- }
- temp_state = parent;
- }
- if (item != NULL && item->data != NULL && !preallocatedString) {
- /*
- * Save the string away for later concatenation.
- */
- PORT_Assert (item->data != NULL);
- sec_asn1d_add_to_subitems (state, item->data, item->len, PR_FALSE);
- /*
- * Clear the child item for the next round.
- */
- item->data = NULL;
- item->len = 0;
- }
-
- /*
- * If our child was just our end-of-contents octets, we are done.
- */
- if (child->endofcontents)
- done = PR_TRUE;
+ PRBool preallocatedString;
+ sec_asn1d_state *temp_state;
+ PORT_Assert(state->indefinite);
+
+ item = (SECItem *)(child->dest);
+
+ /**
+ * At this point, there's three states at play:
+ * child: The element that was just parsed
+ * state: The currently processed element
+ * 'parent' (aka state->parent): The enclosing construct
+ * of state, or NULL if this is the top-most element.
+ *
+ * This state handles both substrings of a constructed string AND
+ * child elements of items whose template type was that of
+ * SEC_ASN1_ANY, SEC_ASN1_SAVE, SEC_ASN1_ANY_CONTENTS, SEC_ASN1_SKIP
+ * template, as described in sec_asn1d_prepare_for_contents. For
+ * brevity, these will be referred to as 'string' and 'any' types.
+ *
+ * This leads to the following possibilities:
+ * 1: This element is an indefinite length string, part of a
+ * definite length string.
+ * 2: This element is an indefinite length string, part of an
+ * indefinite length string.
+ * 3: This element is an indefinite length any, part of a
+ * definite length any.
+ * 4: This element is an indefinite length any, part of an
+ * indefinite length any.
+ * 5: This element is an indefinite length any and does not
+ * meet any of the above criteria. Note that this would include
+ * an indefinite length string type matching an indefinite
+ * length any template.
+ *
+ * In Cases #1 and #3, the definite length 'parent' element will
+ * have allocated state->dest based on the parent elements definite
+ * size. During the processing of 'child', sec_asn1d_parse_leaf will
+ * have copied the (string, any) data directly into the offset of
+ * dest, as appropriate, so there's no need for this class to still
+ * store the child - it's already been processed.
+ *
+ * In Cases #2 and #4, dest will be set to the parent element's dest,
+ * but dest->data will not have been allocated yet, due to the
+ * indefinite length encoding. In this situation, it's necessary to
+ * hold onto child (and all other children) until the EOC, at which
+ * point, it becomes possible to compute 'state's overall length. Once
+ * 'state' has a computed length, this can then be fed to 'parent' (via
+ * this state), and then 'parent' can similarly compute the length of
+ * all of its children up to the EOC, which will ultimately transit to
+ * sec_asn1d_concat_substrings, determine the overall size needed,
+ * allocate, and copy the contents (of all of parent's children, which
+ * would include 'state', just as 'state' will have copied all of its
+ * children via sec_asn1d_concat_substrings)
+ *
+ * The final case, Case #5, will manifest in that item->data and
+ * item->len will be NULL/0, respectively, since this element was
+ * indefinite-length encoded. In that case, both the tag and length will
+ * already exist in state's subitems, via sec_asn1d_record_any_header,
+ * and so the contents (aka 'child') should be added to that list of
+ * items to concatenate in sec_asn1d_concat_substrings once the EOC
+ * is encountered.
+ *
+ * To distinguish #2/#4 from #1/#3, it's sufficient to walk the ancestor
+ * tree. If the current type is a string type, then the enclosing
+ * construct will be that same type (#1/#2). If the current type is an
+ * any type, then the enclosing construct is either an any type (#3/#4)
+ * or some other type (#5). Since this is BER, this nesting relationship
+ * between 'state' and 'parent' may go through several levels of
+ * constructed encoding, so continue walking the ancestor chain until a
+ * clear determination can be made.
+ *
+ * The variable preallocatedString is used to indicate Case #1/#3,
+ * indicating an in-place copy has already occurred, and Cases #2, #4,
+ * and #5 all have the same behaviour of adding a new substring.
+ */
+ preallocatedString = PR_FALSE;
+ temp_state = state;
+ while (temp_state && item == temp_state->dest && temp_state->indefinite) {
+ sec_asn1d_state *parent = sec_asn1d_get_enclosing_construct(temp_state);
+ if (!parent || parent->underlying_kind != temp_state->underlying_kind) {
+ /* Case #5 - Either this is a top-level construct or it is part
+ * of some other element (e.g. a SEQUENCE), in which case, a
+ * new item should be allocated. */
+ break;
+ }
+ if (!parent->indefinite) {
+ /* Cases #1 / #3 - A definite length ancestor exists, for which
+ * this is a substring that has already copied into dest. */
+ preallocatedString = PR_TRUE;
+ break;
+ }
+ if (!parent->substring) {
+ /* Cases #2 / #4 - If the parent is not a substring, but is
+ * indefinite, then there's nothing further up that may have
+ * preallocated dest, thus child will not have already
+ * been copied in place, therefore it's necessary to save child
+ * as a subitem. */
+ break;
+ }
+ temp_state = parent;
+ }
+ if (item != NULL && item->data != NULL && !preallocatedString) {
+ /*
+ * Save the string away for later concatenation.
+ */
+ PORT_Assert(item->data != NULL);
+ sec_asn1d_add_to_subitems(state, item->data, item->len, PR_FALSE);
+ /*
+ * Clear the child item for the next round.
+ */
+ item->data = NULL;
+ item->len = 0;
+ }
+
+ /*
+ * If our child was just our end-of-contents octets, we are done.
+ */
+ if (child->endofcontents)
+ done = PR_TRUE;
}
/*
* Stop or do the next one.
*/
if (done) {
- child->place = notInUse;
- state->place = afterConstructedString;
+ child->place = notInUse;
+ state->place = afterConstructedString;
} else {
- sec_asn1d_scrub_state (child);
- state->top->current = child;
+ sec_asn1d_scrub_state(child);
+ state->top->current = child;
}
}
-
/*
* We are doing a SET OF or SEQUENCE OF, and have just finished an item.
*/
static void
-sec_asn1d_next_in_group (sec_asn1d_state *state)
+sec_asn1d_next_in_group(sec_asn1d_state *state)
{
sec_asn1d_state *child;
unsigned long child_consumed;
- PORT_Assert (state->place == duringGroup);
- PORT_Assert (state->child != NULL);
+ PORT_Assert(state->place == duringGroup);
+ PORT_Assert(state->child != NULL);
child = state->child;
@@ -1945,80 +1940,80 @@ sec_asn1d_next_in_group (sec_asn1d_state *state)
* If our child was just our end-of-contents octets, we are done.
*/
if (child->endofcontents) {
- /* XXX I removed the PORT_Assert (child->dest == NULL) because there
- * was a bug in that a template that was a sequence of which also had
- * a child of a sequence of, in an indefinite group was not working
- * properly. This fix seems to work, (added the if statement below),
- * and nothing appears broken, but I am putting this note here just
- * in case. */
- /*
- * XXX No matter how many times I read that comment,
- * I cannot figure out what case he was fixing. I believe what he
- * did was deliberate, so I am loathe to touch it. I need to
- * understand how it could ever be that child->dest != NULL but
- * child->endofcontents is true, and why it is important to check
- * that state->subitems_head is NULL. This really needs to be
- * figured out, as I am not sure if the following code should be
- * compensating for "offset", as is done a little farther below
- * in the more normal case.
- */
- PORT_Assert (state->indefinite);
- PORT_Assert (state->pending == 0);
- if(child->dest && !state->subitems_head) {
- sec_asn1d_add_to_subitems (state, child->dest, 0, PR_FALSE);
- child->dest = NULL;
- }
-
- child->place = notInUse;
- state->place = afterGroup;
- return;
- }
-
- /*
+ /* XXX I removed the PORT_Assert (child->dest == NULL) because there
+ * was a bug in that a template that was a sequence of which also had
+ * a child of a sequence of, in an indefinite group was not working
+ * properly. This fix seems to work, (added the if statement below),
+ * and nothing appears broken, but I am putting this note here just
+ * in case. */
+ /*
+ * XXX No matter how many times I read that comment,
+ * I cannot figure out what case he was fixing. I believe what he
+ * did was deliberate, so I am loathe to touch it. I need to
+ * understand how it could ever be that child->dest != NULL but
+ * child->endofcontents is true, and why it is important to check
+ * that state->subitems_head is NULL. This really needs to be
+ * figured out, as I am not sure if the following code should be
+ * compensating for "offset", as is done a little farther below
+ * in the more normal case.
+ */
+ PORT_Assert(state->indefinite);
+ PORT_Assert(state->pending == 0);
+ if (child->dest && !state->subitems_head) {
+ sec_asn1d_add_to_subitems(state, child->dest, 0, PR_FALSE);
+ child->dest = NULL;
+ }
+
+ child->place = notInUse;
+ state->place = afterGroup;
+ return;
+ }
+
+ /*
* Do the "after" field notification for next in group.
*/
- sec_asn1d_notify_after (state->top, child->dest, child->depth);
+ sec_asn1d_notify_after(state->top, child->dest, child->depth);
/*
* Save it away (unless we are not storing).
*/
if (child->dest != NULL) {
- void *dest;
+ void *dest;
- dest = child->dest;
- dest = (char *)dest - child->theTemplate->offset;
- sec_asn1d_add_to_subitems (state, dest, 0, PR_FALSE);
- child->dest = NULL;
+ dest = child->dest;
+ dest = (char *)dest - child->theTemplate->offset;
+ sec_asn1d_add_to_subitems(state, dest, 0, PR_FALSE);
+ child->dest = NULL;
}
/*
* Account for those bytes; see if we are done.
*/
if (state->pending) {
- PORT_Assert (!state->indefinite);
- if (child_consumed > state->pending) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
+ PORT_Assert(!state->indefinite);
+ if (child_consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
- state->pending -= child_consumed;
- if (state->pending == 0) {
- child->place = notInUse;
- state->place = afterGroup;
- return;
- }
+ state->pending -= child_consumed;
+ if (state->pending == 0) {
+ child->place = notInUse;
+ state->place = afterGroup;
+ return;
+ }
}
/*
* Do the "before" field notification for next item in group.
*/
- sec_asn1d_notify_before (state->top, child->dest, child->depth);
+ sec_asn1d_notify_before(state->top, child->dest, child->depth);
/*
* Now we do the next one.
*/
- sec_asn1d_scrub_state (child);
+ sec_asn1d_scrub_state(child);
/* Initialize child state from the template */
sec_asn1d_init_state_based_on_template(child);
@@ -2026,30 +2021,29 @@ sec_asn1d_next_in_group (sec_asn1d_state *state)
state->top->current = child;
}
-
/*
* We are moving along through a sequence; move forward by one,
* (detecting end-of-sequence when it happens).
* XXX The handling of "missing" is ugly. Fix it.
*/
static void
-sec_asn1d_next_in_sequence (sec_asn1d_state *state)
+sec_asn1d_next_in_sequence(sec_asn1d_state *state)
{
sec_asn1d_state *child;
unsigned long child_consumed;
PRBool child_missing;
- PORT_Assert (state->place == duringSequence);
- PORT_Assert (state->child != NULL);
+ PORT_Assert(state->place == duringSequence);
+ PORT_Assert(state->child != NULL);
child = state->child;
/*
* Do the "after" field notification.
*/
- sec_asn1d_notify_after (state->top, child->dest, child->depth);
+ sec_asn1d_notify_after(state->top, child->dest, child->depth);
- child_missing = (PRBool) child->missing;
+ child_missing = (PRBool)child->missing;
child_consumed = child->consumed;
child->consumed = 0;
@@ -2057,36 +2051,36 @@ sec_asn1d_next_in_sequence (sec_asn1d_state *state)
* Take care of accounting.
*/
if (child_missing) {
- PORT_Assert (child->optional);
+ PORT_Assert(child->optional);
} else {
- state->consumed += child_consumed;
- /*
- * Free any grandchild.
- */
- sec_asn1d_free_child (child, PR_FALSE);
- if (state->pending) {
- PORT_Assert (!state->indefinite);
- if (child_consumed > state->pending) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
- state->pending -= child_consumed;
- if (state->pending == 0) {
- child->theTemplate++;
- while (child->theTemplate->kind != 0) {
- if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
- child->theTemplate++;
- }
- child->place = notInUse;
- state->place = afterEndOfContents;
- return;
- }
- }
+ state->consumed += child_consumed;
+ /*
+ * Free any grandchild.
+ */
+ sec_asn1d_free_child(child, PR_FALSE);
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ if (child_consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ state->pending -= child_consumed;
+ if (state->pending == 0) {
+ child->theTemplate++;
+ while (child->theTemplate->kind != 0) {
+ if ((child->theTemplate->kind & SEC_ASN1_OPTIONAL) == 0) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ child->theTemplate++;
+ }
+ child->place = notInUse;
+ state->place = afterEndOfContents;
+ return;
+ }
+ }
}
/*
@@ -2094,239 +2088,235 @@ sec_asn1d_next_in_sequence (sec_asn1d_state *state)
*/
child->theTemplate++;
if (child->theTemplate->kind == 0) {
- /*
- * We are done with this sequence.
- */
- child->place = notInUse;
- if (state->pending) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- } else if (child_missing) {
- /*
- * We got to the end, but have a child that started parsing
- * and ended up "missing". The only legitimate reason for
- * this is that we had one or more optional fields at the
- * end of our sequence, and we were encoded indefinite-length,
- * so when we went looking for those optional fields we
- * found our end-of-contents octets instead.
- * (Yes, this is ugly; dunno a better way to handle it.)
- * So, first confirm the situation, and then mark that we
- * are done.
- */
- if (state->indefinite && child->endofcontents) {
- PORT_Assert (child_consumed == 2);
- if (child_consumed != 2) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- } else {
- state->consumed += child_consumed;
- state->place = afterEndOfContents;
- }
- } else {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- }
- } else {
- /*
- * We have to finish out, maybe reading end-of-contents octets;
- * let the normal logic do the right thing.
- */
- state->place = beforeEndOfContents;
- }
+ /*
+ * We are done with this sequence.
+ */
+ child->place = notInUse;
+ if (state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else if (child_missing) {
+ /*
+ * We got to the end, but have a child that started parsing
+ * and ended up "missing". The only legitimate reason for
+ * this is that we had one or more optional fields at the
+ * end of our sequence, and we were encoded indefinite-length,
+ * so when we went looking for those optional fields we
+ * found our end-of-contents octets instead.
+ * (Yes, this is ugly; dunno a better way to handle it.)
+ * So, first confirm the situation, and then mark that we
+ * are done.
+ */
+ if (state->indefinite && child->endofcontents) {
+ PORT_Assert(child_consumed == 2);
+ if (child_consumed != 2) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ state->consumed += child_consumed;
+ state->place = afterEndOfContents;
+ }
+ } else {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ }
+ } else {
+ /*
+ * We have to finish out, maybe reading end-of-contents octets;
+ * let the normal logic do the right thing.
+ */
+ state->place = beforeEndOfContents;
+ }
} else {
- unsigned char child_found_tag_modifiers = 0;
- unsigned long child_found_tag_number = 0;
-
- /*
- * Reset state and push.
- */
- if (state->dest != NULL)
- child->dest = (char *)state->dest + child->theTemplate->offset;
-
- /*
- * Do the "before" field notification.
- */
- sec_asn1d_notify_before (state->top, child->dest, child->depth);
-
- if (child_missing) { /* if previous child was missing, copy the tag data we already have */
- child_found_tag_modifiers = child->found_tag_modifiers;
- child_found_tag_number = child->found_tag_number;
- }
- state->top->current = child;
- child = sec_asn1d_init_state_based_on_template (child);
- if (child_missing && child) {
- child->place = afterIdentifier;
- child->found_tag_modifiers = child_found_tag_modifiers;
- child->found_tag_number = child_found_tag_number;
- child->consumed = child_consumed;
- if (child->underlying_kind == SEC_ASN1_ANY
- && !child->top->filter_only) {
- /*
- * If the new field is an ANY, and we are storing, then
- * we need to save the tag out. We would have done this
- * already in the normal case, but since we were looking
- * for an optional field, and we did not find it, we only
- * now realize we need to save the tag.
- */
- unsigned char identifier;
-
- /*
- * Check that we did not end up with a high tag; for that
- * we need to re-encode the tag into multiple bytes in order
- * to store it back to look like what we parsed originally.
- * In practice this does not happen, but for completeness
- * sake it should probably be made to work at some point.
- */
- PORT_Assert (child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
- identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
- sec_asn1d_record_any_header (child, (char *) &identifier, 1);
- }
- }
+ unsigned char child_found_tag_modifiers = 0;
+ unsigned long child_found_tag_number = 0;
+
+ /*
+ * Reset state and push.
+ */
+ if (state->dest != NULL)
+ child->dest = (char *)state->dest + child->theTemplate->offset;
+
+ /*
+ * Do the "before" field notification.
+ */
+ sec_asn1d_notify_before(state->top, child->dest, child->depth);
+
+ if (child_missing) { /* if previous child was missing, copy the tag data we already have */
+ child_found_tag_modifiers = child->found_tag_modifiers;
+ child_found_tag_number = child->found_tag_number;
+ }
+ state->top->current = child;
+ child = sec_asn1d_init_state_based_on_template(child);
+ if (child_missing && child) {
+ child->place = afterIdentifier;
+ child->found_tag_modifiers = child_found_tag_modifiers;
+ child->found_tag_number = child_found_tag_number;
+ child->consumed = child_consumed;
+ if (child->underlying_kind == SEC_ASN1_ANY && !child->top->filter_only) {
+ /*
+ * If the new field is an ANY, and we are storing, then
+ * we need to save the tag out. We would have done this
+ * already in the normal case, but since we were looking
+ * for an optional field, and we did not find it, we only
+ * now realize we need to save the tag.
+ */
+ unsigned char identifier;
+
+ /*
+ * Check that we did not end up with a high tag; for that
+ * we need to re-encode the tag into multiple bytes in order
+ * to store it back to look like what we parsed originally.
+ * In practice this does not happen, but for completeness
+ * sake it should probably be made to work at some point.
+ */
+ PORT_Assert(child_found_tag_number < SEC_ASN1_HIGH_TAG_NUMBER);
+ identifier = (unsigned char)(child_found_tag_modifiers | child_found_tag_number);
+ sec_asn1d_record_any_header(child, (char *)&identifier, 1);
+ }
+ }
}
}
-
static void
-sec_asn1d_concat_substrings (sec_asn1d_state *state)
+sec_asn1d_concat_substrings(sec_asn1d_state *state)
{
- PORT_Assert (state->place == afterConstructedString);
+ PORT_Assert(state->place == afterConstructedString);
if (state->subitems_head != NULL) {
- struct subitem *substring;
- unsigned long alloc_len, item_len;
- unsigned char *where;
- SECItem *item;
- PRBool is_bit_string;
-
- item_len = 0;
- is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
- ? PR_TRUE : PR_FALSE;
-
- substring = state->subitems_head;
- while (substring != NULL) {
- /*
- * All bit-string substrings except the last one should be
- * a clean multiple of 8 bits.
- */
- if (is_bit_string && (substring->next == NULL)
- && (substring->len & 0x7)) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
- item_len += substring->len;
- substring = substring->next;
- }
-
- if (is_bit_string) {
- alloc_len = ((item_len + 7) >> 3);
- } else {
- /*
- * Add 2 for the end-of-contents octets of an indefinite-length
- * ANY that is *not* also an INNER. Because we zero-allocate
- * below, all we need to do is increase the length here.
- */
- if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
- item_len += 2;
- alloc_len = item_len;
- }
-
- item = (SECItem *)(state->dest);
- PORT_Assert (item != NULL);
- PORT_Assert (item->data == NULL);
- item->data = (unsigned char*)sec_asn1d_zalloc (state->top->their_pool,
- alloc_len);
- if (item->data == NULL) {
- state->top->status = decodeError;
- return;
- }
- item->len = item_len;
-
- where = item->data;
- substring = state->subitems_head;
- while (substring != NULL) {
- if (is_bit_string)
- item_len = (substring->len + 7) >> 3;
- else
- item_len = substring->len;
- PORT_Memcpy (where, substring->data, item_len);
- where += item_len;
- substring = substring->next;
- }
-
- /*
- * Because we use arenas and have a mark set, we later free
- * everything we have allocated, so this does *not* present
- * a memory leak (it is just temporarily left dangling).
- */
- state->subitems_head = state->subitems_tail = NULL;
+ struct subitem *substring;
+ unsigned long alloc_len, item_len;
+ unsigned char *where;
+ SECItem *item;
+ PRBool is_bit_string;
+
+ item_len = 0;
+ is_bit_string = (state->underlying_kind == SEC_ASN1_BIT_STRING)
+ ? PR_TRUE
+ : PR_FALSE;
+
+ substring = state->subitems_head;
+ while (substring != NULL) {
+ /*
+ * All bit-string substrings except the last one should be
+ * a clean multiple of 8 bits.
+ */
+ if (is_bit_string && (substring->next != NULL) && (substring->len & 0x7)) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ item_len += substring->len;
+ substring = substring->next;
+ }
+
+ if (is_bit_string) {
+ alloc_len = ((item_len + 7) >> 3);
+ } else {
+ /*
+ * Add 2 for the end-of-contents octets of an indefinite-length
+ * ANY that is *not* also an INNER. Because we zero-allocate
+ * below, all we need to do is increase the length here.
+ */
+ if (state->underlying_kind == SEC_ASN1_ANY && state->indefinite)
+ item_len += 2;
+ alloc_len = item_len;
+ }
+
+ item = (SECItem *)(state->dest);
+ PORT_Assert(item != NULL);
+ PORT_Assert(item->data == NULL);
+ item->data = (unsigned char *)sec_asn1d_zalloc(state->top->their_pool,
+ alloc_len);
+ if (item->data == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+ item->len = item_len;
+
+ where = item->data;
+ substring = state->subitems_head;
+ while (substring != NULL) {
+ if (is_bit_string)
+ item_len = (substring->len + 7) >> 3;
+ else
+ item_len = substring->len;
+ PORT_Memcpy(where, substring->data, item_len);
+ where += item_len;
+ substring = substring->next;
+ }
+
+ /*
+ * Because we use arenas and have a mark set, we later free
+ * everything we have allocated, so this does *not* present
+ * a memory leak (it is just temporarily left dangling).
+ */
+ state->subitems_head = state->subitems_tail = NULL;
}
state->place = afterEndOfContents;
}
-
static void
-sec_asn1d_concat_group (sec_asn1d_state *state)
+sec_asn1d_concat_group(sec_asn1d_state *state)
{
const void ***placep;
- PORT_Assert (state->place == afterGroup);
+ PORT_Assert(state->place == afterGroup);
- placep = (const void***)state->dest;
+ placep = (const void ***)state->dest;
PORT_Assert(state->subitems_head == NULL || placep != NULL);
if (placep != NULL) {
- struct subitem *item;
- const void **group;
- int count;
-
- count = 0;
- item = state->subitems_head;
- while (item != NULL) {
- PORT_Assert (item->next != NULL || item == state->subitems_tail);
- count++;
- item = item->next;
- }
-
- group = (const void**)sec_asn1d_zalloc (state->top->their_pool,
- (count + 1) * (sizeof(void *)));
- if (group == NULL) {
- state->top->status = decodeError;
- return;
- }
-
- *placep = group;
-
- item = state->subitems_head;
- while (item != NULL) {
- *group++ = item->data;
- item = item->next;
- }
- *group = NULL;
-
- /*
- * Because we use arenas and have a mark set, we later free
- * everything we have allocated, so this does *not* present
- * a memory leak (it is just temporarily left dangling).
- */
- state->subitems_head = state->subitems_tail = NULL;
+ struct subitem *item;
+ const void **group;
+ int count;
+
+ count = 0;
+ item = state->subitems_head;
+ while (item != NULL) {
+ PORT_Assert(item->next != NULL || item == state->subitems_tail);
+ count++;
+ item = item->next;
+ }
+
+ group = (const void **)sec_asn1d_zalloc(state->top->their_pool,
+ (count + 1) * (sizeof(void *)));
+ if (group == NULL) {
+ state->top->status = decodeError;
+ return;
+ }
+
+ *placep = group;
+
+ item = state->subitems_head;
+ while (item != NULL) {
+ *group++ = item->data;
+ item = item->next;
+ }
+ *group = NULL;
+
+ /*
+ * Because we use arenas and have a mark set, we later free
+ * everything we have allocated, so this does *not* present
+ * a memory leak (it is just temporarily left dangling).
+ */
+ state->subitems_head = state->subitems_tail = NULL;
}
state->place = afterEndOfContents;
}
-
/*
* For those states that push a child to handle a subtemplate,
* "absorb" that child (transfer necessary information).
*/
static void
-sec_asn1d_absorb_child (sec_asn1d_state *state)
+sec_asn1d_absorb_child(sec_asn1d_state *state)
{
/*
* There is absolutely supposed to be a child there.
*/
- PORT_Assert (state->child != NULL);
+ PORT_Assert(state->child != NULL);
/*
* Inherit the missing status of our child, and do the ugly
@@ -2334,16 +2324,16 @@ sec_asn1d_absorb_child (sec_asn1d_state *state)
*/
state->missing = state->child->missing;
if (state->missing) {
- state->found_tag_number = state->child->found_tag_number;
- state->found_tag_modifiers = state->child->found_tag_modifiers;
- state->endofcontents = state->child->endofcontents;
+ state->found_tag_number = state->child->found_tag_number;
+ state->found_tag_modifiers = state->child->found_tag_modifiers;
+ state->endofcontents = state->child->endofcontents;
}
/*
* Add in number of bytes consumed by child.
* (Only EXPLICIT should have already consumed bytes itself.)
*/
- PORT_Assert (state->place == afterExplicit || state->consumed == 0);
+ PORT_Assert(state->place == afterExplicit || state->consumed == 0);
state->consumed += state->child->consumed;
/*
@@ -2351,34 +2341,34 @@ sec_asn1d_absorb_child (sec_asn1d_state *state)
* EXPLICIT field.
*/
if (state->pending) {
- PORT_Assert (!state->indefinite);
- PORT_Assert (state->place == afterExplicit);
-
- /*
- * If we had a definite-length explicit, then what the child
- * consumed should be what was left pending.
- */
- if (state->pending != state->child->consumed) {
- if (state->pending < state->child->consumed) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return;
- }
- /*
- * Okay, this is a hack. It *should* be an error whether
- * pending is too big or too small, but it turns out that
- * we had a bug in our *old* DER encoder that ended up
- * counting an explicit header twice in the case where
- * the underlying type was an ANY. So, because we cannot
- * prevent receiving these (our own certificate server can
- * send them to us), we need to be lenient and accept them.
- * To do so, we need to pretend as if we read all of the
- * bytes that the header said we would find, even though
- * we actually came up short.
- */
- state->consumed += (state->pending - state->child->consumed);
- }
- state->pending = 0;
+ PORT_Assert(!state->indefinite);
+ PORT_Assert(state->place == afterExplicit);
+
+ /*
+ * If we had a definite-length explicit, then what the child
+ * consumed should be what was left pending.
+ */
+ if (state->pending != state->child->consumed) {
+ if (state->pending < state->child->consumed) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return;
+ }
+ /*
+ * Okay, this is a hack. It *should* be an error whether
+ * pending is too big or too small, but it turns out that
+ * we had a bug in our *old* DER encoder that ended up
+ * counting an explicit header twice in the case where
+ * the underlying type was an ANY. So, because we cannot
+ * prevent receiving these (our own certificate server can
+ * send them to us), we need to be lenient and accept them.
+ * To do so, we need to pretend as if we read all of the
+ * bytes that the header said we would find, even though
+ * we actually came up short.
+ */
+ state->consumed += (state->pending - state->child->consumed);
+ }
+ state->pending = 0;
}
/*
@@ -2392,90 +2382,87 @@ sec_asn1d_absorb_child (sec_asn1d_state *state)
* for an indefinite-length EXPLICIT; for simplicity though we assert
* that but let the end-of-contents code do the real determination.)
*/
- PORT_Assert (state->place == afterExplicit || (! state->indefinite));
+ PORT_Assert(state->place == afterExplicit || (!state->indefinite));
state->place = beforeEndOfContents;
}
-
static void
-sec_asn1d_prepare_for_end_of_contents (sec_asn1d_state *state)
+sec_asn1d_prepare_for_end_of_contents(sec_asn1d_state *state)
{
- PORT_Assert (state->place == beforeEndOfContents);
+ PORT_Assert(state->place == beforeEndOfContents);
if (state->indefinite) {
- state->place = duringEndOfContents;
- state->pending = 2;
+ state->place = duringEndOfContents;
+ state->pending = 2;
} else {
- state->place = afterEndOfContents;
+ state->place = afterEndOfContents;
}
}
-
static unsigned long
-sec_asn1d_parse_end_of_contents (sec_asn1d_state *state,
- const char *buf, unsigned long len)
+sec_asn1d_parse_end_of_contents(sec_asn1d_state *state,
+ const char *buf, unsigned long len)
{
unsigned int i;
- PORT_Assert (state->pending <= 2);
- PORT_Assert (state->place == duringEndOfContents);
+ PORT_Assert(state->pending <= 2);
+ PORT_Assert(state->place == duringEndOfContents);
if (len == 0) {
- state->top->status = needBytes;
- return 0;
+ state->top->status = needBytes;
+ return 0;
}
if (state->pending < len)
- len = state->pending;
+ len = state->pending;
for (i = 0; i < len; i++) {
- if (buf[i] != 0) {
- /*
- * We expect to find only zeros; if not, just give up.
- */
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return 0;
- }
+ if (buf[i] != 0) {
+ /*
+ * We expect to find only zeros; if not, just give up.
+ */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return 0;
+ }
}
state->pending -= len;
if (state->pending == 0) {
- state->place = afterEndOfContents;
- state->endofcontents = PR_TRUE;
+ state->place = afterEndOfContents;
+ state->endofcontents = PR_TRUE;
}
return len;
}
-
static void
-sec_asn1d_pop_state (sec_asn1d_state *state)
+sec_asn1d_pop_state(sec_asn1d_state *state)
{
-#if 0 /* XXX I think this should always be handled explicitly by parent? */
+#if 0 /* XXX I think this should always be handled explicitly by parent? */
/*
* Account for our child.
*/
if (state->child != NULL) {
- state->consumed += state->child->consumed;
- if (state->pending) {
- PORT_Assert (!state->indefinite);
- if (state->child->consumed > state->pending) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- } else {
- state->pending -= state->child->consumed;
- }
- }
- state->child->consumed = 0;
- }
-#endif /* XXX */
+ state->consumed += state->child->consumed;
+ if (state->pending) {
+ PORT_Assert (!state->indefinite);
+ if (state->child->consumed > state->pending) {
+ PORT_SetError (SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ } else {
+ state->pending -= state->child->consumed;
+ }
+ }
+ state->child->consumed = 0;
+ }
+#endif /* XXX */
/*
* Free our child.
*/
- sec_asn1d_free_child (state, PR_FALSE);
+ sec_asn1d_free_child(state, PR_FALSE);
/*
* Just make my parent be the current state. It will then clean
@@ -2485,33 +2472,33 @@ sec_asn1d_pop_state (sec_asn1d_state *state)
}
static sec_asn1d_state *
-sec_asn1d_before_choice (sec_asn1d_state *state)
+sec_asn1d_before_choice(sec_asn1d_state *state)
{
sec_asn1d_state *child;
if (state->allocate) {
- void *dest;
+ void *dest;
- dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
- if ((void *)NULL == dest) {
- state->top->status = decodeError;
- return (sec_asn1d_state *)NULL;
- }
+ dest = sec_asn1d_zalloc(state->top->their_pool, state->theTemplate->size);
+ if ((void *)NULL == dest) {
+ state->top->status = decodeError;
+ return (sec_asn1d_state *)NULL;
+ }
- state->dest = (char *)dest + state->theTemplate->offset;
+ state->dest = (char *)dest + state->theTemplate->offset;
}
- child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
- (char *)state->dest - state->theTemplate->offset,
- PR_FALSE);
+ child = sec_asn1d_push_state(state->top, state->theTemplate + 1,
+ (char *)state->dest - state->theTemplate->offset,
+ PR_FALSE);
if ((sec_asn1d_state *)NULL == child) {
- return (sec_asn1d_state *)NULL;
+ return (sec_asn1d_state *)NULL;
}
sec_asn1d_scrub_state(child);
child = sec_asn1d_init_state_based_on_template(child);
if ((sec_asn1d_state *)NULL == child) {
- return (sec_asn1d_state *)NULL;
+ return (sec_asn1d_state *)NULL;
}
child->optional = PR_TRUE;
@@ -2522,94 +2509,94 @@ sec_asn1d_before_choice (sec_asn1d_state *state)
}
static sec_asn1d_state *
-sec_asn1d_during_choice (sec_asn1d_state *state)
+sec_asn1d_during_choice(sec_asn1d_state *state)
{
sec_asn1d_state *child = state->child;
-
+
PORT_Assert((sec_asn1d_state *)NULL != child);
if (child->missing) {
- unsigned char child_found_tag_modifiers = 0;
- unsigned long child_found_tag_number = 0;
- void * dest;
-
- state->consumed += child->consumed;
-
- if (child->endofcontents) {
- /* This choice is probably the first item in a GROUP
- ** (e.g. SET_OF) that was indefinite-length encoded.
- ** We're actually at the end of that GROUP.
- ** We look up the stack to be sure that we find
- ** a state with indefinite length encoding before we
- ** find a state (like a SEQUENCE) that is definite.
- */
- child->place = notInUse;
- state->place = afterChoice;
- state->endofcontents = PR_TRUE; /* propagate this up */
- if (sec_asn1d_parent_allows_EOC(state))
- return state;
- PORT_SetError(SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return NULL;
- }
-
- dest = (char *)child->dest - child->theTemplate->offset;
- child->theTemplate++;
-
- if (0 == child->theTemplate->kind) {
- /* Ran out of choices */
- PORT_SetError(SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return (sec_asn1d_state *)NULL;
- }
- child->dest = (char *)dest + child->theTemplate->offset;
-
- /* cargo'd from next_in_sequence innards */
- if (state->pending) {
- PORT_Assert(!state->indefinite);
- if (child->consumed > state->pending) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return NULL;
- }
- state->pending -= child->consumed;
- if (0 == state->pending) {
- /* XXX uh.. not sure if I should have stopped this
- * from happening before. */
- PORT_Assert(0);
- PORT_SetError(SEC_ERROR_BAD_DER);
- state->top->status = decodeError;
- return (sec_asn1d_state *)NULL;
- }
- }
-
- child->consumed = 0;
- sec_asn1d_scrub_state(child);
-
- /* move it on top again */
- state->top->current = child;
-
- child_found_tag_modifiers = child->found_tag_modifiers;
- child_found_tag_number = child->found_tag_number;
-
- child = sec_asn1d_init_state_based_on_template(child);
- if ((sec_asn1d_state *)NULL == child) {
- return (sec_asn1d_state *)NULL;
- }
-
- /* copy our findings to the new top */
- child->found_tag_modifiers = child_found_tag_modifiers;
- child->found_tag_number = child_found_tag_number;
-
- child->optional = PR_TRUE;
- child->place = afterIdentifier;
-
- return child;
- }
+ unsigned char child_found_tag_modifiers = 0;
+ unsigned long child_found_tag_number = 0;
+ void *dest;
+
+ state->consumed += child->consumed;
+
+ if (child->endofcontents) {
+ /* This choice is probably the first item in a GROUP
+ ** (e.g. SET_OF) that was indefinite-length encoded.
+ ** We're actually at the end of that GROUP.
+ ** We look up the stack to be sure that we find
+ ** a state with indefinite length encoding before we
+ ** find a state (like a SEQUENCE) that is definite.
+ */
+ child->place = notInUse;
+ state->place = afterChoice;
+ state->endofcontents = PR_TRUE; /* propagate this up */
+ if (sec_asn1d_parent_allows_EOC(state))
+ return state;
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return NULL;
+ }
+
+ dest = (char *)child->dest - child->theTemplate->offset;
+ child->theTemplate++;
+
+ if (0 == child->theTemplate->kind) {
+ /* Ran out of choices */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return (sec_asn1d_state *)NULL;
+ }
+ child->dest = (char *)dest + child->theTemplate->offset;
+
+ /* cargo'd from next_in_sequence innards */
+ if (state->pending) {
+ PORT_Assert(!state->indefinite);
+ if (child->consumed > state->pending) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return NULL;
+ }
+ state->pending -= child->consumed;
+ if (0 == state->pending) {
+ /* XXX uh.. not sure if I should have stopped this
+ * from happening before. */
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ state->top->status = decodeError;
+ return (sec_asn1d_state *)NULL;
+ }
+ }
+
+ child->consumed = 0;
+ sec_asn1d_scrub_state(child);
+
+ /* move it on top again */
+ state->top->current = child;
+
+ child_found_tag_modifiers = child->found_tag_modifiers;
+ child_found_tag_number = child->found_tag_number;
+
+ child = sec_asn1d_init_state_based_on_template(child);
+ if ((sec_asn1d_state *)NULL == child) {
+ return (sec_asn1d_state *)NULL;
+ }
+
+ /* copy our findings to the new top */
+ child->found_tag_modifiers = child_found_tag_modifiers;
+ child->found_tag_number = child_found_tag_number;
+
+ child->optional = PR_TRUE;
+ child->place = afterIdentifier;
+
+ return child;
+ }
if ((void *)NULL != state->dest) {
- /* Store the enum */
- int *which = (int *)state->dest;
- *which = (int)child->theTemplate->size;
+ /* Store the enum */
+ int *which = (int *)state->dest;
+ *which = (int)child->theTemplate->size;
}
child->place = notInUse;
@@ -2619,7 +2606,7 @@ sec_asn1d_during_choice (sec_asn1d_state *state)
}
static void
-sec_asn1d_after_choice (sec_asn1d_state *state)
+sec_asn1d_after_choice(sec_asn1d_state *state)
{
state->consumed += state->child->consumed;
state->child->consumed = 0;
@@ -2634,13 +2621,13 @@ sec_asn1d_uinteger(SECItem *src)
int len;
if (src->len > 5 || (src->len > 4 && src->data[0] == 0))
- return 0;
+ return 0;
value = 0;
len = src->len;
while (len) {
- value <<= 8;
- value |= src->data[--len];
+ value <<= 8;
+ value |= src->data[--len];
}
return value;
}
@@ -2650,31 +2637,31 @@ SEC_ASN1DecodeInteger(SECItem *src, unsigned long *value)
{
unsigned long v;
unsigned int i;
-
+
if (src == NULL) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
if (src->len > sizeof(unsigned long)) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
if (src->data == NULL) {
- PORT_SetError(SEC_ERROR_INVALID_ARGS);
- return SECFailure;
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
}
if (src->data[0] & 0x80)
- v = -1; /* signed and negative - start with all 1's */
+ v = -1; /* signed and negative - start with all 1's */
else
- v = 0;
+ v = 0;
- for (i= 0; i < src->len; i++) {
- /* shift in next byte */
- v <<= 8;
- v |= src->data[i];
+ for (i = 0; i < src->len; i++) {
+ /* shift in next byte */
+ v <<= 8;
+ v |= src->data[i];
}
*value = v;
return SECSuccess;
@@ -2703,18 +2690,17 @@ dump_states(SEC_ASN1DecoderContext *cx)
state->theTemplate,
kindBuf);
printf(" %s", (state->place >= 0 && state->place <= notInUse)
- ? place_names[ state->place ]
- : "(undefined)");
+ ? place_names[state->place]
+ : "(undefined)");
if (!i)
printf(", expect 0x%02x",
state->expect_tag_number | state->expect_tag_modifiers);
printf("%s%s%s %d\n",
- state->indefinite ? ", indef" : "",
- state->missing ? ", miss" : "",
- state->endofcontents ? ", EOC" : "",
- state->pending
- );
+ state->indefinite ? ", indef" : "",
+ state->missing ? ", miss" : "",
+ state->endofcontents ? ", EOC" : "",
+ state->pending);
}
return;
@@ -2722,8 +2708,8 @@ dump_states(SEC_ASN1DecoderContext *cx)
#endif /* DEBUG_ASN1D_STATES */
SECStatus
-SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,
- const char *buf, unsigned long len)
+SEC_ASN1DecoderUpdate(SEC_ASN1DecoderContext *cx,
+ const char *buf, unsigned long len)
{
sec_asn1d_state *state = NULL;
unsigned long consumed;
@@ -2731,341 +2717,328 @@ SEC_ASN1DecoderUpdate (SEC_ASN1DecoderContext *cx,
sec_asn1d_state *stateEnd = cx->current;
if (cx->status == needBytes)
- cx->status = keepGoing;
+ cx->status = keepGoing;
while (cx->status == keepGoing) {
- state = cx->current;
- what = SEC_ASN1_Contents;
- consumed = 0;
+ state = cx->current;
+ what = SEC_ASN1_Contents;
+ consumed = 0;
#ifdef DEBUG_ASN1D_STATES
printf("\nPLACE = %s, next byte = 0x%02x, %08x[%d]\n",
- (state->place >= 0 && state->place <= notInUse) ?
- place_names[ state->place ] : "(undefined)",
- (unsigned int)((unsigned char *)buf)[ consumed ],
+ (state->place >= 0 && state->place <= notInUse) ? place_names[state->place] : "(undefined)",
+ (unsigned int)((unsigned char *)buf)[consumed],
buf, consumed);
dump_states(cx);
#endif /* DEBUG_ASN1D_STATES */
- switch (state->place) {
- case beforeIdentifier:
- consumed = sec_asn1d_parse_identifier (state, buf, len);
- what = SEC_ASN1_Identifier;
- break;
- case duringIdentifier:
- consumed = sec_asn1d_parse_more_identifier (state, buf, len);
- what = SEC_ASN1_Identifier;
- break;
- case afterIdentifier:
- sec_asn1d_confirm_identifier (state);
- break;
- case beforeLength:
- consumed = sec_asn1d_parse_length (state, buf, len);
- what = SEC_ASN1_Length;
- break;
- case duringLength:
- consumed = sec_asn1d_parse_more_length (state, buf, len);
- what = SEC_ASN1_Length;
- break;
- case afterLength:
- sec_asn1d_prepare_for_contents (state);
- break;
- case beforeBitString:
- consumed = sec_asn1d_parse_bit_string (state, buf, len);
- break;
- case duringBitString:
- consumed = sec_asn1d_parse_more_bit_string (state, buf, len);
- break;
- case duringConstructedString:
- sec_asn1d_next_substring (state);
- break;
- case duringGroup:
- sec_asn1d_next_in_group (state);
- break;
- case duringLeaf:
- consumed = sec_asn1d_parse_leaf (state, buf, len);
- break;
- case duringSaveEncoding:
- sec_asn1d_reuse_encoding (state);
- if (cx->status == decodeError) {
- /* recursive call has already popped all states from stack.
- ** Bail out quickly.
- */
- return SECFailure;
- }
- if (cx->status == needBytes) {
- /* recursive call wanted more data. Fatal. Clean up below. */
- PORT_SetError (SEC_ERROR_BAD_DER);
- cx->status = decodeError;
- }
- break;
- case duringSequence:
- sec_asn1d_next_in_sequence (state);
- break;
- case afterConstructedString:
- sec_asn1d_concat_substrings (state);
- break;
- case afterExplicit:
- case afterImplicit:
- case afterInline:
- case afterPointer:
- sec_asn1d_absorb_child (state);
- break;
- case afterGroup:
- sec_asn1d_concat_group (state);
- break;
- case afterSaveEncoding:
- /* SEC_ASN1DecoderUpdate has called itself recursively to
- ** decode SAVEd encoded data, and now is done decoding that.
- ** Return to the calling copy of SEC_ASN1DecoderUpdate.
- */
- return SECSuccess;
- case beforeEndOfContents:
- sec_asn1d_prepare_for_end_of_contents (state);
- break;
- case duringEndOfContents:
- consumed = sec_asn1d_parse_end_of_contents (state, buf, len);
- what = SEC_ASN1_EndOfContents;
- break;
- case afterEndOfContents:
- sec_asn1d_pop_state (state);
- break;
- case beforeChoice:
- state = sec_asn1d_before_choice(state);
- break;
- case duringChoice:
- state = sec_asn1d_during_choice(state);
+ switch (state->place) {
+ case beforeIdentifier:
+ consumed = sec_asn1d_parse_identifier(state, buf, len);
+ what = SEC_ASN1_Identifier;
+ break;
+ case duringIdentifier:
+ consumed = sec_asn1d_parse_more_identifier(state, buf, len);
+ what = SEC_ASN1_Identifier;
+ break;
+ case afterIdentifier:
+ sec_asn1d_confirm_identifier(state);
+ break;
+ case beforeLength:
+ consumed = sec_asn1d_parse_length(state, buf, len);
+ what = SEC_ASN1_Length;
+ break;
+ case duringLength:
+ consumed = sec_asn1d_parse_more_length(state, buf, len);
+ what = SEC_ASN1_Length;
+ break;
+ case afterLength:
+ sec_asn1d_prepare_for_contents(state);
+ break;
+ case beforeBitString:
+ consumed = sec_asn1d_parse_bit_string(state, buf, len);
+ break;
+ case duringBitString:
+ consumed = sec_asn1d_parse_more_bit_string(state, buf, len);
+ break;
+ case duringConstructedString:
+ sec_asn1d_next_substring(state);
+ break;
+ case duringGroup:
+ sec_asn1d_next_in_group(state);
+ break;
+ case duringLeaf:
+ consumed = sec_asn1d_parse_leaf(state, buf, len);
+ break;
+ case duringSaveEncoding:
+ sec_asn1d_reuse_encoding(state);
+ if (cx->status == decodeError) {
+ /* recursive call has already popped all states from stack.
+ ** Bail out quickly.
+ */
+ return SECFailure;
+ }
+ if (cx->status == needBytes) {
+ /* recursive call wanted more data. Fatal. Clean up below. */
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ }
+ break;
+ case duringSequence:
+ sec_asn1d_next_in_sequence(state);
+ break;
+ case afterConstructedString:
+ sec_asn1d_concat_substrings(state);
+ break;
+ case afterExplicit:
+ case afterImplicit:
+ case afterInline:
+ case afterPointer:
+ sec_asn1d_absorb_child(state);
+ break;
+ case afterGroup:
+ sec_asn1d_concat_group(state);
+ break;
+ case afterSaveEncoding:
+ /* SEC_ASN1DecoderUpdate has called itself recursively to
+ ** decode SAVEd encoded data, and now is done decoding that.
+ ** Return to the calling copy of SEC_ASN1DecoderUpdate.
+ */
+ return SECSuccess;
+ case beforeEndOfContents:
+ sec_asn1d_prepare_for_end_of_contents(state);
+ break;
+ case duringEndOfContents:
+ consumed = sec_asn1d_parse_end_of_contents(state, buf, len);
+ what = SEC_ASN1_EndOfContents;
+ break;
+ case afterEndOfContents:
+ sec_asn1d_pop_state(state);
+ break;
+ case beforeChoice:
+ state = sec_asn1d_before_choice(state);
+ break;
+ case duringChoice:
+ state = sec_asn1d_during_choice(state);
+ break;
+ case afterChoice:
+ sec_asn1d_after_choice(state);
+ break;
+ case notInUse:
+ default:
+ /* This is not an error, but rather a plain old BUG! */
+ PORT_Assert(0);
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ break;
+ }
+
+ if (cx->status == decodeError)
break;
- case afterChoice:
- sec_asn1d_after_choice(state);
+
+ /* We should not consume more than we have. */
+ PORT_Assert(consumed <= len);
+ if (consumed > len) {
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
break;
- case notInUse:
- default:
- /* This is not an error, but rather a plain old BUG! */
- PORT_Assert (0);
- PORT_SetError (SEC_ERROR_BAD_DER);
- cx->status = decodeError;
- break;
- }
-
- if (cx->status == decodeError)
- break;
-
- /* We should not consume more than we have. */
- PORT_Assert (consumed <= len);
- if (consumed > len) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- cx->status = decodeError;
- break;
- }
-
- /* It might have changed, so we have to update our local copy. */
- state = cx->current;
-
- /* If it is NULL, we have popped all the way to the top. */
- if (state == NULL) {
- PORT_Assert (consumed == 0);
-#if 0 /* XXX I want this here, but it seems that we have situations (like
- * downloading a pkcs7 cert chain from some issuers) that give us a
- * length which is greater than the entire encoding. So, we cannot
- * have this be an error.
- */
- if (len > 0) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- cx->status = decodeError;
- } else
+ }
+
+ /* It might have changed, so we have to update our local copy. */
+ state = cx->current;
+
+ /* If it is NULL, we have popped all the way to the top. */
+ if (state == NULL) {
+ PORT_Assert(consumed == 0);
+#if 0 /* XXX I want this here, but it seems that we have situations (like \
+ * downloading a pkcs7 cert chain from some issuers) that give us a \
+ * length which is greater than the entire encoding. So, we cannot \
+ * have this be an error. \
+ */
+ if (len > 0) {
+ PORT_SetError (SEC_ERROR_BAD_DER);
+ cx->status = decodeError;
+ } else
#endif
- cx->status = allDone;
- break;
- }
- else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
- cx->status = allDone;
- break;
- }
-
- if (consumed == 0)
- continue;
-
- /*
- * The following check is specifically looking for an ANY
- * that is *not* also an INNER, because we need to save aside
- * all bytes in that case -- the contents parts will get
- * handled like all other contents, and the end-of-contents
- * bytes are added by the concat code, but the outer header
- * bytes need to get saved too, so we do them explicitly here.
- */
- if (state->underlying_kind == SEC_ASN1_ANY
- && !cx->filter_only && (what == SEC_ASN1_Identifier
- || what == SEC_ASN1_Length)) {
- sec_asn1d_record_any_header (state, buf, consumed);
- }
-
- /*
- * We had some number of good, accepted bytes. If the caller
- * has registered to see them, pass them along.
- */
- if (state->top->filter_proc != NULL) {
- int depth;
-
- depth = state->depth;
- if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
- PORT_Assert (state->parent != NULL
- && state->parent->indefinite);
- depth--;
- PORT_Assert (depth == state->parent->depth);
- }
- (* state->top->filter_proc) (state->top->filter_arg,
- buf, consumed, depth, what);
- }
-
- state->consumed += consumed;
- buf += consumed;
- len -= consumed;
+ cx->status = allDone;
+ break;
+ } else if (state->theTemplate->kind == SEC_ASN1_SKIP_REST) {
+ cx->status = allDone;
+ break;
+ }
+
+ if (consumed == 0)
+ continue;
+
+ /*
+ * The following check is specifically looking for an ANY
+ * that is *not* also an INNER, because we need to save aside
+ * all bytes in that case -- the contents parts will get
+ * handled like all other contents, and the end-of-contents
+ * bytes are added by the concat code, but the outer header
+ * bytes need to get saved too, so we do them explicitly here.
+ */
+ if (state->underlying_kind == SEC_ASN1_ANY && !cx->filter_only && (what == SEC_ASN1_Identifier || what == SEC_ASN1_Length)) {
+ sec_asn1d_record_any_header(state, buf, consumed);
+ }
+
+ /*
+ * We had some number of good, accepted bytes. If the caller
+ * has registered to see them, pass them along.
+ */
+ if (state->top->filter_proc != NULL) {
+ int depth;
+
+ depth = state->depth;
+ if (what == SEC_ASN1_EndOfContents && !state->indefinite) {
+ PORT_Assert(state->parent != NULL && state->parent->indefinite);
+ depth--;
+ PORT_Assert(depth == state->parent->depth);
+ }
+ (*state->top->filter_proc)(state->top->filter_arg,
+ buf, consumed, depth, what);
+ }
+
+ state->consumed += consumed;
+ buf += consumed;
+ len -= consumed;
}
if (cx->status == decodeError) {
- while (state != NULL && stateEnd->parent!=state) {
- sec_asn1d_free_child (state, PR_TRUE);
- state = state->parent;
- }
-#ifdef SEC_ASN1D_FREE_ON_ERROR /*
- * XXX This does not work because we can
- * end up leaving behind dangling pointers
- * to stuff that was allocated. In order
- * to make this really work (which would
- * be a good thing, I think), we need to
- * keep track of every place/pointer that
- * was allocated and make sure to NULL it
- * out before we then free back to the mark.
- */
- if (cx->their_pool != NULL) {
- PORT_Assert (cx->their_mark != NULL);
- PORT_ArenaRelease (cx->their_pool, cx->their_mark);
- cx->their_mark = NULL;
- }
+ while (state != NULL && stateEnd->parent != state) {
+ sec_asn1d_free_child(state, PR_TRUE);
+ state = state->parent;
+ }
+#ifdef SEC_ASN1D_FREE_ON_ERROR /* \
+ * XXX This does not work because we can \
+ * end up leaving behind dangling pointers \
+ * to stuff that was allocated. In order \
+ * to make this really work (which would \
+ * be a good thing, I think), we need to \
+ * keep track of every place/pointer that \
+ * was allocated and make sure to NULL it \
+ * out before we then free back to the mark. \
+ */
+ if (cx->their_pool != NULL) {
+ PORT_Assert(cx->their_mark != NULL);
+ PORT_ArenaRelease(cx->their_pool, cx->their_mark);
+ cx->their_mark = NULL;
+ }
#endif
- return SECFailure;
+ return SECFailure;
}
-#if 0 /* XXX This is what I want, but cannot have because it seems we
- * have situations (like when downloading a pkcs7 cert chain from
- * some issuers) that give us a total length which is greater than
- * the entire encoding. So, we have to allow allDone to have a
- * remaining length greater than zero. I wanted to catch internal
- * bugs with this, noticing when we do not have the right length.
- * Oh well.
- */
+#if 0 /* XXX This is what I want, but cannot have because it seems we \
+ * have situations (like when downloading a pkcs7 cert chain from \
+ * some issuers) that give us a total length which is greater than \
+ * the entire encoding. So, we have to allow allDone to have a \
+ * remaining length greater than zero. I wanted to catch internal \
+ * bugs with this, noticing when we do not have the right length. \
+ * Oh well. \
+ */
PORT_Assert (len == 0
- && (cx->status == needBytes || cx->status == allDone));
+ && (cx->status == needBytes || cx->status == allDone));
#else
- PORT_Assert ((len == 0 && cx->status == needBytes)
- || cx->status == allDone);
+ PORT_Assert((len == 0 && cx->status == needBytes) || cx->status == allDone);
#endif
return SECSuccess;
}
-
SECStatus
-SEC_ASN1DecoderFinish (SEC_ASN1DecoderContext *cx)
+SEC_ASN1DecoderFinish(SEC_ASN1DecoderContext *cx)
{
SECStatus rv;
if (cx->status == needBytes) {
- PORT_SetError (SEC_ERROR_BAD_DER);
- rv = SECFailure;
+ PORT_SetError(SEC_ERROR_BAD_DER);
+ rv = SECFailure;
} else {
- rv = SECSuccess;
+ rv = SECSuccess;
}
/*
* XXX anything else that needs to be finished?
*/
- PORT_FreeArena (cx->our_pool, PR_TRUE);
+ PORT_FreeArena(cx->our_pool, PR_TRUE);
return rv;
}
-
SEC_ASN1DecoderContext *
-SEC_ASN1DecoderStart (PLArenaPool *their_pool, void *dest,
- const SEC_ASN1Template *theTemplate)
+SEC_ASN1DecoderStart(PLArenaPool *their_pool, void *dest,
+ const SEC_ASN1Template *theTemplate)
{
PLArenaPool *our_pool;
SEC_ASN1DecoderContext *cx;
- our_pool = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE);
+ our_pool = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (our_pool == NULL)
- return NULL;
+ return NULL;
- cx = (SEC_ASN1DecoderContext*)PORT_ArenaZAlloc (our_pool, sizeof(*cx));
+ cx = (SEC_ASN1DecoderContext *)PORT_ArenaZAlloc(our_pool, sizeof(*cx));
if (cx == NULL) {
- PORT_FreeArena (our_pool, PR_FALSE);
- return NULL;
+ PORT_FreeArena(our_pool, PR_FALSE);
+ return NULL;
}
cx->our_pool = our_pool;
if (their_pool != NULL) {
- cx->their_pool = their_pool;
+ cx->their_pool = their_pool;
#ifdef SEC_ASN1D_FREE_ON_ERROR
- cx->their_mark = PORT_ArenaMark (their_pool);
+ cx->their_mark = PORT_ArenaMark(their_pool);
#endif
}
cx->status = needBytes;
- if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL
- || sec_asn1d_init_state_based_on_template (cx->current) == NULL) {
- /*
- * Trouble initializing (probably due to failed allocations)
- * requires that we just give up.
- */
- PORT_FreeArena (our_pool, PR_FALSE);
- return NULL;
+ if (sec_asn1d_push_state(cx, theTemplate, dest, PR_FALSE) == NULL || sec_asn1d_init_state_based_on_template(cx->current) == NULL) {
+ /*
+ * Trouble initializing (probably due to failed allocations)
+ * requires that we just give up.
+ */
+ PORT_FreeArena(our_pool, PR_FALSE);
+ return NULL;
}
return cx;
}
-
void
-SEC_ASN1DecoderSetFilterProc (SEC_ASN1DecoderContext *cx,
- SEC_ASN1WriteProc fn, void *arg,
- PRBool only)
+SEC_ASN1DecoderSetFilterProc(SEC_ASN1DecoderContext *cx,
+ SEC_ASN1WriteProc fn, void *arg,
+ PRBool only)
{
/* check that we are "between" fields here */
- PORT_Assert (cx->during_notify);
+ PORT_Assert(cx->during_notify);
cx->filter_proc = fn;
cx->filter_arg = arg;
cx->filter_only = only;
}
-
void
-SEC_ASN1DecoderClearFilterProc (SEC_ASN1DecoderContext *cx)
+SEC_ASN1DecoderClearFilterProc(SEC_ASN1DecoderContext *cx)
{
/* check that we are "between" fields here */
- PORT_Assert (cx->during_notify);
+ PORT_Assert(cx->during_notify);
cx->filter_proc = NULL;
cx->filter_arg = NULL;
cx->filter_only = PR_FALSE;
}
-
void
-SEC_ASN1DecoderSetNotifyProc (SEC_ASN1DecoderContext *cx,
- SEC_ASN1NotifyProc fn, void *arg)
+SEC_ASN1DecoderSetNotifyProc(SEC_ASN1DecoderContext *cx,
+ SEC_ASN1NotifyProc fn, void *arg)
{
cx->notify_proc = fn;
cx->notify_arg = arg;
}
-
void
-SEC_ASN1DecoderClearNotifyProc (SEC_ASN1DecoderContext *cx)
+SEC_ASN1DecoderClearNotifyProc(SEC_ASN1DecoderContext *cx)
{
cx->notify_proc = NULL;
- cx->notify_arg = NULL; /* not necessary; just being clean */
+ cx->notify_arg = NULL; /* not necessary; just being clean */
}
void
@@ -3076,40 +3049,39 @@ SEC_ASN1DecoderAbort(SEC_ASN1DecoderContext *cx, int error)
cx->status = decodeError;
}
-
SECStatus
-SEC_ASN1Decode (PLArenaPool *poolp, void *dest,
- const SEC_ASN1Template *theTemplate,
- const char *buf, long len)
+SEC_ASN1Decode(PLArenaPool *poolp, void *dest,
+ const SEC_ASN1Template *theTemplate,
+ const char *buf, long len)
{
SEC_ASN1DecoderContext *dcx;
SECStatus urv, frv;
- dcx = SEC_ASN1DecoderStart (poolp, dest, theTemplate);
+ dcx = SEC_ASN1DecoderStart(poolp, dest, theTemplate);
if (dcx == NULL)
- return SECFailure;
+ return SECFailure;
- urv = SEC_ASN1DecoderUpdate (dcx, buf, len);
- frv = SEC_ASN1DecoderFinish (dcx);
+ urv = SEC_ASN1DecoderUpdate(dcx, buf, len);
+ frv = SEC_ASN1DecoderFinish(dcx);
if (urv != SECSuccess)
- return urv;
+ return urv;
return frv;
}
-
SECStatus
-SEC_ASN1DecodeItem (PLArenaPool *poolp, void *dest,
- const SEC_ASN1Template *theTemplate,
- const SECItem *src)
+SEC_ASN1DecodeItem(PLArenaPool *poolp, void *dest,
+ const SEC_ASN1Template *theTemplate,
+ const SECItem *src)
{
- return SEC_ASN1Decode (poolp, dest, theTemplate,
- (const char *)src->data, src->len);
+ return SEC_ASN1Decode(poolp, dest, theTemplate,
+ (const char *)src->data, src->len);
}
#ifdef DEBUG_ASN1D_STATES
-void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
+void
+sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
{
printf("Assertion failed, \"%s\", file %s, line %d\n", s, file, ln);
fflush(stdout);
@@ -3121,15 +3093,15 @@ void sec_asn1d_Assert(const char *s, const char *file, PRIntn ln)
* and sets of same.
*
* If you need to add a new one, please note the following:
- * - For each new basic type you should add *four* templates:
- * one plain, one PointerTo, one SequenceOf and one SetOf.
- * - If the new type can be constructed (meaning, it is a
- * *string* type according to BER/DER rules), then you should
- * or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
- * See the definition of the OctetString template for an example.
- * - It may not be obvious, but these are in *alphabetical*
- * order based on the SEC_ASN1_XXX name; so put new ones in
- * the appropriate place.
+ * - For each new basic type you should add *four* templates:
+ * one plain, one PointerTo, one SequenceOf and one SetOf.
+ * - If the new type can be constructed (meaning, it is a
+ * *string* type according to BER/DER rules), then you should
+ * or-in SEC_ASN1_MAY_STREAM to the type in the basic template.
+ * See the definition of the OctetString template for an example.
+ * - It may not be obvious, but these are in *alphabetical*
+ * order based on the SEC_ASN1_XXX name; so put new ones in
+ * the appropriate place.
*/
const SEC_ASN1Template SEC_SequenceOfAnyTemplate[] = {
@@ -3273,7 +3245,7 @@ const SEC_ASN1Template SEC_SetOfOctetStringTemplate[] = {
#endif
const SEC_ASN1Template SEC_PrintableStringTemplate[] = {
- { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
+ { SEC_ASN1_PRINTABLE_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
};
#if 0
@@ -3313,7 +3285,7 @@ const SEC_ASN1Template SEC_SetOfT61StringTemplate[] = {
#endif
const SEC_ASN1Template SEC_UniversalStringTemplate[] = {
- { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem)}
+ { SEC_ASN1_UNIVERSAL_STRING | SEC_ASN1_MAY_STREAM, 0, NULL, sizeof(SECItem) }
};
#if 0
@@ -3387,7 +3359,6 @@ const SEC_ASN1Template SEC_SkipTemplate[] = {
{ SEC_ASN1_SKIP }
};
-
/* These functions simply return the address of the above-declared templates.
** This is necessary for Windows DLLs. Sigh.
*/
@@ -3400,4 +3371,3 @@ SEC_ASN1_CHOOSER_IMPLEMENT(SEC_UniversalStringTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PrintableStringTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_T61StringTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SEC_PointerToGeneralizedTimeTemplate)
-