Remove B_ASN1_UNKNOWN

The distinction between B_ASN1_UNKNOWN and zero never made much sense.
Now that X509_NAME parsing is fixed, this can be removed. In doing so,
implement this function more straightforwardly.

Update-Note: B_ASN1_UNKNOWN is removed. Code search says nothing
external was using it, which makes sense because there was nothing
useful callers could do with it.

Fixed: 42290275
Change-Id: I445bea1b11dfa70abf279530a7338305f28aeb98
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/78330
Reviewed-by: Adam Langley <agl@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/asn1/tasn_dec.cc b/crypto/asn1/tasn_dec.cc
index 13dc114..627c135 100644
--- a/crypto/asn1/tasn_dec.cc
+++ b/crypto/asn1/tasn_dec.cc
@@ -52,46 +52,43 @@
                             long len, const ASN1_ITEM *it, int tag, int aclass,
                             char opt, CRYPTO_BUFFER *buf, int depth);
 
-// Table to convert tags to bit values, used for MSTRING type
-static const unsigned long tag2bit[31] = {
-    0,  // (reserved)
-    0,  // BOOLEAN
-    0,  // INTEGER
-    B_ASN1_BIT_STRING,
-    B_ASN1_OCTET_STRING,
-    0,               // NULL
-    0,               // OBJECT IDENTIFIER
-    B_ASN1_UNKNOWN,  // ObjectDescriptor
-    B_ASN1_UNKNOWN,  // EXTERNAL
-    B_ASN1_UNKNOWN,  // REAL
-    B_ASN1_UNKNOWN,  // ENUMERATED
-    B_ASN1_UNKNOWN,  // EMBEDDED PDV
-    B_ASN1_UTF8STRING,
-    B_ASN1_UNKNOWN,  // RELATIVE-OID
-    B_ASN1_UNKNOWN,  // TIME
-    B_ASN1_UNKNOWN,  // (reserved)
-    B_ASN1_SEQUENCE,
-    0,  // SET
-    B_ASN1_NUMERICSTRING,
-    B_ASN1_PRINTABLESTRING,
-    B_ASN1_T61STRING,
-    B_ASN1_VIDEOTEXSTRING,
-    B_ASN1_IA5STRING,
-    B_ASN1_UTCTIME,
-    B_ASN1_GENERALIZEDTIME,
-    B_ASN1_GRAPHICSTRING,
-    B_ASN1_ISO64STRING,
-    B_ASN1_GENERALSTRING,
-    B_ASN1_UNIVERSALSTRING,
-    B_ASN1_UNKNOWN,  // CHARACTER STRING
-    B_ASN1_BMPSTRING,
-};
-
 unsigned long ASN1_tag2bit(int tag) {
-  if (tag < 0 || tag > 30) {
-    return 0;
+  switch (tag) {
+    case V_ASN1_BIT_STRING:
+      return B_ASN1_BIT_STRING;
+    case V_ASN1_OCTET_STRING:
+      return B_ASN1_OCTET_STRING;
+    case V_ASN1_UTF8STRING:
+      return B_ASN1_UTF8STRING;
+    case V_ASN1_SEQUENCE:
+      return B_ASN1_SEQUENCE;
+    case V_ASN1_NUMERICSTRING:
+      return B_ASN1_NUMERICSTRING;
+    case V_ASN1_PRINTABLESTRING:
+      return B_ASN1_PRINTABLESTRING;
+    case V_ASN1_T61STRING:
+      return B_ASN1_T61STRING;
+    case V_ASN1_VIDEOTEXSTRING:
+      return B_ASN1_VIDEOTEXSTRING;
+    case V_ASN1_IA5STRING:
+      return B_ASN1_IA5STRING;
+    case V_ASN1_UTCTIME:
+      return B_ASN1_UTCTIME;
+    case V_ASN1_GENERALIZEDTIME:
+      return B_ASN1_GENERALIZEDTIME;
+    case V_ASN1_GRAPHICSTRING:
+      return B_ASN1_GRAPHICSTRING;
+    case V_ASN1_ISO64STRING:
+      return B_ASN1_ISO64STRING;
+    case V_ASN1_GENERALSTRING:
+      return B_ASN1_GENERALSTRING;
+    case V_ASN1_UNIVERSALSTRING:
+      return B_ASN1_UNIVERSALSTRING;
+    case V_ASN1_BMPSTRING:
+      return B_ASN1_BMPSTRING;
+    default:
+      return 0;
   }
-  return tag2bit[tag];
 }
 
 static int is_supported_universal_type(int tag, int aclass) {
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index ad4905c..8eb8e8b 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -132,21 +132,13 @@
 #define B_ASN1_OCTET_STRING 0x0200
 #define B_ASN1_BIT_STRING 0x0400
 #define B_ASN1_BMPSTRING 0x0800
-#define B_ASN1_UNKNOWN 0x1000
 #define B_ASN1_UTF8STRING 0x2000
 #define B_ASN1_UTCTIME 0x4000
 #define B_ASN1_GENERALIZEDTIME 0x8000
 #define B_ASN1_SEQUENCE 0x10000
 
 // ASN1_tag2bit converts |tag| from the tag number of a universal type to a
-// corresponding |B_ASN1_*| constant, |B_ASN1_UNKNOWN|, or zero. If the
-// |B_ASN1_*| constant above is defined, it will map the corresponding
-// |V_ASN1_*| constant to it. Otherwise, whether it returns |B_ASN1_UNKNOWN| or
-// zero is ill-defined and a consequence of some historical behavior. Callers
-// should not rely on it.
-//
-// TODO(crbug.com/42290275): Remove |B_ASN1_UNKNOWN| once |X509_NAME| no longer
-// depends on it.
+// corresponding |B_ASN1_*| constant, or zero if |tag| has no bitmask.
 OPENSSL_EXPORT unsigned long ASN1_tag2bit(int tag);
 
 // ASN1_tag2str returns a string representation of |tag|, interpret as a tag
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 2802893..58508a5 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -1504,9 +1504,12 @@
 // pointer for OpenSSL compatibility, but callers should not mutate the result.
 // Doing so will break internal invariants in the library.
 //
-// TODO(crbug.com/42290275): Although the spec says any ASN.1 type is allowed,
-// we currently only allow an ad-hoc set of types. Additionally, it is unclear
-// if some types can even be represented by this function.
+// See |ASN1_STRING| for how values are represented in this library. Where a
+// specific |ASN1_STRING| representation exists, that representation is used.
+// Otherwise, the |V_ASN1_OTHER| representation is used. Note that NULL, OBJECT
+// IDENTIFIER, and BOOLEAN attribute values are represented as |V_ASN1_OTHER|,
+// because their usual representation in this library is not
+// |ASN1_STRING|-compatible.
 OPENSSL_EXPORT ASN1_STRING *X509_NAME_ENTRY_get_data(
     const X509_NAME_ENTRY *entry);