diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-08-27 06:21:24 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2021-08-27 06:21:24 +0000 |
commit | c31fa8a386ba132e83d52db5bb4813c14f25839b (patch) | |
tree | 4ebda0556353a5f6e91bf11e3c1ad0a363cd4c19 | |
parent | 04bc908ac1248ce5f98cf0b837bdf094331e6cbc (diff) | |
parent | a6d06322f44b1e750d07bafbc2f1a7f436c2c8ac (diff) | |
download | interfaces-android12-mainline-extservices-release.tar.gz |
Snap for 7679530 from a6d06322f44b1e750d07bafbc2f1a7f436c2c8ac to mainline-extservices-releaseandroid-mainline-12.0.0_r9android-mainline-12.0.0_r87android-mainline-12.0.0_r72android-mainline-12.0.0_r44android-mainline-12.0.0_r27android-mainline-12.0.0_r117android-mainline-12.0.0_r102android12-mainline-extservices-release
Change-Id: Ib002960055c68661118d4873cbaa0986bba70746
-rw-r--r-- | suspend/1.0/default/SystemSuspend.cpp | 22 | ||||
-rw-r--r-- | suspend/1.0/default/SystemSuspend.h | 1 | ||||
-rw-r--r-- | wifi/keystore/1.0/default/keystore.cpp | 96 | ||||
-rw-r--r-- | wifi/keystore/1.0/default/test/Android.bp | 1 | ||||
-rw-r--r-- | wifi/keystore/1.0/default/test/WifiLegacyKeystoreIntegrationTest.cpp | 288 | ||||
-rw-r--r-- | wifi/keystore/1.0/default/wifikeystorehal_utils.h | 51 | ||||
-rw-r--r-- | wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp | 9 |
7 files changed, 414 insertions, 54 deletions
diff --git a/suspend/1.0/default/SystemSuspend.cpp b/suspend/1.0/default/SystemSuspend.cpp index 81f3d45..e9bb646 100644 --- a/suspend/1.0/default/SystemSuspend.cpp +++ b/suspend/1.0/default/SystemSuspend.cpp @@ -18,6 +18,7 @@ #include <android-base/file.h> #include <android-base/logging.h> +#include <android-base/stringprintf.h> #include <android-base/strings.h> #include <fcntl.h> #include <hidl/Status.h> @@ -70,8 +71,8 @@ static std::vector<std::string> readWakeupReasons(int fd) { std::string reasonlines; lseek(fd, 0, SEEK_SET); - if (!ReadFdToString(fd, &reasonlines)) { - LOG(ERROR) << "failed to read wakeup reasons"; + if (!ReadFdToString(fd, &reasonlines) || reasonlines.empty()) { + PLOG(ERROR) << "failed to read wakeup reasons"; // Return unknown wakeup reason if we fail to read return {kUnknownWakeup}; } @@ -236,6 +237,17 @@ void SystemSuspend::decSuspendCounter(const string& name) { } } +unique_fd SystemSuspend::reopenFileUsingFd(const int fd, const int permission) { + string filePath = android::base::StringPrintf("/proc/self/fd/%d", fd); + + unique_fd tempFd{TEMP_FAILURE_RETRY(open(filePath.c_str(), permission))}; + if (tempFd < 0) { + PLOG(ERROR) << "SystemSuspend: Error opening file, using path: " << filePath; + return unique_fd(-1); + } + return tempFd; +} + void SystemSuspend::initAutosuspend() { std::thread autosuspendThread([this] { while (true) { @@ -268,6 +280,12 @@ void SystemSuspend::initAutosuspend() { updateSleepTime(success, suspendTime); std::vector<std::string> wakeupReasons = readWakeupReasons(mWakeupReasonsFd); + if (wakeupReasons == std::vector<std::string>({kUnknownWakeup})) { + LOG(INFO) << "Unknown/empty wakeup reason. Re-opening wakeup_reason file."; + + mWakeupReasonsFd = + std::move(reopenFileUsingFd(mWakeupReasonsFd.get(), O_CLOEXEC | O_RDONLY)); + } mWakeupList.update(wakeupReasons); mControlService->notifyWakeup(success, wakeupReasons); diff --git a/suspend/1.0/default/SystemSuspend.h b/suspend/1.0/default/SystemSuspend.h index 5632325..b84b1c9 100644 --- a/suspend/1.0/default/SystemSuspend.h +++ b/suspend/1.0/default/SystemSuspend.h @@ -114,6 +114,7 @@ class SystemSuspend : public ISystemSuspend { Result<SuspendStats> getSuspendStats(); void getSuspendInfo(SuspendInfo* info); std::chrono::milliseconds getSleepTime() const; + unique_fd reopenFileUsingFd(const int fd, int permission); private: void initAutosuspend(); diff --git a/wifi/keystore/1.0/default/keystore.cpp b/wifi/keystore/1.0/default/keystore.cpp index a8faa10..69bac18 100644 --- a/wifi/keystore/1.0/default/keystore.cpp +++ b/wifi/keystore/1.0/default/keystore.cpp @@ -7,19 +7,17 @@ #include <android-base/strings.h> #include <android/binder_manager.h> #include <binder/IServiceManager.h> -#include <ctype.h> #include <openssl/base.h> #include <openssl/bio.h> #include <openssl/pem.h> #include <openssl/x509.h> #include <private/android_filesystem_config.h> #include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <future> #include <vector> +#include "wifikeystorehal_utils.h" + #define AT __func__ << ":" << __LINE__ << " " namespace ks2 = ::aidl::android::system::keystore2; @@ -35,43 +33,6 @@ constexpr const char kLegacyKeystoreServiceName[] = "android.security.legacykeys const std::string keystore2_grant_id_prefix("ks2_keystore-engine_grant_id:"); -// Helper method to extract public key from the certificate. -std::vector<uint8_t> extractPubKey(const std::vector<uint8_t>& cert_bytes) { - 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 {}; - } - bssl::UniquePtr<X509> decoded_cert(d2i_X509_bio(cert_bio.get(), nullptr)); - if (!decoded_cert) { - LOG(INFO) << AT << "Could not decode the cert, trying decoding as PEM"; - 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 {}; - } - bssl::UniquePtr<BIO> pub_key_bio(BIO_new(BIO_s_mem())); - if (!pub_key_bio || i2d_PUBKEY_bio(pub_key_bio.get(), pub_key.get()) <= 0) { - LOG(ERROR) << AT << "Could not serialize public key."; - return {}; - } - const uint8_t* pub_key_bytes; - size_t pub_key_len; - if (!BIO_mem_contents(pub_key_bio.get(), &pub_key_bytes, &pub_key_len)) { - LOG(ERROR) << AT << "Could not get bytes from BIO."; - return {}; - } - - return {pub_key_bytes, pub_key_bytes + pub_key_len}; -} - ks2::KeyDescriptor mkKeyDescriptor(const std::string& alias) { // If the key_id starts with the grant id prefix, we parse the following string as numeric // grant id. We can then use the grant domain without alias to load the designated key. @@ -101,6 +62,46 @@ ks2::KeyDescriptor mkKeyDescriptor(const std::string& alias) { using android::hardware::hidl_string; using android::hardware::hidl_vec; +// Helper method to convert certs in DER format to PEM format required by +// openssl library used by supplicant. If boringssl cannot parse the input as one or more +// X509 certificates in DER encoding, this function returns the input as-is. The assumption in +// that case is that either the `cert_bytes` is already PEM encoded, or `cert_bytes` is something +// completely different that was intentionally installed by the Wi-Fi subsystem and it must not +// be changed here. +// If any error occurs during PEM encoding, this function returns std::nullopt and logs an error. +std::optional<hidl_vec<uint8_t>> convertDerCertToPemOrPassthrough( + const std::vector<uint8_t>& cert_bytes) { + // If cert_bytes is a DER encoded X509 certificate, it must be reencoded as PEM, because + // wpa_supplicant only understand PEM. Otherwise the cert_bytes are returned as is. + const uint8_t* cert_current = cert_bytes.data(); + const uint8_t* cert_end = cert_current + cert_bytes.size(); + bssl::UniquePtr<BIO> pem_bio(BIO_new(BIO_s_mem())); + while (cert_current < cert_end) { + auto cert = + bssl::UniquePtr<X509>(d2i_X509(nullptr, &cert_current, cert_end - cert_current)); + // If part of the bytes cannot be parsed as X509 DER certificate, the original blob + // shall be returned as-is. + if (!cert) { + LOG(WARNING) << AT + << "Could not parse DER X509 cert from buffer. Returning blob as is."; + return cert_bytes; + } + + if (!PEM_write_bio_X509(pem_bio.get(), cert.get())) { + LOG(ERROR) << AT << "Could not convert cert to PEM format."; + return std::nullopt; + } + } + + const uint8_t* pem_bytes; + size_t pem_len; + if (!BIO_mem_contents(pem_bio.get(), &pem_bytes, &pem_len)) { + LOG(ERROR) << AT << "Could not extract pem_bytes from BIO."; + return std::nullopt; + } + return {{pem_bytes, pem_bytes + pem_len}}; +} + std::optional<std::vector<uint8_t>> keyStore2GetCert(const hidl_string& key) { ::ndk::SpAIBinder keystoreBinder(AServiceManager_checkService(kKeystore2ServiceName)); auto keystore2 = ks2::IKeystoreService::fromBinder(keystoreBinder); @@ -326,13 +327,22 @@ namespace V1_0 { namespace implementation { // Methods from ::android::hardware::wifi::keystore::V1_0::IKeystore follow. Return<void> Keystore::getBlob(const hidl_string& key, getBlob_cb _hidl_cb) { + std::vector<uint8_t> result_cert; if (auto ks2_cert = keyStore2GetCert(key)) { - _hidl_cb(KeystoreStatusCode::SUCCESS, std::move(*ks2_cert)); + result_cert = std::move(*ks2_cert); } else if (auto blob = getLegacyKeystoreBlob(key)) { - _hidl_cb(KeystoreStatusCode::SUCCESS, *blob); + result_cert = std::move(*blob); } else { LOG(ERROR) << AT << "Failed to get certificate."; _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {}); + return Void(); + } + + if (auto result_cert_hidl = convertDerCertToPemOrPassthrough(result_cert)) { + _hidl_cb(KeystoreStatusCode::SUCCESS, *result_cert_hidl); + } else { + LOG(ERROR) << AT << "Conversion to PEM failed."; + _hidl_cb(KeystoreStatusCode::ERROR_UNKNOWN, {}); } return Void(); } diff --git a/wifi/keystore/1.0/default/test/Android.bp b/wifi/keystore/1.0/default/test/Android.bp index e16155b..eef58e9 100644 --- a/wifi/keystore/1.0/default/test/Android.bp +++ b/wifi/keystore/1.0/default/test/Android.bp @@ -23,6 +23,7 @@ cc_test { shared_libs: [ "libbase", "liblog", + "libcrypto", "libcutils", "libhidlbase", "libnativehelper", diff --git a/wifi/keystore/1.0/default/test/WifiLegacyKeystoreIntegrationTest.cpp b/wifi/keystore/1.0/default/test/WifiLegacyKeystoreIntegrationTest.cpp index b6dcf01..ac801e5 100644 --- a/wifi/keystore/1.0/default/test/WifiLegacyKeystoreIntegrationTest.cpp +++ b/wifi/keystore/1.0/default/test/WifiLegacyKeystoreIntegrationTest.cpp @@ -15,19 +15,16 @@ */ #include <aidl/android/security/legacykeystore/ILegacyKeystore.h> -#include <aidl/android/system/keystore2/IKeystoreOperation.h> -#include <aidl/android/system/keystore2/IKeystoreSecurityLevel.h> -#include <aidl/android/system/keystore2/IKeystoreService.h> #include <aidl/android/system/keystore2/ResponseCode.h> #include <android/binder_manager.h> #include <android/system/wifi/keystore/1.0/IKeystore.h> -#include <binder/IServiceManager.h> #include <cutils/properties.h> #include <gtest/gtest.h> #include <hidl/GtestPrinter.h> #include <hidl/ServiceManagement.h> #include <private/android_filesystem_config.h> -#include <utils/String16.h> + +#include "../wifikeystorehal_utils.h" using namespace std; using namespace ::testing; @@ -50,6 +47,65 @@ enum KeyPurpose { SIGNING, }; +// Some test certificate in PEM encoding. +static const char kPemTestCert[] = R"(-----BEGIN CERTIFICATE----- +MIICWDCCAcGgAwIBAgIUMpH52TRcL1gTknsm5eR+wvCGxNMwDQYJKoZIhvcNAQEL +BQAwPjELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxGjAYBgNVBAoM +EUFuZHJvaWQgVGVzdCBDZXJ0MB4XDTIxMDczMDAwMzY1OVoXDTIyMDczMDAwMzY1 +OVowPjELMAkGA1UEBhMCVVMxEzARBgNVBAgMClNvbWUtU3RhdGUxGjAYBgNVBAoM +EUFuZHJvaWQgVGVzdCBDZXJ0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDL +q7JTXvL3ErVX2ZU9hQ0PLnkyw984qweNhQw8xIvwzTs3hXtV0K4hmWJiPKxOv3H7 +Q//TOcxI6+Qp4qOa79UUYDvmObjOCW1jQvZ9UQQfvdMO1WSa3BQoPJYQXiuyiuPs ++XM58Yl8TPV+IQ+Znx5axn5PxEmoqCUmeBv/wbJlDwIDAQABo1MwUTAdBgNVHQ4E +FgQUEbhF5fYkUPchj+GdWX1aoOHkH3owHwYDVR0jBBgwFoAUEbhF5fYkUPchj+Gd +WX1aoOHkH3owDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQChejph +iYWFBeQEQtPYGGwSNO1HgzRhvsdGKDJUtRDAvDPxlRO8jkGmrSaD3QJUY4bCkx5c +S9W7oRxyiUaxJFtw9Lbxkc4G3v0hpxYqfX4R4lzM8oU/50cPEpZGVaIZNrqBiXbd +wFzPSv/UTXFBKlR5grYTmsiHCBbEv0apNJNI0g== +-----END CERTIFICATE----- +)"; + +// Some test certificate in DER encoding. +static const std::vector<uint8_t> kDerTestCert{ + 0x30, 0x82, 0x02, 0x58, 0x30, 0x82, 0x01, 0xc1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x32, + 0x91, 0xf9, 0xd9, 0x34, 0x5c, 0x2f, 0x58, 0x13, 0x92, 0x7b, 0x26, 0xe5, 0xe4, 0x7e, 0xc2, 0xf0, + 0x86, 0xc4, 0xd3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, + 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, + 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, + 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x32, 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, + 0x39, 0x5a, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, + 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, + 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, + 0x72, 0x74, 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcb, + 0xab, 0xb2, 0x53, 0x5e, 0xf2, 0xf7, 0x12, 0xb5, 0x57, 0xd9, 0x95, 0x3d, 0x85, 0x0d, 0x0f, 0x2e, + 0x79, 0x32, 0xc3, 0xdf, 0x38, 0xab, 0x07, 0x8d, 0x85, 0x0c, 0x3c, 0xc4, 0x8b, 0xf0, 0xcd, 0x3b, + 0x37, 0x85, 0x7b, 0x55, 0xd0, 0xae, 0x21, 0x99, 0x62, 0x62, 0x3c, 0xac, 0x4e, 0xbf, 0x71, 0xfb, + 0x43, 0xff, 0xd3, 0x39, 0xcc, 0x48, 0xeb, 0xe4, 0x29, 0xe2, 0xa3, 0x9a, 0xef, 0xd5, 0x14, 0x60, + 0x3b, 0xe6, 0x39, 0xb8, 0xce, 0x09, 0x6d, 0x63, 0x42, 0xf6, 0x7d, 0x51, 0x04, 0x1f, 0xbd, 0xd3, + 0x0e, 0xd5, 0x64, 0x9a, 0xdc, 0x14, 0x28, 0x3c, 0x96, 0x10, 0x5e, 0x2b, 0xb2, 0x8a, 0xe3, 0xec, + 0xf9, 0x73, 0x39, 0xf1, 0x89, 0x7c, 0x4c, 0xf5, 0x7e, 0x21, 0x0f, 0x99, 0x9f, 0x1e, 0x5a, 0xc6, + 0x7e, 0x4f, 0xc4, 0x49, 0xa8, 0xa8, 0x25, 0x26, 0x78, 0x1b, 0xff, 0xc1, 0xb2, 0x65, 0x0f, 0x02, + 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x11, 0xb8, 0x45, 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, + 0x7d, 0x5a, 0xa0, 0xe1, 0xe4, 0x1f, 0x7a, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0x11, 0xb8, 0x45, 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, + 0x59, 0x7d, 0x5a, 0xa0, 0xe1, 0xe4, 0x1f, 0x7a, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, + 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, + 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xa1, 0x7a, 0x3a, 0x61, + 0x89, 0x85, 0x85, 0x05, 0xe4, 0x04, 0x42, 0xd3, 0xd8, 0x18, 0x6c, 0x12, 0x34, 0xed, 0x47, 0x83, + 0x34, 0x61, 0xbe, 0xc7, 0x46, 0x28, 0x32, 0x54, 0xb5, 0x10, 0xc0, 0xbc, 0x33, 0xf1, 0x95, 0x13, + 0xbc, 0x8e, 0x41, 0xa6, 0xad, 0x26, 0x83, 0xdd, 0x02, 0x54, 0x63, 0x86, 0xc2, 0x93, 0x1e, 0x5c, + 0x4b, 0xd5, 0xbb, 0xa1, 0x1c, 0x72, 0x89, 0x46, 0xb1, 0x24, 0x5b, 0x70, 0xf4, 0xb6, 0xf1, 0x91, + 0xce, 0x06, 0xde, 0xfd, 0x21, 0xa7, 0x16, 0x2a, 0x7d, 0x7e, 0x11, 0xe2, 0x5c, 0xcc, 0xf2, 0x85, + 0x3f, 0xe7, 0x47, 0x0f, 0x12, 0x96, 0x46, 0x55, 0xa2, 0x19, 0x36, 0xba, 0x81, 0x89, 0x76, 0xdd, + 0xc0, 0x5c, 0xcf, 0x4a, 0xff, 0xd4, 0x4d, 0x71, 0x41, 0x2a, 0x54, 0x79, 0x82, 0xb6, 0x13, 0x9a, + 0xc8, 0x87, 0x08, 0x16, 0xc4, 0xbf, 0x46, 0xa9, 0x34, 0x93, 0x48, 0xd2}; + // The fixture for testing the Wifi Keystore HAL legacy keystore integration. class WifiLegacyKeystoreTest : public TestWithParam<std::string> { protected: @@ -163,10 +219,10 @@ TEST_P(WifiLegacyKeystoreTest, GetLegacyKeystoreTest) { << "Cannot transition to AID_SYSTEM."; } - // Only AID_SYSTEM (and AID_WIFI) is allowed to manipulate + // Only AID_SYSTEM (and AID_WIFI) is allowed to manipulate the wifi namespace. ASSERT_EQ(0, seteuid(AID_SYSTEM)) << "Failed to set uid to AID_SYSTEM: " << strerror(errno); - const std::vector<uint8_t> TESTBLOB{1, 2, 3, 5}; + const std::vector<uint8_t> TESTBLOB(std::begin(kPemTestCert), std::end(kPemTestCert)); const std::string TESTALIAS = "LegacyKeystoreWifiTestAlias"; ASSERT_TRUE(LegacyKeystoreRemove(TESTALIAS, AID_WIFI)); @@ -188,4 +244,222 @@ TEST_P(WifiLegacyKeystoreTest, GetLegacyKeystoreTest) { ASSERT_TRUE(LegacyKeystoreRemove(TESTALIAS, AID_WIFI)); } +/* + * This tests checks that a DER encoded certificate is always returned in PEM encoding by getBlob. + */ +TEST_P(WifiLegacyKeystoreTest, IKeystoreGetAlwaysReturnsPem) { + if (!isDebuggableBuild() || getuid() != 0) { + GTEST_SKIP() << "Device not running a debuggable build or not running as root. " + << "Cannot transition to AID_SYSTEM."; + } + + // Only AID_SYSTEM (and AID_WIFI) is allowed to manipulate + ASSERT_EQ(0, seteuid(AID_SYSTEM)) << "Failed to set uid to AID_SYSTEM: " << strerror(errno); + + const std::string TESTALIAS = "LegacyKeystoreWifiTestAlias"; + + ASSERT_TRUE(LegacyKeystoreRemove(TESTALIAS, AID_WIFI)); + ASSERT_TRUE(LegacyKeystorePut(TESTALIAS, kDerTestCert, AID_WIFI)); + + IKeystore::KeystoreStatusCode statusCode; + std::vector<uint8_t> blob; + auto rc = wifiKeystoreHal->getBlob(TESTALIAS, + [&](IKeystore::KeystoreStatusCode status, + const ::android::hardware::hidl_vec<uint8_t>& value) { + statusCode = status; + blob = value; + }); + + ASSERT_TRUE(rc.isOk()) << "Description: " << rc.description(); + ASSERT_EQ(IKeystore::KeystoreStatusCode::SUCCESS, statusCode); + + std::string blob_str(reinterpret_cast<const char*>(blob.data()), + reinterpret_cast<const char*>(blob.data()) + blob.size()); + ASSERT_EQ(blob_str.rfind("-----BEGIN CERTIFICATE-----", 0), 0); + ASSERT_TRUE(LegacyKeystoreRemove(TESTALIAS, AID_WIFI)); +} + +/* + * This tests checks that a DER encoded certificate is always returned in PEM encoding by getBlob. + */ +TEST_P(WifiLegacyKeystoreTest, IKeystoreGetAlwaysReturnsPemWithChain) { + if (!isDebuggableBuild() || getuid() != 0) { + GTEST_SKIP() << "Device not running a debuggable build or not running as root. " + << "Cannot transition to AID_SYSTEM."; + } + + // Only AID_SYSTEM (and AID_WIFI) is allowed to manipulate + ASSERT_EQ(0, seteuid(AID_SYSTEM)) << "Failed to set uid to AID_SYSTEM: " << strerror(errno); + + // Some test certificate in DER encoding, this is three times the same cert. + const std::vector<uint8_t> TESTBLOB_DER_3CERT{ + 0x30, 0x82, 0x02, 0x58, 0x30, 0x82, 0x01, 0xc1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, + 0x32, 0x91, 0xf9, 0xd9, 0x34, 0x5c, 0x2f, 0x58, 0x13, 0x92, 0x7b, 0x26, 0xe5, 0xe4, 0x7e, + 0xc2, 0xf0, 0x86, 0xc4, 0xd3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, + 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x32, + 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, 0x39, 0x5a, 0x30, 0x3e, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x41, 0x6e, + 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcb, + 0xab, 0xb2, 0x53, 0x5e, 0xf2, 0xf7, 0x12, 0xb5, 0x57, 0xd9, 0x95, 0x3d, 0x85, 0x0d, 0x0f, + 0x2e, 0x79, 0x32, 0xc3, 0xdf, 0x38, 0xab, 0x07, 0x8d, 0x85, 0x0c, 0x3c, 0xc4, 0x8b, 0xf0, + 0xcd, 0x3b, 0x37, 0x85, 0x7b, 0x55, 0xd0, 0xae, 0x21, 0x99, 0x62, 0x62, 0x3c, 0xac, 0x4e, + 0xbf, 0x71, 0xfb, 0x43, 0xff, 0xd3, 0x39, 0xcc, 0x48, 0xeb, 0xe4, 0x29, 0xe2, 0xa3, 0x9a, + 0xef, 0xd5, 0x14, 0x60, 0x3b, 0xe6, 0x39, 0xb8, 0xce, 0x09, 0x6d, 0x63, 0x42, 0xf6, 0x7d, + 0x51, 0x04, 0x1f, 0xbd, 0xd3, 0x0e, 0xd5, 0x64, 0x9a, 0xdc, 0x14, 0x28, 0x3c, 0x96, 0x10, + 0x5e, 0x2b, 0xb2, 0x8a, 0xe3, 0xec, 0xf9, 0x73, 0x39, 0xf1, 0x89, 0x7c, 0x4c, 0xf5, 0x7e, + 0x21, 0x0f, 0x99, 0x9f, 0x1e, 0x5a, 0xc6, 0x7e, 0x4f, 0xc4, 0x49, 0xa8, 0xa8, 0x25, 0x26, + 0x78, 0x1b, 0xff, 0xc1, 0xb2, 0x65, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, + 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x11, 0xb8, 0x45, + 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, 0x7d, 0x5a, 0xa0, 0xe1, 0xe4, + 0x1f, 0x7a, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x11, 0xb8, 0x45, 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, 0x7d, 0x5a, + 0xa0, 0xe1, 0xe4, 0x1f, 0x7a, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xa1, 0x7a, 0x3a, 0x61, + 0x89, 0x85, 0x85, 0x05, 0xe4, 0x04, 0x42, 0xd3, 0xd8, 0x18, 0x6c, 0x12, 0x34, 0xed, 0x47, + 0x83, 0x34, 0x61, 0xbe, 0xc7, 0x46, 0x28, 0x32, 0x54, 0xb5, 0x10, 0xc0, 0xbc, 0x33, 0xf1, + 0x95, 0x13, 0xbc, 0x8e, 0x41, 0xa6, 0xad, 0x26, 0x83, 0xdd, 0x02, 0x54, 0x63, 0x86, 0xc2, + 0x93, 0x1e, 0x5c, 0x4b, 0xd5, 0xbb, 0xa1, 0x1c, 0x72, 0x89, 0x46, 0xb1, 0x24, 0x5b, 0x70, + 0xf4, 0xb6, 0xf1, 0x91, 0xce, 0x06, 0xde, 0xfd, 0x21, 0xa7, 0x16, 0x2a, 0x7d, 0x7e, 0x11, + 0xe2, 0x5c, 0xcc, 0xf2, 0x85, 0x3f, 0xe7, 0x47, 0x0f, 0x12, 0x96, 0x46, 0x55, 0xa2, 0x19, + 0x36, 0xba, 0x81, 0x89, 0x76, 0xdd, 0xc0, 0x5c, 0xcf, 0x4a, 0xff, 0xd4, 0x4d, 0x71, 0x41, + 0x2a, 0x54, 0x79, 0x82, 0xb6, 0x13, 0x9a, 0xc8, 0x87, 0x08, 0x16, 0xc4, 0xbf, 0x46, 0xa9, + 0x34, 0x93, 0x48, 0xd2, // End of first cert. + 0x30, 0x82, 0x02, 0x58, 0x30, 0x82, 0x01, 0xc1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, + 0x32, 0x91, 0xf9, 0xd9, 0x34, 0x5c, 0x2f, 0x58, 0x13, 0x92, 0x7b, 0x26, 0xe5, 0xe4, 0x7e, + 0xc2, 0xf0, 0x86, 0xc4, 0xd3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, + 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x32, + 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, 0x39, 0x5a, 0x30, 0x3e, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x41, 0x6e, + 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcb, + 0xab, 0xb2, 0x53, 0x5e, 0xf2, 0xf7, 0x12, 0xb5, 0x57, 0xd9, 0x95, 0x3d, 0x85, 0x0d, 0x0f, + 0x2e, 0x79, 0x32, 0xc3, 0xdf, 0x38, 0xab, 0x07, 0x8d, 0x85, 0x0c, 0x3c, 0xc4, 0x8b, 0xf0, + 0xcd, 0x3b, 0x37, 0x85, 0x7b, 0x55, 0xd0, 0xae, 0x21, 0x99, 0x62, 0x62, 0x3c, 0xac, 0x4e, + 0xbf, 0x71, 0xfb, 0x43, 0xff, 0xd3, 0x39, 0xcc, 0x48, 0xeb, 0xe4, 0x29, 0xe2, 0xa3, 0x9a, + 0xef, 0xd5, 0x14, 0x60, 0x3b, 0xe6, 0x39, 0xb8, 0xce, 0x09, 0x6d, 0x63, 0x42, 0xf6, 0x7d, + 0x51, 0x04, 0x1f, 0xbd, 0xd3, 0x0e, 0xd5, 0x64, 0x9a, 0xdc, 0x14, 0x28, 0x3c, 0x96, 0x10, + 0x5e, 0x2b, 0xb2, 0x8a, 0xe3, 0xec, 0xf9, 0x73, 0x39, 0xf1, 0x89, 0x7c, 0x4c, 0xf5, 0x7e, + 0x21, 0x0f, 0x99, 0x9f, 0x1e, 0x5a, 0xc6, 0x7e, 0x4f, 0xc4, 0x49, 0xa8, 0xa8, 0x25, 0x26, + 0x78, 0x1b, 0xff, 0xc1, 0xb2, 0x65, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, + 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x11, 0xb8, 0x45, + 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, 0x7d, 0x5a, 0xa0, 0xe1, 0xe4, + 0x1f, 0x7a, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x11, 0xb8, 0x45, 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, 0x7d, 0x5a, + 0xa0, 0xe1, 0xe4, 0x1f, 0x7a, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xa1, 0x7a, 0x3a, 0x61, + 0x89, 0x85, 0x85, 0x05, 0xe4, 0x04, 0x42, 0xd3, 0xd8, 0x18, 0x6c, 0x12, 0x34, 0xed, 0x47, + 0x83, 0x34, 0x61, 0xbe, 0xc7, 0x46, 0x28, 0x32, 0x54, 0xb5, 0x10, 0xc0, 0xbc, 0x33, 0xf1, + 0x95, 0x13, 0xbc, 0x8e, 0x41, 0xa6, 0xad, 0x26, 0x83, 0xdd, 0x02, 0x54, 0x63, 0x86, 0xc2, + 0x93, 0x1e, 0x5c, 0x4b, 0xd5, 0xbb, 0xa1, 0x1c, 0x72, 0x89, 0x46, 0xb1, 0x24, 0x5b, 0x70, + 0xf4, 0xb6, 0xf1, 0x91, 0xce, 0x06, 0xde, 0xfd, 0x21, 0xa7, 0x16, 0x2a, 0x7d, 0x7e, 0x11, + 0xe2, 0x5c, 0xcc, 0xf2, 0x85, 0x3f, 0xe7, 0x47, 0x0f, 0x12, 0x96, 0x46, 0x55, 0xa2, 0x19, + 0x36, 0xba, 0x81, 0x89, 0x76, 0xdd, 0xc0, 0x5c, 0xcf, 0x4a, 0xff, 0xd4, 0x4d, 0x71, 0x41, + 0x2a, 0x54, 0x79, 0x82, 0xb6, 0x13, 0x9a, 0xc8, 0x87, 0x08, 0x16, 0xc4, 0xbf, 0x46, 0xa9, + 0x34, 0x93, 0x48, 0xd2, // End of second. + 0x30, 0x82, 0x02, 0x58, 0x30, 0x82, 0x01, 0xc1, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, + 0x32, 0x91, 0xf9, 0xd9, 0x34, 0x5c, 0x2f, 0x58, 0x13, 0x92, 0x7b, 0x26, 0xe5, 0xe4, 0x7e, + 0xc2, 0xf0, 0x86, 0xc4, 0xd3, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, + 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x41, 0x6e, 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, + 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, + 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x32, + 0x30, 0x37, 0x33, 0x30, 0x30, 0x30, 0x33, 0x36, 0x35, 0x39, 0x5a, 0x30, 0x3e, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x53, 0x6f, 0x6d, 0x65, 0x2d, 0x53, 0x74, 0x61, + 0x74, 0x65, 0x31, 0x1a, 0x30, 0x18, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x11, 0x41, 0x6e, + 0x64, 0x72, 0x6f, 0x69, 0x64, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, + 0x30, 0x81, 0x9f, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, + 0x01, 0x05, 0x00, 0x03, 0x81, 0x8d, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xcb, + 0xab, 0xb2, 0x53, 0x5e, 0xf2, 0xf7, 0x12, 0xb5, 0x57, 0xd9, 0x95, 0x3d, 0x85, 0x0d, 0x0f, + 0x2e, 0x79, 0x32, 0xc3, 0xdf, 0x38, 0xab, 0x07, 0x8d, 0x85, 0x0c, 0x3c, 0xc4, 0x8b, 0xf0, + 0xcd, 0x3b, 0x37, 0x85, 0x7b, 0x55, 0xd0, 0xae, 0x21, 0x99, 0x62, 0x62, 0x3c, 0xac, 0x4e, + 0xbf, 0x71, 0xfb, 0x43, 0xff, 0xd3, 0x39, 0xcc, 0x48, 0xeb, 0xe4, 0x29, 0xe2, 0xa3, 0x9a, + 0xef, 0xd5, 0x14, 0x60, 0x3b, 0xe6, 0x39, 0xb8, 0xce, 0x09, 0x6d, 0x63, 0x42, 0xf6, 0x7d, + 0x51, 0x04, 0x1f, 0xbd, 0xd3, 0x0e, 0xd5, 0x64, 0x9a, 0xdc, 0x14, 0x28, 0x3c, 0x96, 0x10, + 0x5e, 0x2b, 0xb2, 0x8a, 0xe3, 0xec, 0xf9, 0x73, 0x39, 0xf1, 0x89, 0x7c, 0x4c, 0xf5, 0x7e, + 0x21, 0x0f, 0x99, 0x9f, 0x1e, 0x5a, 0xc6, 0x7e, 0x4f, 0xc4, 0x49, 0xa8, 0xa8, 0x25, 0x26, + 0x78, 0x1b, 0xff, 0xc1, 0xb2, 0x65, 0x0f, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x53, 0x30, + 0x51, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x11, 0xb8, 0x45, + 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, 0x7d, 0x5a, 0xa0, 0xe1, 0xe4, + 0x1f, 0x7a, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x11, 0xb8, 0x45, 0xe5, 0xf6, 0x24, 0x50, 0xf7, 0x21, 0x8f, 0xe1, 0x9d, 0x59, 0x7d, 0x5a, + 0xa0, 0xe1, 0xe4, 0x1f, 0x7a, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x81, 0x81, 0x00, 0xa1, 0x7a, 0x3a, 0x61, + 0x89, 0x85, 0x85, 0x05, 0xe4, 0x04, 0x42, 0xd3, 0xd8, 0x18, 0x6c, 0x12, 0x34, 0xed, 0x47, + 0x83, 0x34, 0x61, 0xbe, 0xc7, 0x46, 0x28, 0x32, 0x54, 0xb5, 0x10, 0xc0, 0xbc, 0x33, 0xf1, + 0x95, 0x13, 0xbc, 0x8e, 0x41, 0xa6, 0xad, 0x26, 0x83, 0xdd, 0x02, 0x54, 0x63, 0x86, 0xc2, + 0x93, 0x1e, 0x5c, 0x4b, 0xd5, 0xbb, 0xa1, 0x1c, 0x72, 0x89, 0x46, 0xb1, 0x24, 0x5b, 0x70, + 0xf4, 0xb6, 0xf1, 0x91, 0xce, 0x06, 0xde, 0xfd, 0x21, 0xa7, 0x16, 0x2a, 0x7d, 0x7e, 0x11, + 0xe2, 0x5c, 0xcc, 0xf2, 0x85, 0x3f, 0xe7, 0x47, 0x0f, 0x12, 0x96, 0x46, 0x55, 0xa2, 0x19, + 0x36, 0xba, 0x81, 0x89, 0x76, 0xdd, 0xc0, 0x5c, 0xcf, 0x4a, 0xff, 0xd4, 0x4d, 0x71, 0x41, + 0x2a, 0x54, 0x79, 0x82, 0xb6, 0x13, 0x9a, 0xc8, 0x87, 0x08, 0x16, 0xc4, 0xbf, 0x46, 0xa9, + 0x34, 0x93, 0x48, 0xd2, + }; + + const std::string TESTALIAS = "LegacyKeystoreWifiTestAlias"; + + ASSERT_TRUE(LegacyKeystoreRemove(TESTALIAS, AID_WIFI)); + ASSERT_TRUE(LegacyKeystorePut(TESTALIAS, TESTBLOB_DER_3CERT, AID_WIFI)); + + IKeystore::KeystoreStatusCode statusCode; + std::vector<uint8_t> blob; + auto rc = wifiKeystoreHal->getBlob(TESTALIAS, + [&](IKeystore::KeystoreStatusCode status, + const ::android::hardware::hidl_vec<uint8_t>& value) { + statusCode = status; + blob = value; + }); + + ASSERT_TRUE(rc.isOk()) << "Description: " << rc.description(); + ASSERT_EQ(IKeystore::KeystoreStatusCode::SUCCESS, statusCode); + + std::string blob_str(reinterpret_cast<const char*>(blob.data()), + reinterpret_cast<const char*>(blob.data()) + blob.size()); + + // The output must include exactly three PEM certificate begin markers. + auto pos = blob_str.find("-----BEGIN CERTIFICATE-----", 0); + ASSERT_NE(pos, std::string::npos); + pos = blob_str.find("-----BEGIN CERTIFICATE-----", pos + 1); + ASSERT_NE(pos, std::string::npos); + pos = blob_str.find("-----BEGIN CERTIFICATE-----", pos + 1); + ASSERT_NE(pos, std::string::npos); + pos = blob_str.find("-----BEGIN CERTIFICATE-----", pos + 1); + ASSERT_EQ(pos, std::string::npos); + + ASSERT_TRUE(LegacyKeystoreRemove(TESTALIAS, AID_WIFI)); +} + +TEST(WifiKeystoreUtilsTest, ExtractPublicKeyHandlesDer) { + auto cert = extractPubKey(kDerTestCert); + ASSERT_FALSE(cert.empty()); +} + +TEST(WifiKeystoreUtilsTest, ExtractPublicKeyHandlesPemFallback) { + const std::vector<uint8_t> TESTBLOB(std::begin(kPemTestCert), std::end(kPemTestCert)); + auto cert = extractPubKey(TESTBLOB); + ASSERT_FALSE(cert.empty()); +} + } // namespace diff --git a/wifi/keystore/1.0/default/wifikeystorehal_utils.h b/wifi/keystore/1.0/default/wifikeystorehal_utils.h new file mode 100644 index 0000000..d7a790e --- /dev/null +++ b/wifi/keystore/1.0/default/wifikeystorehal_utils.h @@ -0,0 +1,51 @@ +#pragma once + +#include <android-base/logging.h> +#include <openssl/base.h> +#include <openssl/bio.h> +#include <openssl/pem.h> +#include <openssl/x509.h> +#include <vector> + +#define AT __func__ << ":" << __LINE__ << " " + +namespace { +// Helper method to extract public key from the certificate. +std::vector<uint8_t> 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 {}; + } + bssl::UniquePtr<BIO> pub_key_bio(BIO_new(BIO_s_mem())); + if (!pub_key_bio || i2d_PUBKEY_bio(pub_key_bio.get(), pub_key.get()) <= 0) { + LOG(ERROR) << AT << "Could not serialize public key."; + return {}; + } + const uint8_t* pub_key_bytes; + size_t pub_key_len; + if (!BIO_mem_contents(pub_key_bio.get(), &pub_key_bytes, &pub_key_len)) { + LOG(ERROR) << AT << "Could not get bytes from BIO."; + return {}; + } + + return {pub_key_bytes, pub_key_bytes + pub_key_len}; +} + +} // namespace
\ No newline at end of file diff --git a/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp b/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp index cbac948..3139d8e 100644 --- a/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp +++ b/wifi/keystore/1.0/vts/functional/VtsHalWifiKeystoreV1_0TargetTest.cpp @@ -376,9 +376,12 @@ TEST_P(WifiKeystoreHalTest, GetBlob_success) { IKeystore::KeystoreStatusCode statusCode; - auto callback = [&statusCode](IKeystore::KeystoreStatusCode status, - const ::android::hardware::hidl_vec<uint8_t>& /*value*/) { + std::string cert; + auto callback = [&statusCode, &cert](IKeystore::KeystoreStatusCode status, + const ::android::hardware::hidl_vec<uint8_t>& value) { statusCode = status; + cert = std::string(reinterpret_cast<const char*>(value.data()), + reinterpret_cast<const char*>(value.data()) + value.size()); return; }; @@ -389,6 +392,8 @@ TEST_P(WifiKeystoreHalTest, GetBlob_success) { keystore->getBlob(std::string("USRCERT_") + kTestKeyName, callback); EXPECT_EQ(IKeystore::KeystoreStatusCode::SUCCESS, statusCode); + // Must return PEM encoded certificates. + EXPECT_EQ(cert.rfind("-----BEGIN CERTIFICATE-----", 0), 0); result = deleteKey(kTestKeyName, true); EXPECT_EQ(result, true); |