Migrate X509Impl to RefCounted.

Bug: 42290295
Change-Id: I4cd4d809909f50283381b09da084405f6a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/89188
Reviewed-by: Xiangfei Ding <xfding@google.com>
Commit-Queue: Xiangfei Ding <xfding@google.com>
diff --git a/crypto/x509/internal.h b/crypto/x509/internal.h
index 6184565..c7f67ef 100644
--- a/crypto/x509/internal.h
+++ b/crypto/x509/internal.h
@@ -121,14 +121,12 @@
 // (RFC 5280) and C type is |STACK_OF(X509_EXTENSION)*|.
 DECLARE_ASN1_ITEM(X509_EXTENSIONS)
 
-class X509Impl : public x509_st {
+class X509Impl : public x509_st, public RefCounted<X509Impl> {
  public:
-  static constexpr bool kAllowUniquePtr = true;
-
-  ~X509Impl();
+  X509Impl();
 
   // TBSCertificate fields:
-  uint8_t version;  // One of the |X509_VERSION_*| constants.
+  uint8_t version = X509_VERSION_1;  // One of the |X509_VERSION_*| constants.
   ASN1_INTEGER serialNumber;
   X509_ALGOR tbs_sig_alg;
   X509Name issuer;
@@ -147,10 +145,9 @@
   // TODO(davidben): Now every parsed |X509| has an underlying |CRYPTO_BUFFER|,
   // but |X509|s created peacemeal do not. Can we make this more uniform?
   CRYPTO_BUFFER *buf;
-  bssl::CRYPTO_refcount_t references;
   CRYPTO_EX_DATA ex_data;
   // These contain copies of various extension values
-  long ex_pathlen;
+  long ex_pathlen = -1;
   uint32_t ex_flags;
   uint32_t ex_kusage;
   uint32_t ex_xkusage;
@@ -162,6 +159,10 @@
   unsigned char cert_hash[SHA256_DIGEST_LENGTH];
   bssl::X509_CERT_AUX *aux;
   bssl::CRYPTO_MUTEX lock;
+
+ private:
+  friend RefCounted;
+  ~X509Impl();
 } /* X509 */;
 
 int x509_marshal_tbs_cert(CBB *cbb, const X509 *x509);
diff --git a/crypto/x509/x_x509.cc b/crypto/x509/x_x509.cc
index dced8fd..313be92 100644
--- a/crypto/x509/x_x509.cc
+++ b/crypto/x509/x_x509.cc
@@ -44,33 +44,23 @@
 static constexpr CBS_ASN1_TAG kExtensionsTag =
     CBS_ASN1_CONSTRUCTED | CBS_ASN1_CONTEXT_SPECIFIC | 3;
 
-X509 *X509_new() {
-  UniquePtr<X509Impl> ret(NewZeroed<X509Impl>());
-  if (ret == nullptr) {
-    return nullptr;
-  }
-
-  ret->references = 1;
-  ret->ex_pathlen = -1;
-  ret->version = X509_VERSION_1;
-  asn1_string_init(&ret->serialNumber, V_ASN1_INTEGER);
-  x509_algor_init(&ret->tbs_sig_alg);
-  x509_name_init(&ret->issuer);
-  asn1_string_init(&ret->notBefore, -1);
-  asn1_string_init(&ret->notAfter, -1);
-  x509_name_init(&ret->subject);
-  x509_pubkey_init(&ret->key);
-  x509_algor_init(&ret->sig_alg);
-  asn1_string_init(&ret->signature, V_ASN1_BIT_STRING);
-  CRYPTO_new_ex_data(&ret->ex_data);
-  CRYPTO_MUTEX_init(&ret->lock);
-  return ret.release();
+X509Impl::X509Impl() : RefCounted(CheckSubClass()) {
+  asn1_string_init(&serialNumber, V_ASN1_INTEGER);
+  x509_algor_init(&tbs_sig_alg);
+  x509_name_init(&issuer);
+  asn1_string_init(&notBefore, -1);
+  asn1_string_init(&notAfter, -1);
+  x509_name_init(&subject);
+  x509_pubkey_init(&key);
+  x509_algor_init(&sig_alg);
+  asn1_string_init(&signature, V_ASN1_BIT_STRING);
+  CRYPTO_new_ex_data(&ex_data);
+  CRYPTO_MUTEX_init(&lock);
 }
 
-X509Impl::~X509Impl() {
-  // Refcount can be 1 if called by UniquePtr, and 0 if called by X509_free.
-  BSSL_CHECK(references.load() <= 1);
+X509 *X509_new() { return NewZeroed<X509Impl>(); }
 
+X509Impl::~X509Impl() {
   CRYPTO_free_ex_data(&g_ex_data_class, &ex_data);
 
   asn1_string_cleanup(&serialNumber);
@@ -96,13 +86,11 @@
 }
 
 void X509_free(X509 *x509) {
-  auto *impl = FromOpaque(x509);
-  if (impl == nullptr ||
-      !CRYPTO_refcount_dec_and_test_zero(&impl->references)) {
+  if (x509 == nullptr) {
     return;
   }
-
-  Delete(impl);
+  auto *impl = FromOpaque(x509);
+  impl->DecRefInternal();
 }
 
 X509 *X509_parse_with_algorithms(CRYPTO_BUFFER *buf,
@@ -368,7 +356,7 @@
 
 int X509_up_ref(X509 *x) {
   auto *impl = FromOpaque(x);
-  CRYPTO_refcount_inc(&impl->references);
+  impl->UpRefInternal();
   return 1;
 }