Test ASN1_STRING_set_by_NID with built-in NIDs.
Change-Id: I58a3fba79b03058aaff37bb3e83f971a4ecd2e99
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/49767
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/asn1/a_strnid.c b/crypto/asn1/a_strnid.c
index 299d03b..62c2f5d 100644
--- a/crypto/asn1/a_strnid.c
+++ b/crypto/asn1/a_strnid.c
@@ -122,15 +122,13 @@
* Now the tables and helper functions for the string table:
*/
-/* size limits: this stuff is taken straight from RFC 3280 */
-
+/* See RFC 5280. */
#define ub_name 32768
#define ub_common_name 64
#define ub_locality_name 128
#define ub_state_name 128
#define ub_organization_name 64
#define ub_organization_unit_name 64
-#define ub_title 64
#define ub_email_address 128
#define ub_serial_number 64
diff --git a/crypto/asn1/asn1_test.cc b/crypto/asn1/asn1_test.cc
index 49a0c27..3a039bf 100644
--- a/crypto/asn1/asn1_test.cc
+++ b/crypto/asn1/asn1_test.cc
@@ -1037,6 +1037,126 @@
}
}
+TEST(ASN1Test, StringByNID) {
+ // |ASN1_mbstring_*| tests above test most of the interactions with |inform|,
+ // so all tests below use UTF-8.
+ const struct {
+ int nid;
+ std::string in;
+ int expected_type;
+ std::string expected;
+ } kTests[] = {
+ // Although DirectoryString and PKCS9String allow many types of strings,
+ // we prefer UTF8String.
+ {NID_commonName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_commonName, "\xe2\x98\x83", V_ASN1_UTF8STRING, "\xe2\x98\x83"},
+ {NID_localityName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_stateOrProvinceName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_organizationName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_organizationalUnitName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_pkcs9_unstructuredName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_pkcs9_challengePassword, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_pkcs9_unstructuredAddress, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_givenName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_givenName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_givenName, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_surname, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_initials, "abc", V_ASN1_UTF8STRING, "abc"},
+ {NID_name, "abc", V_ASN1_UTF8STRING, "abc"},
+
+ // Some attribute types use a particular string type.
+ {NID_countryName, "US", V_ASN1_PRINTABLESTRING, "US"},
+ {NID_pkcs9_emailAddress, "example@example.com", V_ASN1_IA5STRING,
+ "example@example.com"},
+ {NID_serialNumber, "1234", V_ASN1_PRINTABLESTRING, "1234"},
+ {NID_friendlyName, "abc", V_ASN1_BMPSTRING,
+ std::string({'\0', 'a', '\0', 'b', '\0', 'c'})},
+ {NID_dnQualifier, "US", V_ASN1_PRINTABLESTRING, "US"},
+ {NID_domainComponent, "com", V_ASN1_IA5STRING, "com"},
+ {NID_ms_csp_name, "abc", V_ASN1_BMPSTRING,
+ std::string({'\0', 'a', '\0', 'b', '\0', 'c'})},
+
+ // Unknown NIDs default to UTF8String.
+ {NID_rsaEncryption, "abc", V_ASN1_UTF8STRING, "abc"},
+ };
+ for (const auto &t : kTests) {
+ SCOPED_TRACE(t.nid);
+ SCOPED_TRACE(t.in);
+
+ // Test allocating a new object.
+ bssl::UniquePtr<ASN1_STRING> str(ASN1_STRING_set_by_NID(
+ nullptr, reinterpret_cast<const uint8_t *>(t.in.data()), t.in.size(),
+ MBSTRING_UTF8, t.nid));
+ ASSERT_TRUE(str);
+ EXPECT_EQ(t.expected_type, ASN1_STRING_type(str.get()));
+ EXPECT_EQ(Bytes(t.expected), Bytes(ASN1_STRING_get0_data(str.get()),
+ ASN1_STRING_length(str.get())));
+
+ // Test writing into an existing object.
+ str.reset(ASN1_STRING_new());
+ ASSERT_TRUE(str);
+ ASN1_STRING *old_str = str.get();
+ ASSERT_TRUE(ASN1_STRING_set_by_NID(
+ &old_str, reinterpret_cast<const uint8_t *>(t.in.data()), t.in.size(),
+ MBSTRING_UTF8, t.nid));
+ ASSERT_EQ(old_str, str.get());
+ EXPECT_EQ(t.expected_type, ASN1_STRING_type(str.get()));
+ EXPECT_EQ(Bytes(t.expected), Bytes(ASN1_STRING_get0_data(str.get()),
+ ASN1_STRING_length(str.get())));
+ }
+
+ const struct {
+ int nid;
+ std::string in;
+ } kInvalidTests[] = {
+ // DirectoryString forbids empty inputs.
+ {NID_commonName, ""},
+ {NID_localityName, ""},
+ {NID_stateOrProvinceName, ""},
+ {NID_organizationName, ""},
+ {NID_organizationalUnitName, ""},
+ {NID_pkcs9_unstructuredName, ""},
+ {NID_pkcs9_challengePassword, ""},
+ {NID_pkcs9_unstructuredAddress, ""},
+ {NID_givenName, ""},
+ {NID_givenName, ""},
+ {NID_givenName, ""},
+ {NID_surname, ""},
+ {NID_initials, ""},
+ {NID_name, ""},
+
+ // Test upper bounds from RFC 5280.
+ {NID_name, std::string(32769, 'a')},
+ {NID_commonName, std::string(65, 'a')},
+ {NID_localityName, std::string(129, 'a')},
+ {NID_stateOrProvinceName, std::string(129, 'a')},
+ {NID_organizationName, std::string(65, 'a')},
+ {NID_organizationalUnitName, std::string(65, 'a')},
+ {NID_pkcs9_emailAddress, std::string(256, 'a')},
+ {NID_serialNumber, std::string(65, 'a')},
+
+ // X520countryName must be exactly two characters.
+ {NID_countryName, "A"},
+ {NID_countryName, "AAA"},
+
+ // Some string types cannot represent all codepoints.
+ {NID_countryName, "\xe2\x98\x83"},
+ {NID_pkcs9_emailAddress, "\xe2\x98\x83"},
+ {NID_serialNumber, "\xe2\x98\x83"},
+ {NID_dnQualifier, "\xe2\x98\x83"},
+ {NID_domainComponent, "\xe2\x98\x83"},
+ };
+ for (const auto &t : kInvalidTests) {
+ SCOPED_TRACE(t.nid);
+ SCOPED_TRACE(t.in);
+ bssl::UniquePtr<ASN1_STRING> str(ASN1_STRING_set_by_NID(
+ nullptr, reinterpret_cast<const uint8_t *>(t.in.data()), t.in.size(),
+ MBSTRING_UTF8, t.nid));
+ EXPECT_FALSE(str);
+ ERR_clear_error();
+ }
+}
+
// Test that multi-string types correctly encode negative ENUMERATED.
// Multi-string types cannot contain INTEGER, so we only test ENUMERATED.
TEST(ASN1Test, NegativeEnumeratedMultistring) {