Cut down on usage of deprecated APIs in //crypto.

SSL_library_init is deprecated. It's CRYPTO_library_init. Switch from the
legacy ASN.1 APIs to the new parsers where feasible.
ECPrivateKey::CreateFromEncryptedPrivateKeyInfo is left alone for now as we
still need a new version of those APIs.

This also adds a scoper for CBB for use in later CLs.

BUG=499653

Review URL: https://codereview.chromium.org/1739403002

Cr-Commit-Position: refs/heads/master@{#378610}
diff --git a/crypto/rsa_private_key_openssl.cc b/crypto/rsa_private_key_openssl.cc
index f7fdd9d..3e87a0a 100644
--- a/crypto/rsa_private_key_openssl.cc
+++ b/crypto/rsa_private_key_openssl.cc
@@ -4,55 +4,21 @@
 
 #include "crypto/rsa_private_key.h"
 
-#include <openssl/bio.h>
+#include <openssl/bytestring.h>
 #include <openssl/bn.h>
 #include <openssl/evp.h>
-#include <openssl/pkcs12.h>
+#include <openssl/mem.h>
 #include <openssl/rsa.h>
 #include <stdint.h>
 
 #include "base/logging.h"
 #include "base/memory/scoped_ptr.h"
+#include "crypto/auto_cbb.h"
 #include "crypto/openssl_util.h"
 #include "crypto/scoped_openssl_types.h"
 
 namespace crypto {
 
-namespace {
-
-using ScopedPKCS8_PRIV_KEY_INFO =
-    ScopedOpenSSL<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_free>;
-
-// Function pointer definition, for injecting the required key export function
-// into ExportKey, below. The supplied function should export EVP_PKEY into
-// the supplied BIO, returning 1 on success or 0 on failure.
-using ExportFunction = int (*)(BIO*, EVP_PKEY*);
-
-// Helper to export |key| into |output| via the specified ExportFunction.
-bool ExportKey(EVP_PKEY* key,
-               ExportFunction export_fn,
-               std::vector<uint8_t>* output) {
-  if (!key)
-    return false;
-
-  OpenSSLErrStackTracer err_tracer(FROM_HERE);
-  ScopedBIO bio(BIO_new(BIO_s_mem()));
-
-  int res = export_fn(bio.get(), key);
-  if (!res)
-    return false;
-
-  char* data = NULL;
-  long len = BIO_get_mem_data(bio.get(), &data);
-  if (!data || len < 0)
-    return false;
-
-  output->assign(data, data + len);
-  return true;
-}
-
-}  // namespace
-
 // static
 RSAPrivateKey* RSAPrivateKey::Create(uint16_t num_bits) {
   OpenSSLErrStackTracer err_tracer(FROM_HERE);
@@ -76,25 +42,16 @@
 // static
 RSAPrivateKey* RSAPrivateKey::CreateFromPrivateKeyInfo(
     const std::vector<uint8_t>& input) {
-  if (input.empty())
-    return NULL;
-
   OpenSSLErrStackTracer err_tracer(FROM_HERE);
 
-  // Importing is a little more involved than exporting, as we must first
-  // PKCS#8 decode the input, and then import the EVP_PKEY from Private Key
-  // Info structure returned.
-  const uint8_t* ptr = &input[0];
-  ScopedPKCS8_PRIV_KEY_INFO p8inf(
-      d2i_PKCS8_PRIV_KEY_INFO(nullptr, &ptr, input.size()));
-  if (!p8inf.get() || ptr != &input[0] + input.size())
-    return NULL;
+  CBS cbs;
+  CBS_init(&cbs, input.data(), input.size());
+  ScopedEVP_PKEY pkey(EVP_parse_private_key(&cbs));
+  if (!pkey || CBS_len(&cbs) != 0 || EVP_PKEY_id(pkey.get()) != EVP_PKEY_RSA)
+    return nullptr;
 
   scoped_ptr<RSAPrivateKey> result(new RSAPrivateKey);
-  result->key_ = EVP_PKCS82PKEY(p8inf.get());
-  if (!result->key_ || EVP_PKEY_id(result->key_) != EVP_PKEY_RSA)
-    return NULL;
-
+  result->key_ = pkey.release();
   return result.release();
 }
 
@@ -129,11 +86,31 @@
 }
 
 bool RSAPrivateKey::ExportPrivateKey(std::vector<uint8_t>* output) const {
-  return ExportKey(key_, i2d_PKCS8PrivateKeyInfo_bio, output);
+  uint8_t *der;
+  size_t der_len;
+  AutoCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EVP_marshal_private_key(cbb.get(), key_) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
+  return true;
 }
 
 bool RSAPrivateKey::ExportPublicKey(std::vector<uint8_t>* output) const {
-  return ExportKey(key_, i2d_PUBKEY_bio, output);
+  uint8_t *der;
+  size_t der_len;
+  AutoCBB cbb;
+  if (!CBB_init(cbb.get(), 0) ||
+      !EVP_marshal_public_key(cbb.get(), key_) ||
+      !CBB_finish(cbb.get(), &der, &der_len)) {
+    return false;
+  }
+  output->assign(der, der + der_len);
+  OPENSSL_free(der);
+  return true;
 }
 
 }  // namespace crypto