Reject -1 types in ASN1_TYPE and MSTRINGs when encoding.
See https://github.com/openssl/openssl/issues/16538
Update-Note: A default-constructed object with a required ANY or
string-like CHOICE field cannot be encoded until the field is specified.
Note this affects i2d_X509: notBefore and notAfter are string-like
CHOICEs in OpenSSL.
Bug: 429
Change-Id: I97d971fa588ab72be25a4c1eb7310ed330f16c4f
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49349
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc
index e1c9cbd..5cd17af 100644
--- a/crypto/asn1/asn1_test.cc
+++ b/crypto/asn1/asn1_test.cc
@@ -1096,6 +1096,29 @@
EXPECT_EQ(-1, i2d_X509_ALGOR(alg.get(), nullptr));
}
+// Encoding invalid |ASN1_TYPE|s should fail. |ASN1_TYPE|s are
+// default-initialized to an invalid type.
+TEST(ASN1Test, InvalidASN1Type) {
+ bssl::UniquePtr<ASN1_TYPE> obj(ASN1_TYPE_new());
+ ASSERT_TRUE(obj);
+ EXPECT_EQ(-1, obj->type);
+ EXPECT_EQ(-1, i2d_ASN1_TYPE(obj.get(), nullptr));
+}
+
+// Encoding invalid MSTRING types should fail. An MSTRING is a CHOICE of
+// string-like types. They are initialized to an invalid type.
+TEST(ASN1Test, InvalidMSTRING) {
+ bssl::UniquePtr<ASN1_STRING> obj(ASN1_TIME_new());
+ ASSERT_TRUE(obj);
+ EXPECT_EQ(-1, obj->type);
+ EXPECT_EQ(-1, i2d_ASN1_TIME(obj.get(), nullptr));
+
+ obj.reset(DIRECTORYSTRING_new());
+ ASSERT_TRUE(obj);
+ EXPECT_EQ(-1, obj->type);
+ EXPECT_EQ(-1, i2d_DIRECTORYSTRING(obj.get(), nullptr));
+}
+
// The ASN.1 macros do not work on Windows shared library builds, where usage of
// |OPENSSL_EXPORT| is a bit stricter.
#if !defined(OPENSSL_WINDOWS) || !defined(BORINGSSL_SHARED_LIBRARY)
diff --git a/crypto/asn1/tasn_enc.c b/crypto/asn1/tasn_enc.c
index 49b79d2..7e79da2 100644
--- a/crypto/asn1/tasn_enc.c
+++ b/crypto/asn1/tasn_enc.c
@@ -554,6 +554,11 @@
/* If MSTRING type set the underlying type */
strtmp = (ASN1_STRING *)*pval;
utype = strtmp->type;
+ if (utype < 0 && utype != V_ASN1_OTHER) {
+ /* MSTRINGs can have type -1 when default-constructed. */
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
+ return -1;
+ }
/* Negative INTEGER and ENUMERATED values use |ASN1_STRING| type values
* that do not match their corresponding utype values. INTEGERs cannot
* participate in MSTRING types, but ENUMERATEDs can.
@@ -574,6 +579,11 @@
ASN1_TYPE *typ;
typ = (ASN1_TYPE *)*pval;
utype = typ->type;
+ if (utype < 0 && utype != V_ASN1_OTHER) {
+ /* |ASN1_TYPE|s can have type -1 when default-constructed. */
+ OPENSSL_PUT_ERROR(ASN1, ASN1_R_WRONG_TYPE);
+ return -1;
+ }
*putype = utype;
pval = &typ->value.asn1_value;
} else