Mark x509v3_cache_extensions as const

While it does mutate the X509 object, it is thread-safe and logically
const. When we fix this to instead fill in cached fields on parse, this
will be more obviously const-correct. In the meantime, mark this as
const so it doesn't get in the way of keeping other fields const.

Bug: 443261873
Change-Id: Id1a819f0342d468f3e904cc97a7df9b009090482
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/103855
Reviewed-by: Xiangfei Ding <xfding@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h
index b2e6189..238a2e8 100644
--- a/crypto/x509/internal.h
+++ b/crypto/x509/internal.h
@@ -170,18 +170,18 @@
   UniquePtr<CRYPTO_BUFFER> buf;
   CRYPTO_EX_DATA ex_data;
   // These contain copies of various extension values
-  long ex_pathlen = -1;
-  uint32_t ex_flags = 0;
-  uint32_t ex_kusage = 0;
-  uint32_t ex_xkusage = 0;
-  UniquePtr<ASN1_OCTET_STRING> skid;
-  UniquePtr<AUTHORITY_KEYID> akid;
-  UniquePtr<STACK_OF(DIST_POINT)> crldp;
-  UniquePtr<STACK_OF(GENERAL_NAME)> altname;
-  UniquePtr<NAME_CONSTRAINTS> nc;
-  unsigned char cert_hash[SHA256_DIGEST_LENGTH] = {};
+  mutable long ex_pathlen = -1;
+  mutable uint32_t ex_flags = 0;
+  mutable uint32_t ex_kusage = 0;
+  mutable uint32_t ex_xkusage = 0;
+  mutable UniquePtr<ASN1_OCTET_STRING> skid;
+  mutable UniquePtr<AUTHORITY_KEYID> akid;
+  mutable UniquePtr<STACK_OF(DIST_POINT)> crldp;
+  mutable UniquePtr<STACK_OF(GENERAL_NAME)> altname;
+  mutable UniquePtr<NAME_CONSTRAINTS> nc;
+  mutable unsigned char cert_hash[SHA256_DIGEST_LENGTH] = {};
   bssl::X509_CERT_AUX *aux = nullptr;
-  Mutex lock;
+  mutable Mutex lock;
 
  private:
   friend RefCounted;
@@ -522,7 +522,7 @@
 // x509v3_cache_extensions fills in a number of fields relating to X.509
 // extensions in `x`. It returns one on success and zero if some extensions were
 // invalid.
-OPENSSL_EXPORT int x509v3_cache_extensions(X509 *x);
+OPENSSL_EXPORT int x509v3_cache_extensions(const X509 *x);
 
 // x509v3_a2i_ipadd decodes `ipasc` as an IPv4 or IPv6 address. IPv6 addresses
 // use colon-separated syntax while IPv4 addresses use dotted decimal syntax. If
diff --git a/crypto/x509/v3_purp.cc b/crypto/x509/v3_purp.cc
index cf9f79e..2dba0d0 100644
--- a/crypto/x509/v3_purp.cc
+++ b/crypto/x509/v3_purp.cc
@@ -147,7 +147,7 @@
          nid == NID_pe_mtcCertificationAuthority_SHA256;
 }
 
-static int setup_crldp(X509 *x) {
+static int setup_crldp(const X509 *x) {
   int j;
   auto *impl = FromOpaque(x);
   impl->crldp.reset(reinterpret_cast<STACK_OF(DIST_POINT) *>(
@@ -158,7 +158,7 @@
   return 1;
 }
 
-int bssl::x509v3_cache_extensions(X509 *x) {
+int bssl::x509v3_cache_extensions(const X509 *x) {
   BASIC_CONSTRAINTS *bs;
   ASN1_BIT_STRING *usage;
   EXTENDED_KEY_USAGE *extusage;
@@ -342,7 +342,7 @@
 }
 
 int X509_check_ca(const X509 *x) {
-  if (!x509v3_cache_extensions(const_cast<X509 *>(x))) {
+  if (!x509v3_cache_extensions(x)) {
     return 0;
   }
   return check_ca(x);
@@ -451,8 +451,8 @@
                     X509_get_issuer_name(subject))) {
     return X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
   }
-  if (!x509v3_cache_extensions(const_cast<X509 *>(issuer)) ||
-      !x509v3_cache_extensions(const_cast<X509 *>(subject))) {
+  if (!x509v3_cache_extensions(issuer) ||
+      !x509v3_cache_extensions(subject)) {
     return X509_V_ERR_UNSPECIFIED;
   }
 
diff --git a/crypto/x509/x509_cmp.cc b/crypto/x509/x509_cmp.cc
index 4dea236..5c78399 100644
--- a/crypto/x509/x509_cmp.cc
+++ b/crypto/x509/x509_cmp.cc
@@ -107,8 +107,8 @@
   // comparison and may cause misbehaving sorts by transitivity. For now, we
   // retain the old OpenSSL behavior, which was to ignore the error. See
   // https://crbug.com/boringssl/355.
-  x509v3_cache_extensions((X509Impl *)a_impl);
-  x509v3_cache_extensions((X509Impl *)b_impl);
+  x509v3_cache_extensions(a_impl);
+  x509v3_cache_extensions(b_impl);
 
   return OPENSSL_memcmp(a_impl->cert_hash, b_impl->cert_hash,
                         SHA256_DIGEST_LENGTH);