Keystore 2.0 engine: Handle legacy PEM certificates.

Keystore 2.0 in Android S requires all new certificates to be stored in
DER format, however, when upgrading from R or older, there may be
certificates stored in PEM format. This patch allows keystore2-engine to
extract the public keys from certificates in either format.

Bug: 199155260
Test: N/A
Change-Id: I4bd5befcef15af5fbc2cbec3fdf4d581b1558b56
diff --git a/keystore-engine/keystore2_engine.cpp b/keystore-engine/keystore2_engine.cpp
index ee550ca..69caf51 100644
--- a/keystore-engine/keystore2_engine.cpp
+++ b/keystore-engine/keystore2_engine.cpp
@@ -23,11 +23,13 @@
 
 #include <private/android_filesystem_config.h>
 
+#include <openssl/bio.h>
 #include <openssl/bn.h>
 #include <openssl/ec.h>
 #include <openssl/ec_key.h>
 #include <openssl/ecdsa.h>
 #include <openssl/engine.h>
+#include <openssl/pem.h>
 #include <openssl/rsa.h>
 #include <openssl/x509.h>
 
@@ -327,6 +329,31 @@
     return 1;
 }
 
+bssl::UniquePtr<EVP_PKEY> extractPubKey(const std::vector<uint8_t>& cert_bytes) {
+    const uint8_t* p = cert_bytes.data();
+    bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &p, cert_bytes.size()));
+    if (!decoded_cert) {
+        LOG(INFO) << AT << "Could not decode the cert, trying decoding as PEM";
+        bssl::UniquePtr<BIO> cert_bio(BIO_new_mem_buf(cert_bytes.data(), cert_bytes.size()));
+        if (!cert_bio) {
+            LOG(ERROR) << AT << "Failed to create BIO";
+            return {};
+        }
+        decoded_cert =
+            bssl::UniquePtr<X509>(PEM_read_bio_X509(cert_bio.get(), nullptr, nullptr, nullptr));
+    }
+    if (!decoded_cert) {
+        LOG(ERROR) << AT << "Could not decode the cert.";
+        return {};
+    }
+    bssl::UniquePtr<EVP_PKEY> pub_key(X509_get_pubkey(decoded_cert.get()));
+    if (!pub_key) {
+        LOG(ERROR) << AT << "Could not extract public key.";
+        return {};
+    }
+    return pub_key;
+}
+
 }  // namespace
 
 /* EVP_PKEY_from_keystore returns an |EVP_PKEY| that contains either an RSA or
@@ -383,13 +410,7 @@
         return nullptr;
     }
 
-    const uint8_t* p = response.metadata.certificate->data();
-    bssl::UniquePtr<X509> x509(d2i_X509(nullptr, &p, response.metadata.certificate->size()));
-    if (!x509) {
-        LOG(ERROR) << AT << "Failed to parse x509 certificate.";
-        return nullptr;
-    }
-    bssl::UniquePtr<EVP_PKEY> pkey(X509_get_pubkey(x509.get()));
+    auto pkey = extractPubKey(*response.metadata.certificate);
     if (!pkey) {
         LOG(ERROR) << AT << "Failed to extract public key.";
         return nullptr;