Simplify and document X509_supported_extension

It doesn't make sense to binary search over a list of 10 entries.
Additionally, the compiler is perfectly capable of optimizing a bunch of
equality checks (e.g. by turning it into a bitmask), so just let the
compiler do what it wants.

Change-Id: Ie7cee62d1ddec1ac1e24f483817b9a67aaff369c
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/64250
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Bob Beck <bbe@google.com>
diff --git a/crypto/x509/v3_purp.c b/crypto/x509/v3_purp.c
index 32fdb60..e7a9764 100644
--- a/crypto/x509/v3_purp.c
+++ b/crypto/x509/v3_purp.c
@@ -310,43 +310,18 @@
 
 int X509_PURPOSE_get_trust(const X509_PURPOSE *xp) { return xp->trust; }
 
-static int nid_cmp(const void *void_a, const void *void_b) {
-  const int *a = void_a, *b = void_b;
-
-  return *a - *b;
-}
-
 int X509_supported_extension(const X509_EXTENSION *ex) {
-  // This table is a list of the NIDs of supported extensions: that is
-  // those which are used by the verify process. If an extension is
-  // critical and doesn't appear in this list then the verify process will
-  // normally reject the certificate. The list must be kept in numerical
-  // order because it will be searched using bsearch.
-
-  static const int supported_nids[] = {
-      NID_netscape_cert_type,    // 71
-      NID_key_usage,             // 83
-      NID_subject_alt_name,      // 85
-      NID_basic_constraints,     // 87
-      NID_certificate_policies,  // 89
-      NID_ext_key_usage,         // 126
-      NID_policy_constraints,    // 401
-      NID_name_constraints,      // 666
-      NID_policy_mappings,       // 747
-      NID_inhibit_any_policy     // 748
-  };
-
-  int ex_nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
-
-  if (ex_nid == NID_undef) {
-    return 0;
-  }
-
-  if (bsearch(&ex_nid, supported_nids, sizeof(supported_nids) / sizeof(int),
-              sizeof(int), nid_cmp) != NULL) {
-    return 1;
-  }
-  return 0;
+  int nid = OBJ_obj2nid(X509_EXTENSION_get_object(ex));
+  return nid == NID_netscape_cert_type ||    //
+         nid == NID_key_usage ||             //
+         nid == NID_subject_alt_name ||      //
+         nid == NID_basic_constraints ||     //
+         nid == NID_certificate_policies ||  //
+         nid == NID_ext_key_usage ||         //
+         nid == NID_policy_constraints ||    //
+         nid == NID_name_constraints ||      //
+         nid == NID_policy_mappings ||       //
+         nid == NID_inhibit_any_policy;
 }
 
 static int setup_dp(X509 *x, DIST_POINT *dp) {
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 449f932..0c8d5df 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -4027,7 +4027,16 @@
 
 OPENSSL_EXPORT int X509_check_ca(X509 *x);
 OPENSSL_EXPORT int X509_check_purpose(X509 *x, int id, int ca);
+
+// X509_supported_extension returns one if |ex| is a critical X.509 certificate
+// extension, supported by |X509_verify_cert|, and zero otherwise.
+//
+// Note this function only reports certificate extensions (as opposed to CRL or
+// CRL extensions), and only extensions that are expected to be marked critical.
+// Additionally, |X509_verify_cert| checks for unsupported critical extensions
+// internally, so most callers will not need to call this function separately.
 OPENSSL_EXPORT int X509_supported_extension(const X509_EXTENSION *ex);
+
 OPENSSL_EXPORT int X509_PURPOSE_set(int *p, int purpose);
 OPENSSL_EXPORT int X509_check_issued(X509 *issuer, X509 *subject);
 OPENSSL_EXPORT int X509_check_akid(X509 *issuer, AUTHORITY_KEYID *akid);