1 #pragma once
2
3 #include <android-base/logging.h>
4 #include <openssl/base.h>
5 #include <openssl/bio.h>
6 #include <openssl/pem.h>
7 #include <openssl/x509.h>
8 #include <vector>
9
10 #define AT __func__ << ":" << __LINE__ << " "
11
12 namespace {
13 // Helper method to extract public key from the certificate.
extractPubKey(const std::vector<uint8_t> & cert_bytes)14 std::vector<uint8_t> extractPubKey(const std::vector<uint8_t>& cert_bytes) {
15 const uint8_t* p = cert_bytes.data();
16 bssl::UniquePtr<X509> decoded_cert(d2i_X509(nullptr, &p, cert_bytes.size()));
17 if (!decoded_cert) {
18 LOG(INFO) << AT << "Could not decode the cert, trying decoding as PEM";
19 bssl::UniquePtr<BIO> cert_bio(BIO_new_mem_buf(cert_bytes.data(), cert_bytes.size()));
20 if (!cert_bio) {
21 LOG(ERROR) << AT << "Failed to create BIO";
22 return {};
23 }
24 decoded_cert =
25 bssl::UniquePtr<X509>(PEM_read_bio_X509(cert_bio.get(), nullptr, nullptr, nullptr));
26 }
27 if (!decoded_cert) {
28 LOG(ERROR) << AT << "Could not decode the cert.";
29 return {};
30 }
31 bssl::UniquePtr<EVP_PKEY> pub_key(X509_get_pubkey(decoded_cert.get()));
32 if (!pub_key) {
33 LOG(ERROR) << AT << "Could not extract public key.";
34 return {};
35 }
36 bssl::UniquePtr<BIO> pub_key_bio(BIO_new(BIO_s_mem()));
37 if (!pub_key_bio || i2d_PUBKEY_bio(pub_key_bio.get(), pub_key.get()) <= 0) {
38 LOG(ERROR) << AT << "Could not serialize public key.";
39 return {};
40 }
41 const uint8_t* pub_key_bytes;
42 size_t pub_key_len;
43 if (!BIO_mem_contents(pub_key_bio.get(), &pub_key_bytes, &pub_key_len)) {
44 LOG(ERROR) << AT << "Could not get bytes from BIO.";
45 return {};
46 }
47
48 return {pub_key_bytes, pub_key_bytes + pub_key_len};
49 }
50
51 } // namespace