summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjulien.pierre.bugs%sun.com <devnull@localhost>2005-04-09 05:06:34 +0000
committerjulien.pierre.bugs%sun.com <devnull@localhost>2005-04-09 05:06:34 +0000
commit0a86fd97bfa7775a74525f8298ac7b294e8b7a00 (patch)
tree556d08f04be961a74f4d7eadcb703126eacf3176
parent2127fe26d2fc2d7fa51bd85f981e173416c3a64e (diff)
downloadnss-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.h5
-rw-r--r--security/nss/lib/util/secasn1e.c39
-rw-r--r--security/nss/lib/util/secasn1u.c22
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 */
+}
+