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