diff options
author | javi%netscape.com <devnull@localhost> | 2001-08-03 22:31:34 +0000 |
---|---|---|
committer | javi%netscape.com <devnull@localhost> | 2001-08-03 22:31:34 +0000 |
commit | b8c70b4cdf91252056ac6431fa5c639d2c2b5ca3 (patch) | |
tree | d242483180ed68f1ba3d260a2bdee981b04b6e95 | |
parent | 9a3c19a5e8282046cc9ea6093d360764f01d33f6 (diff) | |
download | nss-hg-b8c70b4cdf91252056ac6431fa5c639d2c2b5ca3.tar.gz |
Bringing patches from trunk over to the branch.
-rw-r--r-- | security/nss/lib/util/secasn1e.c | 60 | ||||
-rw-r--r-- | security/nss/lib/util/secasn1t.h | 7 |
2 files changed, 44 insertions, 23 deletions
diff --git a/security/nss/lib/util/secasn1e.c b/security/nss/lib/util/secasn1e.c index cb91934bd..8520a2afe 100644 --- a/security/nss/lib/util/secasn1e.c +++ b/security/nss/lib/util/secasn1e.c @@ -83,7 +83,8 @@ typedef struct sec_asn1e_state_struct { indefinite, /* need end-of-contents */ is_string, /* encoding a simple string or an ANY */ may_stream, /* when streaming, do indefinite encoding */ - optional; /* omit field if it has no contents */ + optional, /* omit field if it has no contents */ + ignore_stream; /* ignore streaming value of sub-template */ } sec_asn1e_state; /* @@ -184,7 +185,7 @@ sec_asn1e_notify_after (SEC_ASN1EncoderContext *cx, void *src, int depth) static sec_asn1e_state * sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) { - PRBool explicit, is_string, may_stream, optional, universal; + PRBool explicit, is_string, may_stream, optional, universal, ignore_stream; unsigned char tag_modifiers; unsigned long encode_kind, under_kind; unsigned long tag_number; @@ -206,6 +207,9 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) may_stream = (encode_kind & SEC_ASN1_MAY_STREAM) ? PR_TRUE : PR_FALSE; encode_kind &= ~SEC_ASN1_MAY_STREAM; + ignore_stream = (encode_kind & SEC_ASN1_NO_STREAM) ? PR_TRUE : PR_FALSE; + encode_kind &= ~SEC_ASN1_NO_STREAM; + /* Just clear this to get it out of the way; we do not need it here */ encode_kind &= ~SEC_ASN1_DYNAMIC; @@ -290,7 +294,8 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) under_kind = state->theTemplate->kind; if (under_kind & SEC_ASN1_MAY_STREAM) { - may_stream = PR_TRUE; + if (!ignore_stream) + may_stream = PR_TRUE; under_kind &= ~SEC_ASN1_MAY_STREAM; } } else { @@ -363,6 +368,7 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) state->may_stream = may_stream; state->is_string = is_string; state->optional = optional; + state->ignore_stream = ignore_stream; sec_asn1e_scrub_state (state); @@ -473,12 +479,27 @@ sec_asn1e_which_choice static unsigned long sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, - PRBool parentstreaming, PRBool *noheaderp) + PRBool ignoresubstream, PRBool *noheaderp) { unsigned long encode_kind, underlying_kind; PRBool explicit, optional, universal, may_stream; unsigned long len; + /* + * This function currently calculates the length in all cases + * except the following: when writing out the contents of a + * template that belongs to a state where it was a sub-template + * with the SEC_ASN1_MAY_STREAM bit set and it's parent had the + * optional bit set. The information that the parent is optional + * and that we should return the length of 0 when that length is + * present since that means the optional field is no longer present. + * So we add the ignoresubstream flag which is passed in when + * writing the contents, but for all recursive calls to + * sec_asn1e_contents_length, we pass PR_FALSE, because this + * function correctly calculates the length for children templates + * from that point on. Confused yet? At least you didn't have + * to figure it out. ;) -javi + */ encode_kind = theTemplate->kind; universal = ((encode_kind & SEC_ASN1_CLASS_MASK) == SEC_ASN1_UNIVERSAL) @@ -497,6 +518,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, /* Just clear this to get it out of the way; we do not need it here */ encode_kind &= ~SEC_ASN1_DYNAMIC; + encode_kind &= ~SEC_ASN1_NO_STREAM; if( encode_kind & SEC_ASN1_CHOICE ) { void *src2; @@ -509,8 +531,8 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, src2 = (void *)((char *)src + theTemplate[indx].offset); - return sec_asn1e_contents_length(&theTemplate[indx], src2, parentstreaming, - noheaderp); + return sec_asn1e_contents_length(&theTemplate[indx], src2, + PR_FALSE, noheaderp); } if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || !universal) { @@ -545,7 +567,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, src = (char *)src + theTemplate->offset; if (explicit) { - len = sec_asn1e_contents_length (theTemplate, src, parentstreaming, + len = sec_asn1e_contents_length (theTemplate, src, PR_FALSE, noheaderp); if (len == 0 && optional) { *noheaderp = PR_TRUE; @@ -595,7 +617,7 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, } src2 = (void *)((char *)src - theTemplate->offset + theTemplate[indx].offset); - len = sec_asn1e_contents_length(&theTemplate[indx], src2, parentstreaming, + len = sec_asn1e_contents_length(&theTemplate[indx], src2, PR_FALSE, noheaderp); } else @@ -618,9 +640,8 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, for (; *group != NULL; group++) { sub_src = (char *)(*group) + tmpt->offset; - sub_len = sec_asn1e_contents_length (tmpt, sub_src, - may_stream, noheaderp); - + sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE, + noheaderp); len += sub_len; /* * XXX The 1 below is the presumed length of the identifier; @@ -642,9 +663,8 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, len = 0; for (tmpt = theTemplate + 1; tmpt->kind; tmpt++) { sub_src = (char *)src + tmpt->offset; - sub_len = sec_asn1e_contents_length (tmpt, sub_src, - may_stream, noheaderp); - + sub_len = sec_asn1e_contents_length (tmpt, sub_src, PR_FALSE, + noheaderp); len += sub_len; /* * XXX The 1 below is the presumed length of the identifier; @@ -666,13 +686,8 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, default: len = ((SECItem *)src)->len; - if (may_stream && len == 0 && parentstreaming) - len = 1; /* if we're streaming, we may have a - * secitem w/len 0 as placeholder. - * But if the caller says we're optional, - * then we're not streaming, so we don't - * need a placeholder. - */ + if (may_stream && len == 0 && !ignoresubstream) + len = 1; /* if we're streaming, we may have a secitem w/len 0 as placeholder */ break; } @@ -703,7 +718,6 @@ sec_asn1e_write_header (sec_asn1e_state *state) } if( state->underlying_kind & SEC_ASN1_CHOICE ) { - void *src2; int indx = sec_asn1e_which_choice(state->src, state->theTemplate); if( 0 == indx ) { /* XXX set an error? "choice not found" */ @@ -732,7 +746,7 @@ sec_asn1e_write_header (sec_asn1e_state *state) */ contents_length = sec_asn1e_contents_length (state->theTemplate, state->src, - (state->parent) ? state->parent->may_stream : state->may_stream, + state->ignore_stream, &noheader); /* * We might be told explicitly not to put out a header. diff --git a/security/nss/lib/util/secasn1t.h b/security/nss/lib/util/secasn1t.h index 45f0eba60..cb56a0bd7 100644 --- a/security/nss/lib/util/secasn1t.h +++ b/security/nss/lib/util/secasn1t.h @@ -178,6 +178,13 @@ typedef struct sec_ASN1Template_struct { #define SEC_ASN1_SKIP_REST 0x80000 /* skip all following fields; only for decoding */ #define SEC_ASN1_CHOICE 0x100000 /* pick one from a template */ +#define SEC_ASN1_NO_STREAM 0X200000 /* This entry will not stream + even if the sub-template says + streaming is possible. Helps + to solve ambiguities with potential + streaming entries that are + optional */ + /* Shorthand/Aliases */ #define SEC_ASN1_SEQUENCE_OF (SEC_ASN1_GROUP | SEC_ASN1_SEQUENCE) |