Skip to content

Commit

Permalink
Keystore 2.0 engine: Handle legacy PEM certificates.
Browse files Browse the repository at this point in the history
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.

Ignore-AOSP-First: Cherry-Pick - Already on AOSP.

Bug: 199155260
Test: N/A
Change-Id: I4bd5befcef15af5fbc2cbec3fdf4d581b1558b56
Merged-In: I4bd5befcef15af5fbc2cbec3fdf4d581b1558b56
  • Loading branch information
Janis Danisevskis committed Nov 19, 2021
1 parent 89f78e9 commit b9f9bfa
Showing 1 changed file with 28 additions and 7 deletions.
35 changes: 28 additions & 7 deletions keystore-engine/keystore2_engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>

Expand Down Expand Up @@ -327,6 +329,31 @@ extern "C" int ecdsa_sign(const uint8_t* digest, size_t digest_len, uint8_t* sig
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
Expand Down Expand Up @@ -383,13 +410,7 @@ extern "C" EVP_PKEY* EVP_PKEY_from_keystore2(const char* key_id) {
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;
Expand Down

0 comments on commit b9f9bfa

Please sign in to comment.