Use the new SPKI API in d2i_RSA_PUBKEY and friends

These functions only need to pull in the algorithms they support. The
new API is slightly less friendly in this context because it expects the
caller to have found the end first, but it's easy enough to to write a
small wrapper.

Bug: 42290364
Change-Id: Ibdc44f399182cd5722700917aec6c151221f4674
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/81747
Reviewed-by: Adam Langley <agl@google.com>
Auto-Submit: David Benjamin <davidben@google.com>
Commit-Queue: Adam Langley <agl@google.com>
diff --git a/crypto/evp/evp_asn1.cc b/crypto/evp/evp_asn1.cc
index 1f5216f..a135b0a 100644
--- a/crypto/evp/evp_asn1.cc
+++ b/crypto/evp/evp_asn1.cc
@@ -390,13 +390,28 @@
   return CBB_finish_i2d(&cbb, outp);
 }
 
+static bssl::UniquePtr<EVP_PKEY> parse_spki(
+    CBS *cbs, bssl::Span<const EVP_PKEY_ALG *const> algs) {
+  CBS spki;
+  if (!CBS_get_asn1_element(cbs, &spki, CBS_ASN1_SEQUENCE)) {
+    OPENSSL_PUT_ERROR(EVP, EVP_R_DECODE_ERROR);
+    return nullptr;
+  }
+  return bssl::UniquePtr<EVP_PKEY>(EVP_PKEY_from_subject_public_key_info(
+      CBS_data(&spki), CBS_len(&spki), algs.data(), algs.size()));
+}
+
+static bssl::UniquePtr<EVP_PKEY> parse_spki(CBS *cbs, const EVP_PKEY_ALG *alg) {
+  return parse_spki(cbs, bssl::Span(&alg, 1));
+}
+
 RSA *d2i_RSA_PUBKEY(RSA **out, const uint8_t **inp, long len) {
   if (len < 0) {
     return nullptr;
   }
   CBS cbs;
   CBS_init(&cbs, *inp, (size_t)len);
-  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+  bssl::UniquePtr<EVP_PKEY> pkey = parse_spki(&cbs, EVP_pkey_rsa());
   if (pkey == nullptr) {
     return nullptr;
   }
@@ -432,7 +447,7 @@
   }
   CBS cbs;
   CBS_init(&cbs, *inp, (size_t)len);
-  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+  bssl::UniquePtr<EVP_PKEY> pkey = parse_spki(&cbs, EVP_pkey_dsa());
   if (pkey == nullptr) {
     return nullptr;
   }
@@ -468,7 +483,9 @@
   }
   CBS cbs;
   CBS_init(&cbs, *inp, (size_t)len);
-  bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
+  const EVP_PKEY_ALG *const algs[] = {EVP_pkey_ec_p224(), EVP_pkey_ec_p256(),
+                                      EVP_pkey_ec_p384(), EVP_pkey_ec_p521()};
+  bssl::UniquePtr<EVP_PKEY> pkey = parse_spki(&cbs, algs);
   if (pkey == nullptr) {
     return nullptr;
   }