Replace Scoped* heap types with bssl::UniquePtr.

Unlike the Scoped* types, bssl::UniquePtr is available to C++ users, and
offered for a large variety of types.  The 'extern "C++"' trick is used
to make the C++ bits digestible to C callers that wrap header files in
'extern "C"'.

Change-Id: Ifbca4c2997d6628e33028c7d7620c72aff0f862e
Reviewed-on: https://boringssl-review.googlesource.com/10521
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/include/openssl/asn1.h b/include/openssl/asn1.h
index e0bfc8b..e99099e 100644
--- a/include/openssl/asn1.h
+++ b/include/openssl/asn1.h
@@ -475,7 +475,7 @@
 
 DECLARE_ASN1_SET_OF(ASN1_INTEGER)
 
-typedef struct asn1_type_st
+struct asn1_type_st
 	{
 	int type;
 	union	{
@@ -503,7 +503,7 @@
 		ASN1_STRING *		sequence;
 		ASN1_VALUE *		asn1_value;
 		} value;
-	} ASN1_TYPE;
+    };
 
 DECLARE_ASN1_SET_OF(ASN1_TYPE)
 
@@ -923,6 +923,23 @@
 
 #ifdef  __cplusplus
 }
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(ASN1_OBJECT, ASN1_OBJECT_free)
+BORINGSSL_MAKE_DELETER(ASN1_STRING, ASN1_STRING_free)
+BORINGSSL_MAKE_DELETER(ASN1_TYPE, ASN1_TYPE_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define ASN1_R_ASN1_LENGTH_MISMATCH 100
diff --git a/include/openssl/base.h b/include/openssl/base.h
index 441aa29..8347c61 100644
--- a/include/openssl/base.h
+++ b/include/openssl/base.h
@@ -195,6 +195,7 @@
 typedef struct asn1_string_st ASN1_UTCTIME;
 typedef struct asn1_string_st ASN1_UTF8STRING;
 typedef struct asn1_string_st ASN1_VISIBLESTRING;
+typedef struct asn1_type_st ASN1_TYPE;
 
 typedef struct AUTHORITY_KEYID_st AUTHORITY_KEYID;
 typedef struct BASIC_CONSTRAINTS_st BASIC_CONSTRAINTS;
@@ -286,6 +287,7 @@
 typedef struct x509_cert_pair_st X509_CERT_PAIR;
 typedef struct x509_cinf_st X509_CINF;
 typedef struct x509_crl_method_st X509_CRL_METHOD;
+typedef struct x509_lookup_st X509_LOOKUP;
 typedef struct x509_revoked_st X509_REVOKED;
 typedef struct x509_st X509;
 typedef struct x509_store_ctx_st X509_STORE_CTX;
@@ -297,6 +299,55 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+// MSVC doesn't set __cplusplus to 201103 to indicate C++11 support (see
+// https://connect.microsoft.com/VisualStudio/feedback/details/763051/a-value-of-predefined-macro-cplusplus-is-still-199711l)
+// so MSVC is just assumed to support C++11.
+#if defined(BORINGSSL_NO_CXX) || (__cplusplus < 201103L && !defined(_MSC_VER))
+
+#define BORINGSSL_MAKE_DELETER(type, deleter)
+#define BORINGSSL_MAKE_STACK_DELETER(type, deleter)
+
+#else
+
+#include <memory>
+
+namespace bssl {
+
+namespace internal {
+
+template <class T> struct Deleter {};
+
+#define BORINGSSL_MAKE_DELETER(type, deleter)       \
+    template <> struct Deleter<type> {              \
+      void operator()(type* ptr) { deleter(ptr); }  \
+    };
+
+// This makes a unique_ptr to STACK_OF(type) that owns all elements on the
+// stack, i.e. it uses sk_pop_free() to clean up.
+#define BORINGSSL_MAKE_STACK_DELETER(type, deleter)  \
+    template <> struct Deleter<STACK_OF(type)> {     \
+      void operator()(STACK_OF(type)* ptr) {         \
+        sk_##type##_pop_free(ptr, deleter);          \
+      }                                              \
+    };
+
+}  // namespace internal
+
+// Holds ownership of heap-allocated BoringSSL structures. Sample usage:
+//   bssl::UniquePtr<BIO> rsa(RSA_new());
+//   bssl::UniquePtr<BIO> bio(BIO_new(BIO_s_mem()));
+template <typename T>
+using UniquePtr = std::unique_ptr<T, internal::Deleter<T>>;
+
+}  // namespace bssl
+
+#endif  // C++ allowed?
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_BASE_H */
diff --git a/include/openssl/bio.h b/include/openssl/bio.h
index 9622f96..4aa9070 100644
--- a/include/openssl/bio.h
+++ b/include/openssl/bio.h
@@ -895,6 +895,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(BIO, BIO_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define BIO_R_BAD_FOPEN_MODE 100
diff --git a/include/openssl/bn.h b/include/openssl/bn.h
index 67a3455..c1b9e39 100644
--- a/include/openssl/bn.h
+++ b/include/openssl/bn.h
@@ -913,6 +913,23 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(BIGNUM, BN_free)
+BORINGSSL_MAKE_DELETER(BN_CTX, BN_CTX_free)
+BORINGSSL_MAKE_DELETER(BN_MONT_CTX, BN_MONT_CTX_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define BN_R_ARG2_LT_ARG3 100
diff --git a/include/openssl/buf.h b/include/openssl/buf.h
index 8ae856b..7e39864 100644
--- a/include/openssl/buf.h
+++ b/include/openssl/buf.h
@@ -117,6 +117,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(BUF_MEM, BUF_MEM_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_BUFFER_H */
diff --git a/include/openssl/cmac.h b/include/openssl/cmac.h
index 0bb44b9..fb0b9f2 100644
--- a/include/openssl/cmac.h
+++ b/include/openssl/cmac.h
@@ -71,6 +71,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(CMAC_CTX, CMAC_CTX_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_CMAC_H */
diff --git a/include/openssl/conf.h b/include/openssl/conf.h
index 2aa3b79..8acb084 100644
--- a/include/openssl/conf.h
+++ b/include/openssl/conf.h
@@ -158,6 +158,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(CONF, NCONF_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define CONF_R_LIST_CANNOT_BE_NULL 100
diff --git a/include/openssl/curve25519.h b/include/openssl/curve25519.h
index a9441cd..70eff7a 100644
--- a/include/openssl/curve25519.h
+++ b/include/openssl/curve25519.h
@@ -167,6 +167,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(SPAKE2_CTX, SPAKE2_CTX_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_CURVE25519_H */
diff --git a/include/openssl/dh.h b/include/openssl/dh.h
index 4025656..a3f34d9 100644
--- a/include/openssl/dh.h
+++ b/include/openssl/dh.h
@@ -274,6 +274,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(DH, DH_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define DH_R_BAD_GENERATOR 100
diff --git a/include/openssl/dsa.h b/include/openssl/dsa.h
index 1e1ff65..07f1495 100644
--- a/include/openssl/dsa.h
+++ b/include/openssl/dsa.h
@@ -411,6 +411,22 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(DSA, DSA_free)
+BORINGSSL_MAKE_DELETER(DSA_SIG, DSA_SIG_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define DSA_R_BAD_Q_VALUE 100
diff --git a/include/openssl/ec.h b/include/openssl/ec.h
index 71c59d1..2349403 100644
--- a/include/openssl/ec.h
+++ b/include/openssl/ec.h
@@ -356,6 +356,22 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(EC_POINT, EC_POINT_free)
+BORINGSSL_MAKE_DELETER(EC_GROUP, EC_GROUP_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define EC_R_BUFFER_TOO_SMALL 100
diff --git a/include/openssl/ec_key.h b/include/openssl/ec_key.h
index 0658deb..a7c8bf8 100644
--- a/include/openssl/ec_key.h
+++ b/include/openssl/ec_key.h
@@ -321,6 +321,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(EC_KEY, EC_KEY_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_EC_KEY_H */
diff --git a/include/openssl/ecdsa.h b/include/openssl/ecdsa.h
index a060eab..5f07a9c 100644
--- a/include/openssl/ecdsa.h
+++ b/include/openssl/ecdsa.h
@@ -194,6 +194,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(ECDSA_SIG, ECDSA_SIG_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define ECDSA_R_BAD_SIGNATURE 100
diff --git a/include/openssl/engine.h b/include/openssl/engine.h
index 128a2ae..9cbdf39 100644
--- a/include/openssl/engine.h
+++ b/include/openssl/engine.h
@@ -91,6 +91,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(ENGINE, ENGINE_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define ENGINE_R_OPERATION_NOT_SUPPORTED 100
diff --git a/include/openssl/evp.h b/include/openssl/evp.h
index d5d528e..41e9e14 100644
--- a/include/openssl/evp.h
+++ b/include/openssl/evp.h
@@ -750,6 +750,22 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(EVP_CIPHER_CTX, EVP_CIPHER_CTX_free)
+BORINGSSL_MAKE_DELETER(EVP_PKEY, EVP_PKEY_free)
+BORINGSSL_MAKE_DELETER(EVP_PKEY_CTX, EVP_PKEY_CTX_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define EVP_R_BUFFER_TOO_SMALL 100
diff --git a/include/openssl/mem.h b/include/openssl/mem.h
index 31756f0..98ee077 100644
--- a/include/openssl/mem.h
+++ b/include/openssl/mem.h
@@ -133,6 +133,22 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(char, OPENSSL_free)
+BORINGSSL_MAKE_DELETER(uint8_t, OPENSSL_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif  /* OPENSSL_HEADER_MEM_H */
diff --git a/include/openssl/newhope.h b/include/openssl/newhope.h
index 487e03f..67728ea 100644
--- a/include/openssl/newhope.h
+++ b/include/openssl/newhope.h
@@ -142,6 +142,21 @@
 
 #if defined(__cplusplus)
 } /* extern "C" */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(NEWHOPE_POLY, NEWHOPE_POLY_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #endif /* OPENSSL_HEADER_NEWHOPE_H */
diff --git a/include/openssl/pkcs8.h b/include/openssl/pkcs8.h
index 28cf6ac..0939d8c 100644
--- a/include/openssl/pkcs8.h
+++ b/include/openssl/pkcs8.h
@@ -187,6 +187,22 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(PKCS12, PKCS12_free)
+BORINGSSL_MAKE_DELETER(PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define PKCS8_R_BAD_PKCS12_DATA 100
diff --git a/include/openssl/rsa.h b/include/openssl/rsa.h
index b4c7653..f761dc6 100644
--- a/include/openssl/rsa.h
+++ b/include/openssl/rsa.h
@@ -636,6 +636,21 @@
 
 #if defined(__cplusplus)
 }  /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(RSA, RSA_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define RSA_R_BAD_ENCODING 100
diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h
index 9787bcb..3d705ee 100644
--- a/include/openssl/ssl.h
+++ b/include/openssl/ssl.h
@@ -4646,6 +4646,23 @@
 
 #if defined(__cplusplus)
 } /* extern C */
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_DELETER(SSL, SSL_free)
+BORINGSSL_MAKE_DELETER(SSL_CTX, SSL_CTX_free)
+BORINGSSL_MAKE_DELETER(SSL_SESSION, SSL_SESSION_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define SSL_R_APP_DATA_IN_HANDSHAKE 100
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 5bbf651..c32a6e7 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -1224,6 +1224,38 @@
 
 #ifdef  __cplusplus
 }
+
+extern "C++" {
+
+namespace bssl {
+
+namespace internal {
+
+BORINGSSL_MAKE_STACK_DELETER(X509, X509_free)
+BORINGSSL_MAKE_DELETER(X509, X509_free)
+BORINGSSL_MAKE_DELETER(X509_ALGOR, X509_ALGOR_free)
+BORINGSSL_MAKE_DELETER(X509_CRL, X509_CRL_free)
+BORINGSSL_MAKE_DELETER(X509_CRL_METHOD, X509_CRL_METHOD_free)
+BORINGSSL_MAKE_DELETER(X509_EXTENSION, X509_EXTENSION_free)
+BORINGSSL_MAKE_DELETER(X509_INFO, X509_INFO_free)
+BORINGSSL_MAKE_DELETER(X509_LOOKUP, X509_LOOKUP_free)
+BORINGSSL_MAKE_DELETER(X509_NAME, X509_NAME_free)
+BORINGSSL_MAKE_DELETER(X509_NAME_ENTRY, X509_NAME_ENTRY_free)
+BORINGSSL_MAKE_DELETER(X509_PKEY, X509_PKEY_free)
+BORINGSSL_MAKE_DELETER(X509_POLICY_TREE, X509_policy_tree_free)
+BORINGSSL_MAKE_DELETER(X509_REQ, X509_REQ_free)
+BORINGSSL_MAKE_DELETER(X509_REVOKED, X509_REVOKED_free)
+BORINGSSL_MAKE_DELETER(X509_SIG, X509_SIG_free)
+BORINGSSL_MAKE_DELETER(X509_STORE, X509_STORE_free)
+BORINGSSL_MAKE_DELETER(X509_STORE_CTX, X509_STORE_CTX_free)
+BORINGSSL_MAKE_DELETER(X509_VERIFY_PARAM, X509_VERIFY_PARAM_free)
+
+}  // namespace internal
+
+}  // namespace bssl
+
+}  /* extern C++ */
+
 #endif
 
 #define X509_R_AKID_MISMATCH 100
diff --git a/include/openssl/x509_vfy.h b/include/openssl/x509_vfy.h
index 50ded0d..0a45aad 100644
--- a/include/openssl/x509_vfy.h
+++ b/include/openssl/x509_vfy.h
@@ -129,8 +129,6 @@
 		} data;
 	} X509_OBJECT;
 
-typedef struct x509_lookup_st X509_LOOKUP;
-
 DECLARE_STACK_OF(X509_LOOKUP)
 DECLARE_STACK_OF(X509_OBJECT)