Migrate RSAImpl to RefCounted.

Bug: 42290295
Change-Id: Iea6a067c6e473ac0944aabc2f286e40b6a6a6964
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/89169
Reviewed-by: Xiangfei Ding <xfding@google.com>
Commit-Queue: Xiangfei Ding <xfding@google.com>
diff --git a/crypto/fipsmodule/rsa/internal.h b/crypto/fipsmodule/rsa/internal.h
index 46f3d1a..d8b4f1d 100644
--- a/crypto/fipsmodule/rsa/internal.h
+++ b/crypto/fipsmodule/rsa/internal.h
@@ -21,6 +21,7 @@
 #include <openssl/rsa.h>
 
 #include "../../internal.h"
+#include "../../mem_internal.h"
 
 
 DECLARE_OPAQUE_STRUCT(rsa_st, RSAImpl)
@@ -44,53 +45,54 @@
   rsa_pss_sha512,
 };
 
-class RSAImpl : public rsa_st {
+class RSAImpl : public rsa_st, public RefCounted<RSAImpl> {
  public:
-  static constexpr bool kAllowUniquePtr = true;
-
-  ~RSAImpl();
+  explicit RSAImpl(const ENGINE *engine);
 
   RSA_METHOD *meth;
 
-  BIGNUM *n;
-  BIGNUM *e;
-  BIGNUM *d;
-  BIGNUM *p;
-  BIGNUM *q;
-  BIGNUM *dmp1;
-  BIGNUM *dmq1;
-  BIGNUM *iqmp;
+  BIGNUM *n = nullptr;
+  BIGNUM *e = nullptr;
+  BIGNUM *d = nullptr;
+  BIGNUM *p = nullptr;
+  BIGNUM *q = nullptr;
+  BIGNUM *dmp1 = nullptr;
+  BIGNUM *dmq1 = nullptr;
+  BIGNUM *iqmp = nullptr;
 
   // be careful using this if the RSA structure is shared
-  CRYPTO_EX_DATA ex_data;
-  bssl::CRYPTO_refcount_t references;
+  CRYPTO_EX_DATA ex_data = {};
   int flags;
 
   bssl::CRYPTO_MUTEX lock;
 
   // Used to cache montgomery values. The creation of these values is protected
   // by |lock|.
-  BN_MONT_CTX *mont_n;
-  BN_MONT_CTX *mont_p;
-  BN_MONT_CTX *mont_q;
+  BN_MONT_CTX *mont_n = nullptr;
+  BN_MONT_CTX *mont_p = nullptr;
+  BN_MONT_CTX *mont_q = nullptr;
 
   // The following fields are copies of |d|, |dmp1|, and |dmq1|, respectively,
   // but with the correct widths to prevent side channels. These must use
   // separate copies due to threading concerns caused by OpenSSL's API
   // mistakes. See https://github.com/openssl/openssl/issues/5158 and
   // the |freeze_private_key| implementation.
-  BIGNUM *d_fixed, *dmp1_fixed, *dmq1_fixed;
+  BIGNUM *d_fixed = nullptr, *dmp1_fixed = nullptr, *dmq1_fixed = nullptr;
 
   // iqmp_mont is q^-1 mod p in Montgomery form, using |mont_p|.
-  BIGNUM *iqmp_mont;
+  BIGNUM *iqmp_mont = nullptr;
 
   // pss_params is the RSA-PSS parameters associated with the key. This is not
   // used by the low-level RSA implementation, just the EVP layer.
-  bssl::rsa_pss_params_t pss_params;
+  bssl::rsa_pss_params_t pss_params = {};
 
   // private_key_frozen is one if the key has been used for a private key
   // operation and may no longer be mutated.
-  unsigned private_key_frozen : 1;
+  unsigned private_key_frozen = 0;
+
+ private:
+  friend RefCounted;
+  ~RSAImpl();
 };
 
 #define RSA_PKCS1_PADDING_SIZE 11
diff --git a/crypto/fipsmodule/rsa/rsa.cc.inc b/crypto/fipsmodule/rsa/rsa.cc.inc
index a3e8fe0..b7b0857 100644
--- a/crypto/fipsmodule/rsa/rsa.cc.inc
+++ b/crypto/fipsmodule/rsa/rsa.cc.inc
@@ -165,35 +165,33 @@
   return rsa;
 }
 
+RSAImpl::RSAImpl(const ENGINE *engine)
+    : RefCounted(CheckSubClass()),
+      meth(engine ? ENGINE_get_RSA_method(engine) : nullptr) {
+  if (meth == nullptr) {
+    meth = (RSA_METHOD *)RSA_default_method();
+  }
+  METHOD_ref(meth);
+  flags = meth->flags;
+  CRYPTO_MUTEX_init(&lock);
+  CRYPTO_new_ex_data(&ex_data);
+}
+
 RSA *RSA_new() { return RSA_new_method(nullptr); }
 
 RSA *RSA_new_method(const ENGINE *engine) {
-  RSAImpl *rsa = NewZeroed<RSAImpl>();
+  UniquePtr<RSAImpl> rsa(New<RSAImpl>(engine));
   if (rsa == nullptr) {
     return nullptr;
   }
 
-  if (engine) {
-    rsa->meth = ENGINE_get_RSA_method(engine);
-  }
-
-  if (rsa->meth == nullptr) {
-    rsa->meth = (RSA_METHOD *)RSA_default_method();
-  }
-  METHOD_ref(rsa->meth);
-
-  rsa->references = 1;
-  rsa->flags = rsa->meth->flags;
-  CRYPTO_MUTEX_init(&rsa->lock);
-  CRYPTO_new_ex_data(&rsa->ex_data);
-
-  if (rsa->meth->init && !rsa->meth->init(rsa)) {
+  if (rsa->meth->init && !rsa->meth->init(rsa.get())) {
+    METHOD_unref(rsa->meth);
     rsa->meth = nullptr;
-    RSA_free(rsa);
     return nullptr;
   }
 
-  return rsa;
+  return rsa.release();
 }
 
 RSA *RSA_new_method_no_e(const ENGINE *engine, const BIGNUM *n) {
@@ -207,9 +205,6 @@
 }
 
 RSAImpl::~RSAImpl() {
-  // Refcount can be 1 if called by UniquePtr, and 0 if called by RSA_free.
-  BSSL_CHECK(references.load() <= 1);
-
   if (meth != nullptr && meth->finish != nullptr) {
     meth->finish(this);
   }
@@ -235,15 +230,12 @@
   }
 
   auto *impl = FromOpaque(rsa);
-  if (!CRYPTO_refcount_dec_and_test_zero(&impl->references)) {
-    return;
-  }
-  Delete(impl);
+  impl->DecRefInternal();
 }
 
 int RSA_up_ref(RSA *rsa) {
   auto *impl = FromOpaque(rsa);
-  CRYPTO_refcount_inc(&impl->references);
+  impl->UpRefInternal();
   return 1;
 }