diff options
author | julien.pierre.bugs%sun.com <devnull@localhost> | 2005-04-09 05:06:34 +0000 |
---|---|---|
committer | julien.pierre.bugs%sun.com <devnull@localhost> | 2005-04-09 05:06:34 +0000 |
commit | 0a86fd97bfa7775a74525f8298ac7b294e8b7a00 (patch) | |
tree | 556d08f04be961a74f4d7eadcb703126eacf3176 | |
parent | 2127fe26d2fc2d7fa51bd85f981e173416c3a64e (diff) | |
download | nss-hg-0a86fd97bfa7775a74525f8298ac7b294e8b7a00.tar.gz |
Fix for 280121 - allow encoding simple templates with SEC_ASN1_INLINE and SEC_ASN1_OPTIONAL . r=nelson
-rw-r--r-- | security/nss/lib/util/secasn1.h | 5 | ||||
-rw-r--r-- | security/nss/lib/util/secasn1e.c | 39 | ||||
-rw-r--r-- | security/nss/lib/util/secasn1u.c | 22 |
3 files changed, 63 insertions, 3 deletions
diff --git a/security/nss/lib/util/secasn1.h b/security/nss/lib/util/secasn1.h index 5c414522e..5e4779d57 100644 --- a/security/nss/lib/util/secasn1.h +++ b/security/nss/lib/util/secasn1.h @@ -183,6 +183,11 @@ extern const SEC_ASN1Template * SEC_ASN1GetSubtemplate (const SEC_ASN1Template *inTemplate, void *thing, PRBool encoding); +/* whether the template is for a primitive type or a choice of + * primitive types + */ +extern PRBool SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate); + /************************************************************************/ /* diff --git a/security/nss/lib/util/secasn1e.c b/security/nss/lib/util/secasn1e.c index 8a7e33207..778aff08c 100644 --- a/security/nss/lib/util/secasn1e.c +++ b/security/nss/lib/util/secasn1e.c @@ -193,6 +193,7 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) unsigned char tag_modifiers; unsigned long encode_kind, under_kind; unsigned long tag_number; + PRBool isInline = PR_FALSE; encode_kind = state->theTemplate->kind; @@ -222,7 +223,7 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) } else if ((encode_kind & (SEC_ASN1_POINTER | SEC_ASN1_INLINE)) || (!universal && !isExplicit)) { const SEC_ASN1Template *subt; - void *src; + void *src = NULL; PORT_Assert ((encode_kind & (SEC_ASN1_ANY | SEC_ASN1_SKIP)) == 0); @@ -231,6 +232,7 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) if (encode_kind & SEC_ASN1_POINTER) { src = *(void **)state->src; state->place = afterPointer; + if (src == NULL) { /* * If this is optional, but NULL, then the field does @@ -249,8 +251,9 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) src = state->src; if (encode_kind & SEC_ASN1_INLINE) { /* check that there are no extraneous bits */ - PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); + /* PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); */ state->place = afterInline; + isInline = PR_TRUE; } else { /* * Save the tag modifiers and tag number here before moving @@ -268,6 +271,22 @@ sec_asn1e_init_state_based_on_template (sec_asn1e_state *state) } subt = SEC_ASN1GetSubtemplate (state->theTemplate, state->src, PR_TRUE); + if (isInline && optional) { + /* we only handle a very limited set of optional inline cases at + this time */ + if (PR_FALSE != SEC_ASN1IsTemplateSimple(subt)) { + /* we now know that the target is a SECItem*, so we can check + if the source contains one */ + SECItem* target = (SECItem*)state->src; + if (!target || !target->data || !target->len) { + /* no valid data to encode subtemplate */ + return state; + } + } else { + PORT_Assert(0); /* complex templates are not handled as + inline optional */ + } + } state = sec_asn1e_push_state (state->top, subt, src, PR_FALSE); if (state == NULL) return state; @@ -552,7 +571,21 @@ sec_asn1e_contents_length (const SEC_ASN1Template *theTemplate, void *src, } } else if (encode_kind & SEC_ASN1_INLINE) { /* check that there are no extraneous bits */ - PORT_Assert (encode_kind == SEC_ASN1_INLINE && !optional); + if (optional) { + if (PR_FALSE != SEC_ASN1IsTemplateSimple(theTemplate)) { + /* we now know that the target is a SECItem*, so we can check + if the source contains one */ + SECItem* target = (SECItem*)src; + if (!target || !target->data || !target->len) { + /* no valid data to encode subtemplate */ + *noheaderp = PR_TRUE; + return 0; + } + } else { + PORT_Assert(0); /* complex templates not handled as inline + optional */ + } + } } src = (char *)src + theTemplate->offset; diff --git a/security/nss/lib/util/secasn1u.c b/security/nss/lib/util/secasn1u.c index 2de4f2753..1514bd7ed 100644 --- a/security/nss/lib/util/secasn1u.c +++ b/security/nss/lib/util/secasn1u.c @@ -107,3 +107,25 @@ SEC_ASN1GetSubtemplate (const SEC_ASN1Template *theTemplate, void *thing, } return subt; } + +PRBool SEC_ASN1IsTemplateSimple(const SEC_ASN1Template *theTemplate) +{ + if (!theTemplate) { + return PR_TRUE; /* it doesn't get any simpler than NULL */ + } + /* only templates made of one primitive type or a choice of primitive + types are considered simple */ + if (! (theTemplate->kind & (~SEC_ASN1_TAGNUM_MASK))) { + return PR_TRUE; /* primitive type */ + } + if (!theTemplate->kind & SEC_ASN1_CHOICE) { + return PR_FALSE; /* no choice means not simple */ + } + while (++theTemplate && theTemplate->kind) { + if (theTemplate->kind & (~SEC_ASN1_TAGNUM_MASK)) { + return PR_FALSE; /* complex type */ + } + } + return PR_TRUE; /* choice of primitive types */ +} + |