Merge changes I48840207,Idc5de13c,I8f2b7ab3,I2460106c

* changes:
  Keymaster 4.1 VTS tests
  Update KM4 VTS tests to allow s/w implementation to pass.
  Remove service death test.
  Change finish input test to avoid large sizes.
This commit is contained in:
TreeHugger Robot
2020-01-21 20:47:04 +00:00
committed by Android (Google) Code Review
18 changed files with 1257 additions and 201 deletions

View File

@@ -321,19 +321,20 @@ ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc
LOG(ERROR) << AT << "Failed record parsing";
return ErrorCode::UNKNOWN_ERROR;
}
if (!record->tee_enforced) {
LOG(ERROR) << AT << "Failed hardware characteristic parsing";
KM_ROOT_OF_TRUST* root_of_trust = nullptr;
if (record->tee_enforced && record->tee_enforced->root_of_trust) {
root_of_trust = record->tee_enforced->root_of_trust;
} else if (record->software_enforced && record->software_enforced->root_of_trust) {
root_of_trust = record->software_enforced->root_of_trust;
} else {
LOG(ERROR) << AT << " Failed root of trust parsing";
return ErrorCode::INVALID_ARGUMENT;
}
if (!record->tee_enforced->root_of_trust) {
LOG(ERROR) << AT << "Failed root of trust parsing";
if (!root_of_trust->verified_boot_key) {
LOG(ERROR) << AT << " Failed verified boot key parsing";
return ErrorCode::INVALID_ARGUMENT;
}
if (!record->tee_enforced->root_of_trust->verified_boot_key) {
LOG(ERROR) << AT << "Failed verified boot key parsing";
return ErrorCode::INVALID_ARGUMENT;
}
KM_ROOT_OF_TRUST* root_of_trust = record->tee_enforced->root_of_trust;
auto& vb_key = root_of_trust->verified_boot_key;
verified_boot_key->resize(vb_key->length);
@@ -342,19 +343,19 @@ ErrorCode parse_root_of_trust(const uint8_t* asn1_key_desc, size_t asn1_key_desc
*verified_boot_state = static_cast<keymaster_verified_boot_t>(
ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
if (!verified_boot_state) {
LOG(ERROR) << AT << "Failed verified boot state parsing";
LOG(ERROR) << AT << " Failed verified boot state parsing";
return ErrorCode::INVALID_ARGUMENT;
}
*device_locked = root_of_trust->device_locked;
if (!device_locked) {
LOG(ERROR) << AT << "Failed device locked parsing";
LOG(ERROR) << AT << " Failed device locked parsing";
return ErrorCode::INVALID_ARGUMENT;
}
auto& vb_hash = root_of_trust->verified_boot_hash;
if (!vb_hash) {
LOG(ERROR) << AT << "Failed verified boot hash parsing";
LOG(ERROR) << AT << " Failed verified boot hash parsing";
return ErrorCode::INVALID_ARGUMENT;
}
verified_boot_hash->resize(vb_hash->length);

View File

@@ -25,7 +25,7 @@ namespace hardware {
namespace keymaster {
namespace V4_0 {
inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
if (a.tag != b.tag) return a.tag < b.tag;
int retval;
switch (typeFromTag(a.tag)) {
@@ -58,7 +58,7 @@ inline bool keyParamLess(const KeyParameter& a, const KeyParameter& b) {
return false;
}
inline bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
bool keyParamEqual(const KeyParameter& a, const KeyParameter& b) {
if (a.tag != b.tag) return false;
switch (typeFromTag(a.tag)) {

View File

@@ -355,95 +355,61 @@ inline NullOr<const typename TypedTag2ValueType<TypedTag<tag_type, tag>>::type&>
return accessTagValue(ttag, param);
}
inline bool operator<(const KeyParameter& a, const KeyParameter& b) {
if (a.tag != b.tag) return a.tag < b.tag;
int retval;
switch (typeFromTag(a.tag)) {
case TagType::INVALID:
case TagType::BOOL:
return false;
case TagType::ENUM:
case TagType::ENUM_REP:
case TagType::UINT:
case TagType::UINT_REP:
return a.f.integer < b.f.integer;
case TagType::ULONG:
case TagType::ULONG_REP:
return a.f.longInteger < b.f.longInteger;
case TagType::DATE:
return a.f.dateTime < b.f.dateTime;
case TagType::BIGNUM:
case TagType::BYTES:
// Handle the empty cases.
if (a.blob.size() == 0) return b.blob.size() != 0;
if (b.blob.size() == 0) return false;
retval = memcmp(&a.blob[0], &b.blob[0], std::min(a.blob.size(), b.blob.size()));
// if one is the prefix of the other the longer wins
if (retval == 0) return a.blob.size() < b.blob.size();
// Otherwise a is less if a is less.
else
return retval < 0;
}
return false;
}
inline bool operator==(const KeyParameter& a, const KeyParameter& b) {
if (a.tag != b.tag) {
return false;
}
if (a.tag != b.tag) return false;
switch (a.tag) {
/* Boolean tags */
case Tag::INVALID:
case Tag::CALLER_NONCE:
case Tag::INCLUDE_UNIQUE_ID:
case Tag::BOOTLOADER_ONLY:
case Tag::NO_AUTH_REQUIRED:
case Tag::ALLOW_WHILE_ON_BODY:
case Tag::UNLOCKED_DEVICE_REQUIRED:
case Tag::ROLLBACK_RESISTANCE:
case Tag::RESET_SINCE_ID_ROTATION:
case Tag::TRUSTED_CONFIRMATION_REQUIRED:
case Tag::TRUSTED_USER_PRESENCE_REQUIRED:
switch (typeFromTag(a.tag)) {
case TagType::INVALID:
case TagType::BOOL:
return true;
/* Integer tags */
case Tag::KEY_SIZE:
case Tag::MIN_MAC_LENGTH:
case Tag::MIN_SECONDS_BETWEEN_OPS:
case Tag::MAX_USES_PER_BOOT:
case Tag::OS_VERSION:
case Tag::OS_PATCHLEVEL:
case Tag::MAC_LENGTH:
case Tag::USER_ID:
case Tag::AUTH_TIMEOUT:
case Tag::VENDOR_PATCHLEVEL:
case Tag::BOOT_PATCHLEVEL:
case TagType::ENUM:
case TagType::ENUM_REP:
case TagType::UINT:
case TagType::UINT_REP:
return a.f.integer == b.f.integer;
/* Long integer tags */
case Tag::RSA_PUBLIC_EXPONENT:
case Tag::USER_SECURE_ID:
case TagType::ULONG:
case TagType::ULONG_REP:
return a.f.longInteger == b.f.longInteger;
/* Date-time tags */
case Tag::ACTIVE_DATETIME:
case Tag::ORIGINATION_EXPIRE_DATETIME:
case Tag::USAGE_EXPIRE_DATETIME:
case Tag::CREATION_DATETIME:
case TagType::DATE:
return a.f.dateTime == b.f.dateTime;
/* Bytes tags */
case Tag::APPLICATION_ID:
case Tag::APPLICATION_DATA:
case Tag::ROOT_OF_TRUST:
case Tag::UNIQUE_ID:
case Tag::ATTESTATION_CHALLENGE:
case Tag::ATTESTATION_APPLICATION_ID:
case Tag::ATTESTATION_ID_BRAND:
case Tag::ATTESTATION_ID_DEVICE:
case Tag::ATTESTATION_ID_PRODUCT:
case Tag::ATTESTATION_ID_SERIAL:
case Tag::ATTESTATION_ID_IMEI:
case Tag::ATTESTATION_ID_MEID:
case Tag::ATTESTATION_ID_MANUFACTURER:
case Tag::ATTESTATION_ID_MODEL:
case Tag::ASSOCIATED_DATA:
case Tag::CONFIRMATION_TOKEN:
case Tag::NONCE:
return a.blob == b.blob;
/* Enum tags */
case Tag::PURPOSE:
return a.f.purpose == b.f.purpose;
case Tag::ALGORITHM:
return a.f.algorithm == b.f.algorithm;
case Tag::BLOCK_MODE:
return a.f.blockMode == b.f.blockMode;
case Tag::DIGEST:
return a.f.digest == b.f.digest;
case Tag::PADDING:
return a.f.paddingMode == b.f.paddingMode;
case Tag::EC_CURVE:
return a.f.ecCurve == b.f.ecCurve;
case Tag::BLOB_USAGE_REQUIREMENTS:
return a.f.keyBlobUsageRequirements == b.f.keyBlobUsageRequirements;
case Tag::USER_AUTH_TYPE:
return a.f.integer == b.f.integer;
case Tag::ORIGIN:
return a.f.origin == b.f.origin;
case Tag::HARDWARE_TYPE:
return a.f.hardwareType == b.f.hardwareType;
case TagType::BIGNUM:
case TagType::BYTES:
if (a.blob.size() != b.blob.size()) return false;
return a.blob.size() == 0 || memcmp(&a.blob[0], &b.blob[0], a.blob.size()) == 0;
}
return false;
}

View File

@@ -18,6 +18,8 @@
#define HARDWARE_INTERFACES_KEYMASTER_4_0_SUPPORT_OPENSSL_UTILS_H_
#include <android/hardware/keymaster/4.0/types.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
template <typename T, void (*F)(T*)>
struct UniquePtrDeleter {

View File

@@ -19,7 +19,6 @@ cc_test {
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"HmacKeySharingTest.cpp",
"KeymasterHidlTest.cpp",
"VerificationTokenTest.cpp",
"keymaster_hidl_hal_test.cpp",
],
@@ -27,9 +26,25 @@ cc_test {
"android.hardware.keymaster@4.0",
"libcrypto_static",
"libkeymaster4support",
"libkeymaster4vtstest",
],
test_suites: [
"general-tests",
"vts-core",
],
}
cc_test_library {
name: "libkeymaster4vtstest",
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"KeymasterHidlTest.cpp",
],
export_include_dirs: [
".",
],
static_libs: [
"android.hardware.keymaster@4.0",
"libkeymaster4support",
],
}

View File

@@ -44,10 +44,9 @@ namespace test {
using namespace std::literals::chrono_literals;
void KeymasterHidlTest::InitializeKeymaster() {
keymaster_ = IKeymasterDevice::getService(GetParam());
ASSERT_NE(keymaster_, nullptr);
void KeymasterHidlTest::InitializeKeymaster(sp<IKeymasterDevice> keymaster) {
ASSERT_NE(keymaster, nullptr);
keymaster_ = keymaster;
ASSERT_TRUE(keymaster_
->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
const hidl_string& author) {
@@ -56,15 +55,15 @@ void KeymasterHidlTest::InitializeKeymaster() {
author_ = author;
})
.isOk());
}
void KeymasterHidlTest::SetUp() {
InitializeKeymaster();
os_version_ = support::getOsVersion();
os_patch_level_ = support::getOsPatchlevel();
}
void KeymasterHidlTest::SetUp() {
InitializeKeymaster(IKeymasterDevice::getService(GetParam()));
}
ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
KeyCharacteristics* key_characteristics) {
EXPECT_NE(key_blob, nullptr) << "Key blob pointer must not be null. Test bug";
@@ -127,7 +126,7 @@ ErrorCode KeymasterHidlTest::ImportWrappedKey(string wrapped_key, string wrappin
string masking_key,
const AuthorizationSet& unwrapping_params) {
ErrorCode error;
ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key);
EXPECT_EQ(ErrorCode::OK, ImportKey(wrapping_key_desc, KeyFormat::PKCS8, wrapping_key));
EXPECT_TRUE(keymaster_
->importWrappedKey(HidlBuf(wrapped_key), key_blob_, HidlBuf(masking_key),
unwrapping_params.hidl_data(), 0 /* passwordSid */,
@@ -196,7 +195,9 @@ void KeymasterHidlTest::CheckGetCharacteristics(const HidlBuf& key_blob, const H
HidlBuf empty_buf = {};
EXPECT_EQ(ErrorCode::OK,
GetCharacteristics(key_blob, client_id, app_data, key_characteristics));
EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
if (SecLevel() != SecurityLevel::SOFTWARE) {
EXPECT_GT(key_characteristics->hardwareEnforced.size(), 0);
}
EXPECT_GT(key_characteristics->softwareEnforced.size(), 0);
EXPECT_EQ(ErrorCode::INVALID_KEY_BLOB,
@@ -636,23 +637,25 @@ std::vector<uint32_t> KeymasterHidlTest::ValidKeySizes(Algorithm algorithm) {
switch (algorithm) {
case Algorithm::RSA:
switch (SecLevel()) {
case SecurityLevel::SOFTWARE:
case SecurityLevel::TRUSTED_ENVIRONMENT:
return {2048, 3072, 4096};
case SecurityLevel::STRONGBOX:
return {2048};
default:
CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
break;
}
break;
case Algorithm::EC:
switch (SecLevel()) {
case SecurityLevel::SOFTWARE:
case SecurityLevel::TRUSTED_ENVIRONMENT:
return {224, 256, 384, 521};
case SecurityLevel::STRONGBOX:
return {256};
default:
CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
break;
}
break;
@@ -667,25 +670,27 @@ std::vector<uint32_t> KeymasterHidlTest::ValidKeySizes(Algorithm algorithm) {
return retval;
}
default:
CHECK(false) << "Invalid Algorithm: " << algorithm;
ADD_FAILURE() << "Invalid Algorithm: " << algorithm;
return {};
}
CHECK(false) << "Should be impossible to get here";
ADD_FAILURE() << "Should be impossible to get here";
return {};
}
std::vector<uint32_t> KeymasterHidlTest::InvalidKeySizes(Algorithm algorithm) {
if (SecLevel() == SecurityLevel::TRUSTED_ENVIRONMENT) return {};
CHECK(SecLevel() == SecurityLevel::STRONGBOX);
switch (algorithm) {
case Algorithm::RSA:
return {3072, 4096};
case Algorithm::EC:
return {224, 384, 521};
case Algorithm::AES:
return {192};
default:
return {};
if (SecLevel() == SecurityLevel::STRONGBOX) {
switch (algorithm) {
case Algorithm::RSA:
return {3072, 4096};
case Algorithm::EC:
return {224, 384, 521};
case Algorithm::AES:
return {192};
default:
return {};
}
}
return {};
}
std::vector<EcCurve> KeymasterHidlTest::ValidCurves() {
@@ -704,6 +709,7 @@ std::vector<EcCurve> KeymasterHidlTest::InvalidCurves() {
std::vector<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
switch (SecLevel()) {
case SecurityLevel::SOFTWARE:
case SecurityLevel::TRUSTED_ENVIRONMENT:
if (withNone) {
if (withMD5)
@@ -729,10 +735,10 @@ std::vector<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5)
return {Digest::SHA_2_256};
break;
default:
CHECK(false) << "Invalid security level " << uint32_t(SecLevel());
ADD_FAILURE() << "Invalid security level " << uint32_t(SecLevel());
break;
}
CHECK(false) << "Should be impossible to get here";
ADD_FAILURE() << "Should be impossible to get here";
return {};
}

View File

@@ -38,12 +38,14 @@ using hidl::base::V1_0::DebugInfo;
using ::std::string;
class HidlBuf : public hidl_vec<uint8_t> {
typedef hidl_vec<uint8_t> super;
using super = hidl_vec<uint8_t>;
public:
HidlBuf() {}
HidlBuf(const super& other) : super(other) {}
HidlBuf(super&& other) : super(std::move(other)) {}
HidlBuf(super&& other) : super(std::move(other)) { other = {}; }
HidlBuf(const HidlBuf& other) : super(other) {}
HidlBuf(HidlBuf&& other) : super(std::move(other)) { other = HidlBuf(); }
explicit HidlBuf(const std::string& other) : HidlBuf() { *this = other; }
HidlBuf& operator=(const super& other) {
@@ -53,6 +55,18 @@ class HidlBuf : public hidl_vec<uint8_t> {
HidlBuf& operator=(super&& other) {
super::operator=(std::move(other));
other = {};
return *this;
}
HidlBuf& operator=(const HidlBuf& other) {
super::operator=(other);
return *this;
}
HidlBuf& operator=(HidlBuf&& other) {
super::operator=(std::move(other));
other.super::operator=({});
return *this;
}
@@ -77,7 +91,7 @@ class KeymasterHidlTest : public ::testing::TestWithParam<std::string> {
AbortIfNeeded();
}
void InitializeKeymaster();
void InitializeKeymaster(sp<IKeymasterDevice> keymaster);
IKeymasterDevice& keymaster() { return *keymaster_; }
uint32_t os_version() { return os_version_; }
uint32_t os_patch_level() { return os_patch_level_; }
@@ -204,6 +218,11 @@ class KeymasterHidlTest : public ::testing::TestWithParam<std::string> {
KeyCharacteristics key_characteristics_;
OperationHandle op_handle_ = kOpHandleSentinel;
static std::vector<std::string> build_params() {
auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
return params;
}
private:
sp<IKeymasterDevice> keymaster_;
uint32_t os_version_;
@@ -214,10 +233,9 @@ class KeymasterHidlTest : public ::testing::TestWithParam<std::string> {
hidl_string author_;
};
#define INSTANTIATE_KEYMASTER_HIDL_TEST(name) \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
testing::ValuesIn(android::hardware::getAllHalInstanceNames( \
IKeymasterDevice::descriptor)), \
#define INSTANTIATE_KEYMASTER_HIDL_TEST(name) \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
testing::ValuesIn(KeymasterHidlTest::build_params()), \
android::hardware::PrintInstanceNameToString)
} // namespace test

View File

@@ -352,11 +352,11 @@ bool verify_attestation_record(const string& challenge, const string& app_id,
EXPECT_EQ(ErrorCode::OK, error);
if (error != ErrorCode::OK) return false;
EXPECT_TRUE(att_attestation_version == 3);
EXPECT_GE(att_attestation_version, 3U);
expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID, HidlBuf(app_id));
EXPECT_EQ(att_keymaster_version, 4U);
EXPECT_GE(att_keymaster_version, 4U);
EXPECT_EQ(security_level, att_keymaster_security_level);
EXPECT_EQ(security_level, att_attestation_security_level);
@@ -397,10 +397,16 @@ bool verify_attestation_record(const string& challenge, const string& app_id,
// true. A provided boolean tag that can be pulled back out of the certificate indicates correct
// encoding. No need to check if it's in both lists, since the AuthorizationSet compare below
// will handle mismatches of tags.
EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
if (security_level == SecurityLevel::SOFTWARE) {
EXPECT_TRUE(expected_sw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
} else {
EXPECT_TRUE(expected_hw_enforced.Contains(TAG_NO_AUTH_REQUIRED));
}
// Alternatively this checks the opposite - a false boolean tag (one that isn't provided in
// the authorization list during key generation) isn't being attested to in the certificate.
EXPECT_FALSE(expected_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
EXPECT_FALSE(att_sw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
EXPECT_FALSE(expected_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
EXPECT_FALSE(att_hw_enforced.Contains(TAG_TRUSTED_USER_PRESENCE_REQUIRED));
@@ -461,10 +467,10 @@ bool verify_attestation_record(const string& challenge, const string& app_id,
verified_boot_key.size()));
} else if (!strcmp(property_value, "red")) {
EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_FAILED);
EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
verified_boot_key.size()));
} else {
EXPECT_TRUE(false);
EXPECT_EQ(verified_boot_state, KM_VERIFIED_BOOT_UNVERIFIED);
EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
verified_boot_key.size()));
}
att_sw_enforced.Sort();
@@ -4557,53 +4563,14 @@ TEST_P(ClearOperationsTest, TooManyOperations) {
AbortIfNeeded();
}
/*
* ClearSlotsTest.ServiceDeath
*
* Verifies that the service is restarted after death and the ongoing
* operations are cleared.
*/
TEST_P(ClearOperationsTest, ServiceDeath) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaEncryptionKey(2048, 65537)
.Padding(PaddingMode::NONE)));
auto params = AuthorizationSetBuilder().Padding(PaddingMode::NONE);
int max_operations = SecLevel() == SecurityLevel::STRONGBOX ? 4 : 16;
OperationHandle op_handles[max_operations];
AuthorizationSet out_params;
for(int i=0; i<max_operations; i++) {
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
}
EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
DebugInfo debug_info;
GetDebugInfo(&debug_info);
kill(debug_info.pid, SIGKILL);
// wait 1 second for keymaster to restart
sleep(1);
InitializeKeymaster();
for(int i=0; i<max_operations; i++) {
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &(op_handles[i])));
}
EXPECT_EQ(ErrorCode::TOO_MANY_OPERATIONS,
Begin(KeyPurpose::ENCRYPT, key_blob_, params, &out_params, &op_handle_));
for(int i=0; i<max_operations; i++) {
EXPECT_EQ(ErrorCode::OK, Abort(op_handles[i]));
}
}
INSTANTIATE_KEYMASTER_HIDL_TEST(ClearOperationsTest);
typedef KeymasterHidlTest TransportLimitTest;
/*
* TransportLimitTest.LargeFinishInput
* TransportLimitTest.FinishInput
*
* Verifies that passing large input data to finish either succeeds or fails as expected.
* Verifies that passing input data to finish succeeds as expected.
*/
TEST_P(TransportLimitTest, LargeFinishInput) {
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
@@ -4612,7 +4579,7 @@ TEST_P(TransportLimitTest, LargeFinishInput) {
.BlockMode(BlockMode::ECB)
.Padding(PaddingMode::NONE)));
for (int msg_size = 10 /*1KB*/; msg_size <= 17 /*128KB*/; msg_size++) {
for (int msg_size = 8 /* 256 bytes */; msg_size <= 11 /* 2 KiB */; msg_size++) {
auto cipher_params =
AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE);
@@ -4623,31 +4590,19 @@ TEST_P(TransportLimitTest, LargeFinishInput) {
string encrypted_message;
auto rc = Finish(plain_message, &encrypted_message);
if (rc == ErrorCode::OK) {
EXPECT_EQ(plain_message.size(), encrypted_message.size())
<< "Encrypt finish returned OK, but did not consume all of the given input";
} else {
EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, rc)
<< "Encrypt finish failed in an unexpected way when given a large input";
continue;
}
EXPECT_EQ(ErrorCode::OK, rc);
EXPECT_EQ(plain_message.size(), encrypted_message.size())
<< "Encrypt finish returned OK, but did not consume all of the given input";
cipher_params.push_back(out_params);
EXPECT_EQ(ErrorCode::OK, Begin(KeyPurpose::DECRYPT, cipher_params));
string decrypted_message;
rc = Finish(encrypted_message, &decrypted_message);
if (rc == ErrorCode::OK) {
EXPECT_EQ(plain_message.size(), decrypted_message.size())
<< "Decrypt finish returned OK, did not consume all of the given input";
} else {
EXPECT_EQ(ErrorCode::INVALID_INPUT_LENGTH, rc)
<< "Encrypt finish failed in an unexpected way when given a large input";
}
EXPECT_EQ(ErrorCode::OK, rc);
EXPECT_EQ(plain_message.size(), decrypted_message.size())
<< "Decrypt finish returned OK, did not consume all of the given input";
}
CheckedDeleteKey();
}
INSTANTIATE_KEYMASTER_HIDL_TEST(TransportLimitTest);

View File

@@ -22,11 +22,17 @@ cc_library {
"-Wextra",
"-Werror",
],
srcs: [
"attestation_record.cpp",
],
export_include_dirs: ["include"],
shared_libs: [
"android.hardware.keymaster@3.0",
"android.hardware.keymaster@4.0",
"android.hardware.keymaster@4.1",
"libbase",
"libcrypto",
"libhidlbase",
"libkeymaster4support",
]
],
}

View File

@@ -0,0 +1,387 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <keymasterV4_1/attestation_record.h>
#include <android-base/logging.h>
#include <assert.h>
#include <openssl/asn1t.h>
#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/x509.h>
#include <keymasterV4_0/authorization_set.h>
#include <keymasterV4_0/openssl_utils.h>
#define AT __FILE__ ":" << __LINE__
/*
* NOTE: The contents of this file are *extremely* similar to the contents of the V4_0 copy of the
* same support file. Unfortunately, small changes in the scheme mean that the schema types have to
* be distinct, which drives almost everything else to be different as well. In the next version we
* plan to abandon not just this openssl mechanism for parsing ASN.1, but ASN.1 entirely, so
* eventually all of this duplication can be removed.
*/
namespace android {
namespace hardware {
namespace keymaster {
namespace V4_1 {
struct stack_st_ASN1_TYPE_Delete {
void operator()(stack_st_ASN1_TYPE* p) { sk_ASN1_TYPE_free(p); }
};
struct ASN1_STRING_Delete {
void operator()(ASN1_STRING* p) { ASN1_STRING_free(p); }
};
struct ASN1_TYPE_Delete {
void operator()(ASN1_TYPE* p) { ASN1_TYPE_free(p); }
};
#define ASN1_INTEGER_SET STACK_OF(ASN1_INTEGER)
typedef struct km_root_of_trust {
ASN1_OCTET_STRING* verified_boot_key;
ASN1_BOOLEAN* device_locked;
ASN1_ENUMERATED* verified_boot_state;
ASN1_OCTET_STRING* verified_boot_hash;
} KM_ROOT_OF_TRUST;
ASN1_SEQUENCE(KM_ROOT_OF_TRUST) = {
ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_key, ASN1_OCTET_STRING),
ASN1_SIMPLE(KM_ROOT_OF_TRUST, device_locked, ASN1_BOOLEAN),
ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_state, ASN1_ENUMERATED),
ASN1_SIMPLE(KM_ROOT_OF_TRUST, verified_boot_hash, ASN1_OCTET_STRING),
} ASN1_SEQUENCE_END(KM_ROOT_OF_TRUST);
IMPLEMENT_ASN1_FUNCTIONS(KM_ROOT_OF_TRUST);
typedef struct km_auth_list {
ASN1_INTEGER_SET* purpose;
ASN1_INTEGER* algorithm;
ASN1_INTEGER* key_size;
ASN1_INTEGER_SET* digest;
ASN1_INTEGER_SET* padding;
ASN1_INTEGER* ec_curve;
ASN1_INTEGER* rsa_public_exponent;
ASN1_INTEGER* active_date_time;
ASN1_INTEGER* origination_expire_date_time;
ASN1_INTEGER* usage_expire_date_time;
ASN1_NULL* no_auth_required;
ASN1_INTEGER* user_auth_type;
ASN1_INTEGER* auth_timeout;
ASN1_NULL* allow_while_on_body;
ASN1_NULL* all_applications;
ASN1_OCTET_STRING* application_id;
ASN1_INTEGER* creation_date_time;
ASN1_INTEGER* origin;
ASN1_NULL* rollback_resistance;
KM_ROOT_OF_TRUST* root_of_trust;
ASN1_INTEGER* os_version;
ASN1_INTEGER* os_patchlevel;
ASN1_OCTET_STRING* attestation_application_id;
ASN1_NULL* trusted_user_presence_required;
ASN1_NULL* trusted_confirmation_required;
ASN1_NULL* unlocked_device_required;
ASN1_INTEGER* vendor_patchlevel;
ASN1_INTEGER* boot_patchlevel;
ASN1_NULL* early_boot_only;
ASN1_NULL* device_unique_attestation;
} KM_AUTH_LIST;
ASN1_SEQUENCE(KM_AUTH_LIST) = {
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, purpose, ASN1_INTEGER, TAG_PURPOSE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, algorithm, ASN1_INTEGER, TAG_ALGORITHM.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, key_size, ASN1_INTEGER, TAG_KEY_SIZE.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, digest, ASN1_INTEGER, TAG_DIGEST.maskedTag()),
ASN1_EXP_SET_OF_OPT(KM_AUTH_LIST, padding, ASN1_INTEGER, TAG_PADDING.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, ec_curve, ASN1_INTEGER, TAG_EC_CURVE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rsa_public_exponent, ASN1_INTEGER,
TAG_RSA_PUBLIC_EXPONENT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, rollback_resistance, ASN1_NULL,
TAG_ROLLBACK_RESISTANCE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, active_date_time, ASN1_INTEGER, TAG_ACTIVE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origination_expire_date_time, ASN1_INTEGER,
TAG_ORIGINATION_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, usage_expire_date_time, ASN1_INTEGER,
TAG_USAGE_EXPIRE_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, no_auth_required, ASN1_NULL, TAG_NO_AUTH_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, user_auth_type, ASN1_INTEGER, TAG_USER_AUTH_TYPE.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, auth_timeout, ASN1_INTEGER, TAG_AUTH_TIMEOUT.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, allow_while_on_body, ASN1_NULL,
TAG_ALLOW_WHILE_ON_BODY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, trusted_user_presence_required, ASN1_NULL,
TAG_TRUSTED_USER_PRESENCE_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, trusted_confirmation_required, ASN1_NULL,
TAG_TRUSTED_CONFIRMATION_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, unlocked_device_required, ASN1_NULL,
TAG_UNLOCKED_DEVICE_REQUIRED.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, creation_date_time, ASN1_INTEGER,
TAG_CREATION_DATETIME.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, origin, ASN1_INTEGER, TAG_ORIGIN.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, root_of_trust, KM_ROOT_OF_TRUST, TAG_ROOT_OF_TRUST.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_version, ASN1_INTEGER, TAG_OS_VERSION.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, os_patchlevel, ASN1_INTEGER, TAG_OS_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, vendor_patchlevel, ASN1_INTEGER,
TAG_VENDOR_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, boot_patchlevel, ASN1_INTEGER, TAG_BOOT_PATCHLEVEL.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, attestation_application_id, ASN1_OCTET_STRING,
TAG_ATTESTATION_APPLICATION_ID.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, early_boot_only, ASN1_NULL, TAG_EARLY_BOOT_ONLY.maskedTag()),
ASN1_EXP_OPT(KM_AUTH_LIST, device_unique_attestation, ASN1_NULL,
TAG_DEVICE_UNIQUE_ATTESTATION.maskedTag()),
} ASN1_SEQUENCE_END(KM_AUTH_LIST);
IMPLEMENT_ASN1_FUNCTIONS(KM_AUTH_LIST);
typedef struct km_key_description {
ASN1_INTEGER* attestation_version;
ASN1_ENUMERATED* attestation_security_level;
ASN1_INTEGER* keymaster_version;
ASN1_ENUMERATED* keymaster_security_level;
ASN1_OCTET_STRING* attestation_challenge;
KM_AUTH_LIST* software_enforced;
KM_AUTH_LIST* tee_enforced;
ASN1_INTEGER* unique_id;
} KM_KEY_DESCRIPTION;
ASN1_SEQUENCE(KM_KEY_DESCRIPTION) = {
ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_version, ASN1_INTEGER),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_security_level, ASN1_ENUMERATED),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_version, ASN1_INTEGER),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, keymaster_security_level, ASN1_ENUMERATED),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, attestation_challenge, ASN1_OCTET_STRING),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, unique_id, ASN1_OCTET_STRING),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, software_enforced, KM_AUTH_LIST),
ASN1_SIMPLE(KM_KEY_DESCRIPTION, tee_enforced, KM_AUTH_LIST),
} ASN1_SEQUENCE_END(KM_KEY_DESCRIPTION);
IMPLEMENT_ASN1_FUNCTIONS(KM_KEY_DESCRIPTION);
template <V4_0::Tag tag>
void copyAuthTag(const stack_st_ASN1_INTEGER* stack, TypedTag<TagType::ENUM_REP, tag> ttag,
AuthorizationSet* auth_list) {
typedef typename V4_0::TypedTag2ValueType<decltype(ttag)>::type ValueT;
for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) {
auth_list->push_back(
ttag, static_cast<ValueT>(ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i))));
}
}
template <V4_0::Tag tag>
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ENUM, tag> ttag,
AuthorizationSet* auth_list) {
typedef typename V4_0::TypedTag2ValueType<decltype(ttag)>::type ValueT;
if (!asn1_int) return;
auth_list->push_back(ttag, static_cast<ValueT>(ASN1_INTEGER_get(asn1_int)));
}
template <V4_0::Tag tag>
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::UINT, tag> ttag,
AuthorizationSet* auth_list) {
if (!asn1_int) return;
auth_list->push_back(ttag, ASN1_INTEGER_get(asn1_int));
}
BIGNUM* construct_uint_max() {
BIGNUM* value = BN_new();
BIGNUM_Ptr one(BN_new());
BN_one(one.get());
BN_lshift(value, one.get(), 32);
return value;
}
uint64_t BignumToUint64(BIGNUM* num) {
static_assert((sizeof(BN_ULONG) == sizeof(uint32_t)) || (sizeof(BN_ULONG) == sizeof(uint64_t)),
"This implementation only supports 32 and 64-bit BN_ULONG");
if (sizeof(BN_ULONG) == sizeof(uint32_t)) {
BIGNUM_Ptr uint_max(construct_uint_max());
BIGNUM_Ptr hi(BN_new()), lo(BN_new());
BN_CTX_Ptr ctx(BN_CTX_new());
BN_div(hi.get(), lo.get(), num, uint_max.get(), ctx.get());
return static_cast<uint64_t>(BN_get_word(hi.get())) << 32 | BN_get_word(lo.get());
} else if (sizeof(BN_ULONG) == sizeof(uint64_t)) {
return BN_get_word(num);
} else {
return 0;
}
}
template <V4_0::Tag tag>
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::ULONG, tag> ttag,
AuthorizationSet* auth_list) {
if (!asn1_int) return;
BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
auth_list->push_back(ttag, BignumToUint64(num.get()));
}
template <V4_0::Tag tag>
void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag<TagType::DATE, tag> ttag,
AuthorizationSet* auth_list) {
if (!asn1_int) return;
BIGNUM_Ptr num(ASN1_INTEGER_to_BN(asn1_int, nullptr));
auth_list->push_back(ttag, BignumToUint64(num.get()));
}
template <V4_0::Tag tag>
void copyAuthTag(const ASN1_NULL* asn1_null, TypedTag<TagType::BOOL, tag> ttag,
AuthorizationSet* auth_list) {
if (!asn1_null) return;
auth_list->push_back(ttag);
}
template <V4_0::Tag tag>
void copyAuthTag(const ASN1_OCTET_STRING* asn1_string, TypedTag<TagType::BYTES, tag> ttag,
AuthorizationSet* auth_list) {
if (!asn1_string) return;
hidl_vec<uint8_t> buf;
buf.setToExternal(asn1_string->data, asn1_string->length);
auth_list->push_back(ttag, buf);
}
// Extract the values from the specified ASN.1 record and place them in auth_list.
static ErrorCode extract_auth_list(const KM_AUTH_LIST* record, AuthorizationSet* auth_list) {
if (!record) return ErrorCode::OK;
copyAuthTag(record->active_date_time, TAG_ACTIVE_DATETIME, auth_list);
copyAuthTag(record->algorithm, TAG_ALGORITHM, auth_list);
copyAuthTag(record->application_id, TAG_APPLICATION_ID, auth_list);
copyAuthTag(record->auth_timeout, TAG_AUTH_TIMEOUT, auth_list);
copyAuthTag(record->creation_date_time, TAG_CREATION_DATETIME, auth_list);
copyAuthTag(record->digest, TAG_DIGEST, auth_list);
copyAuthTag(record->ec_curve, TAG_EC_CURVE, auth_list);
copyAuthTag(record->key_size, TAG_KEY_SIZE, auth_list);
copyAuthTag(record->no_auth_required, TAG_NO_AUTH_REQUIRED, auth_list);
copyAuthTag(record->origin, TAG_ORIGIN, auth_list);
copyAuthTag(record->origination_expire_date_time, TAG_ORIGINATION_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->os_patchlevel, TAG_OS_PATCHLEVEL, auth_list);
copyAuthTag(record->os_version, TAG_OS_VERSION, auth_list);
copyAuthTag(record->padding, TAG_PADDING, auth_list);
copyAuthTag(record->purpose, TAG_PURPOSE, auth_list);
copyAuthTag(record->rollback_resistance, TAG_ROLLBACK_RESISTANCE, auth_list);
copyAuthTag(record->rsa_public_exponent, TAG_RSA_PUBLIC_EXPONENT, auth_list);
copyAuthTag(record->usage_expire_date_time, TAG_USAGE_EXPIRE_DATETIME, auth_list);
copyAuthTag(record->user_auth_type, TAG_USER_AUTH_TYPE, auth_list);
copyAuthTag(record->attestation_application_id, TAG_ATTESTATION_APPLICATION_ID, auth_list);
copyAuthTag(record->vendor_patchlevel, TAG_VENDOR_PATCHLEVEL, auth_list);
copyAuthTag(record->boot_patchlevel, TAG_BOOT_PATCHLEVEL, auth_list);
copyAuthTag(record->trusted_user_presence_required, TAG_TRUSTED_USER_PRESENCE_REQUIRED,
auth_list);
copyAuthTag(record->trusted_confirmation_required, TAG_TRUSTED_CONFIRMATION_REQUIRED,
auth_list);
copyAuthTag(record->unlocked_device_required, TAG_UNLOCKED_DEVICE_REQUIRED, auth_list);
copyAuthTag(record->early_boot_only, TAG_EARLY_BOOT_ONLY, auth_list);
copyAuthTag(record->device_unique_attestation, TAG_DEVICE_UNIQUE_ATTESTATION, auth_list);
return ErrorCode::OK;
}
MAKE_OPENSSL_PTR_TYPE(KM_KEY_DESCRIPTION)
// Parse the DER-encoded attestation record, placing the results in keymaster_version,
// attestation_challenge, software_enforced, tee_enforced and unique_id.
std::tuple<ErrorCode, AttestationRecord> parse_attestation_record(const hidl_vec<uint8_t>& cert) {
const uint8_t* p = cert.data();
X509_Ptr x509(d2i_X509(nullptr, &p, cert.size()));
ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
if (!oid.get()) {
LOG(ERROR) << "Error parsing OID";
return {ErrorCode::UNKNOWN_ERROR, {}};
}
int location = X509_get_ext_by_OBJ(x509.get(), oid.get(), -1 /* search from beginning */);
if (location == -1) {
LOG(ERROR) << "Attestation extension not found in certificate";
return {ErrorCode::UNKNOWN_ERROR, {}};
}
X509_EXTENSION* attest_rec_ext = X509_get_ext(x509.get(), location);
if (!attest_rec_ext) {
LOG(ERROR) << "Found extension but couldn't retrieve it. Probably BoringSSL bug.";
return {ErrorCode::UNKNOWN_ERROR, {}};
}
ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
if (!attest_rec_ext) {
LOG(ERROR) << "Attestation extension contained no data";
return {ErrorCode::UNKNOWN_ERROR, {}};
}
p = attest_rec->data;
KM_KEY_DESCRIPTION_Ptr record(d2i_KM_KEY_DESCRIPTION(nullptr, &p, attest_rec->length));
if (!record.get()) return {ErrorCode::UNKNOWN_ERROR, {}};
AttestationRecord result;
result.attestation_version = ASN1_INTEGER_get(record->attestation_version);
result.attestation_security_level =
static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->attestation_security_level));
result.keymaster_version = ASN1_INTEGER_get(record->keymaster_version);
result.keymaster_security_level =
static_cast<SecurityLevel>(ASN1_ENUMERATED_get(record->keymaster_security_level));
auto& chall = record->attestation_challenge;
result.attestation_challenge.resize(chall->length);
memcpy(result.attestation_challenge.data(), chall->data, chall->length);
auto& uid = record->unique_id;
result.unique_id.resize(uid->length);
memcpy(result.unique_id.data(), uid->data, uid->length);
ErrorCode error = extract_auth_list(record->software_enforced, &result.software_enforced);
if (error != ErrorCode::OK) return {error, {}};
error = extract_auth_list(record->tee_enforced, &result.hardware_enforced);
if (error != ErrorCode::OK) return {error, {}};
KM_ROOT_OF_TRUST* root_of_trust = nullptr;
if (record->tee_enforced && record->tee_enforced->root_of_trust) {
root_of_trust = record->tee_enforced->root_of_trust;
} else if (record->software_enforced && record->software_enforced->root_of_trust) {
root_of_trust = record->software_enforced->root_of_trust;
} else {
LOG(ERROR) << AT << " Failed root of trust parsing";
return {ErrorCode::INVALID_ARGUMENT, {}};
}
if (!root_of_trust->verified_boot_key) {
LOG(ERROR) << AT << " Failed verified boot key parsing";
return {ErrorCode::INVALID_ARGUMENT, {}};
}
RootOfTrust& rot = result.root_of_trust;
auto& vb_key = root_of_trust->verified_boot_key;
rot.verified_boot_key.resize(vb_key->length);
memcpy(rot.verified_boot_key.data(), vb_key->data, vb_key->length);
rot.verified_boot_state = static_cast<keymaster_verified_boot_t>(
ASN1_ENUMERATED_get(root_of_trust->verified_boot_state));
rot.device_locked = root_of_trust->device_locked;
auto& vb_hash = root_of_trust->verified_boot_hash;
if (!vb_hash) {
LOG(ERROR) << AT << " Failed verified boot hash parsing";
return {ErrorCode::INVALID_ARGUMENT, {}};
}
rot.verified_boot_hash.resize(vb_hash->length);
memcpy(rot.verified_boot_hash.data(), vb_hash->data, vb_hash->length);
return {ErrorCode::OK, result};
}
} // namespace V4_1
} // namespace keymaster
} // namespace hardware
} // namespace android

View File

@@ -0,0 +1,57 @@
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
#include <keymasterV4_0/attestation_record.h>
#include <keymasterV4_0/openssl_utils.h>
#include <keymasterV4_1/authorization_set.h>
namespace android {
namespace hardware {
namespace keymaster {
namespace V4_1 {
using V4_0::kAttestionRecordOid;
using V4_0::keymaster_verified_boot_t;
struct RootOfTrust {
SecurityLevel security_level;
hidl_vec<uint8_t> verified_boot_key;
hidl_vec<uint8_t> verified_boot_hash;
keymaster_verified_boot_t verified_boot_state;
bool device_locked;
};
struct AttestationRecord {
RootOfTrust root_of_trust;
uint32_t attestation_version;
SecurityLevel attestation_security_level;
uint32_t keymaster_version;
SecurityLevel keymaster_security_level;
hidl_vec<uint8_t> attestation_challenge;
AuthorizationSet software_enforced;
AuthorizationSet hardware_enforced;
hidl_vec<uint8_t> unique_id;
};
std::tuple<ErrorCode, AttestationRecord> parse_attestation_record(const hidl_vec<uint8_t>& cert);
} // namespace V4_1
} // namespace keymaster
} // namespace hardware
} // namespace android

View File

@@ -26,10 +26,13 @@ namespace android::hardware::keymaster::V4_1 {
using V4_0::BlockMode;
using V4_0::Digest;
using V4_0::EcCurve;
using V4_0::ErrorCode;
using V4_0::HardwareAuthToken;
using V4_0::KeyCharacteristics;
using V4_0::KeyOrigin;
using V4_0::KeyParameter;
using V4_0::KeyPurpose;
using V4_0::PaddingMode;
using V4_0::SecurityLevel;
using V4_0::TagType;
using V4_0::VerificationToken;

View File

@@ -19,12 +19,24 @@ cc_test {
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"EarlyBootKeyTest.cpp",
"DeviceUniqueAttestationTest.cpp",
"Keymaster4_1HidlTest.cpp",
"UnlockedDeviceRequiredTest.cpp",
],
static_libs: [
"android.hardware.keymaster@4.0",
"android.hardware.keymaster@4.1",
"libkeymaster4support",
"libcrypto_static",
"libkeymaster4_1support",
"libkeymaster4support",
"libkeymaster4vtstest",
],
cflags: [
"-Wall",
"-O0",
],
test_suites: [
"general-tests",
"vts-core",
],
test_suites: ["vts-core"],
}

View File

@@ -0,0 +1,278 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Keymaster4_1HidlTest.h"
#include <cutils/properties.h>
#include <openssl/x509.h>
#include <keymasterV4_1/attestation_record.h>
#include <keymasterV4_1/authorization_set.h>
namespace android::hardware::keymaster::V4_0 {
bool operator==(const AuthorizationSet& a, const AuthorizationSet& b) {
return std::equal(a.begin(), a.end(), b.begin(), b.end());
}
} // namespace android::hardware::keymaster::V4_0
namespace android::hardware::keymaster::V4_1 {
inline ::std::ostream& operator<<(::std::ostream& os, Tag tag) {
return os << toString(tag);
}
namespace test {
using std::string;
using std::tuple;
namespace {
char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
string bin2hex(const hidl_vec<uint8_t>& data) {
string retval;
retval.reserve(data.size() * 2 + 1);
for (uint8_t byte : data) {
retval.push_back(nibble2hex[0x0F & (byte >> 4)]);
retval.push_back(nibble2hex[0x0F & byte]);
}
return retval;
}
struct AuthorizationSetDifferences {
string aName;
string bName;
AuthorizationSet aWhackB;
AuthorizationSet bWhackA;
};
std::ostream& operator<<(std::ostream& o, const AuthorizationSetDifferences& diffs) {
if (!diffs.aWhackB.empty()) {
o << "Set " << diffs.aName << " contains the following that " << diffs.bName << " does not"
<< diffs.aWhackB;
if (!diffs.bWhackA.empty()) o << std::endl;
}
if (!diffs.bWhackA.empty()) {
o << "Set " << diffs.bName << " contains the following that " << diffs.aName << " does not"
<< diffs.bWhackA;
}
return o;
}
// Computes and returns a \ b and b \ a ('\' is the set-difference operator, a \ b means all the
// elements that are in a but not b, i.e. take a and whack all the elements in b) to the provided
// stream. The sets must be sorted.
//
// This provides a simple and clear view of how the two sets differ, generally much
// easier than scrutinizing printouts of the two sets.
AuthorizationSetDifferences difference(string aName, const AuthorizationSet& a, string bName,
const AuthorizationSet& b) {
AuthorizationSetDifferences diffs = {std::move(aName), std::move(bName), {}, {}};
std::set_difference(a.begin(), a.end(), b.begin(), b.end(), std::back_inserter(diffs.aWhackB));
std::set_difference(b.begin(), b.end(), a.begin(), a.end(), std::back_inserter(diffs.bWhackA));
return diffs;
}
#define DIFFERENCE(a, b) difference(#a, a, #b, b)
void check_root_of_trust(const RootOfTrust& root_of_trust) {
char vb_meta_device_state[PROPERTY_VALUE_MAX];
if (property_get("ro.boot.vbmeta.device_state", vb_meta_device_state, "") == 0) return;
char vb_meta_digest[PROPERTY_VALUE_MAX];
EXPECT_GT(property_get("ro.boot.vbmeta.digest", vb_meta_digest, ""), 0);
EXPECT_EQ(vb_meta_digest, bin2hex(root_of_trust.verified_boot_hash));
// Verified boot key should be all 0's if the boot state is not verified or self signed
HidlBuf empty_boot_key(string(32, '\0'));
char vb_meta_bootstate[PROPERTY_VALUE_MAX];
auto& verified_boot_key = root_of_trust.verified_boot_key;
auto& verified_boot_state = root_of_trust.verified_boot_state;
EXPECT_GT(property_get("ro.boot.verifiedbootstate", vb_meta_bootstate, ""), 0);
if (!strcmp(vb_meta_bootstate, "green")) {
EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_VERIFIED);
EXPECT_NE(verified_boot_key, empty_boot_key);
} else if (!strcmp(vb_meta_bootstate, "yellow")) {
EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_SELF_SIGNED);
EXPECT_NE(verified_boot_key, empty_boot_key);
} else if (!strcmp(vb_meta_bootstate, "orange")) {
EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_UNVERIFIED);
EXPECT_EQ(verified_boot_key, empty_boot_key);
} else if (!strcmp(vb_meta_bootstate, "red")) {
EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_FAILED);
} else {
EXPECT_EQ(verified_boot_state, V4_0::KM_VERIFIED_BOOT_UNVERIFIED);
EXPECT_EQ(verified_boot_key, empty_boot_key);
}
}
void check_attestation_record(AttestationRecord attestation, const HidlBuf& challenge,
AuthorizationSet expected_sw_enforced,
AuthorizationSet expected_hw_enforced,
SecurityLevel expected_security_level) {
EXPECT_EQ(41U, attestation.keymaster_version);
EXPECT_EQ(4U, attestation.attestation_version);
EXPECT_EQ(expected_security_level, attestation.attestation_security_level);
EXPECT_EQ(expected_security_level, attestation.keymaster_security_level);
EXPECT_EQ(challenge, attestation.attestation_challenge);
check_root_of_trust(attestation.root_of_trust);
// Sort all of the authorization lists, so that equality matching works.
expected_sw_enforced.Sort();
expected_hw_enforced.Sort();
attestation.software_enforced.Sort();
attestation.hardware_enforced.Sort();
EXPECT_EQ(expected_sw_enforced, attestation.software_enforced)
<< DIFFERENCE(expected_sw_enforced, attestation.software_enforced);
EXPECT_EQ(expected_hw_enforced, attestation.hardware_enforced)
<< DIFFERENCE(expected_hw_enforced, attestation.hardware_enforced);
}
} // namespace
using std::string;
using DeviceUniqueAttestationTest = Keymaster4_1HidlTest;
TEST_P(DeviceUniqueAttestationTest, StrongBoxOnly) {
if (SecLevel() != SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaSigningKey(2048, 65537)
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_INCLUDE_UNIQUE_ID))));
hidl_vec<hidl_vec<uint8_t>> cert_chain;
EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
convert(AttestKey(
AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
.Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
&cert_chain)));
CheckedDeleteKey();
ASSERT_EQ(ErrorCode::OK, convert(GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(EcCurve::P_256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_INCLUDE_UNIQUE_ID))));
EXPECT_EQ(ErrorCode::UNIMPLEMENTED,
convert(AttestKey(
AuthorizationSetBuilder()
.Authorization(TAG_ATTESTATION_CHALLENGE, HidlBuf("challenge"))
.Authorization(TAG_ATTESTATION_APPLICATION_ID, HidlBuf("foo")),
&cert_chain)));
}
TEST_P(DeviceUniqueAttestationTest, Rsa) {
if (SecLevel() != SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK,
convert(GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaSigningKey(2048, 65537)
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_CREATION_DATETIME, 1))));
hidl_vec<hidl_vec<uint8_t>> cert_chain;
HidlBuf challenge("challenge");
HidlBuf app_id("foo");
EXPECT_EQ(ErrorCode::OK,
convert(AttestKey(AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
.Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
&cert_chain)));
EXPECT_EQ(1U, cert_chain.size());
auto [err, attestation] = parse_attestation_record(cert_chain[0]);
EXPECT_EQ(ErrorCode::OK, err);
check_attestation_record(attestation, challenge,
/* sw_enforced */
AuthorizationSetBuilder()
.Authorization(TAG_CREATION_DATETIME, 1)
.Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
/* hw_enforced */
AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_NO_AUTH_REQUIRED)
.RsaSigningKey(2048, 65537)
.Digest(Digest::SHA_2_256)
.Padding(PaddingMode::RSA_PKCS1_1_5_SIGN)
.Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
.Authorization(TAG_OS_VERSION, os_version())
.Authorization(TAG_OS_PATCHLEVEL, os_patch_level()),
SecLevel());
}
TEST_P(DeviceUniqueAttestationTest, Ecdsa) {
if (SecLevel() != SecurityLevel::STRONGBOX) return;
ASSERT_EQ(ErrorCode::OK,
convert(GenerateKey(AuthorizationSetBuilder()
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_CREATION_DATETIME, 1))));
hidl_vec<hidl_vec<uint8_t>> cert_chain;
HidlBuf challenge("challenge");
HidlBuf app_id("foo");
EXPECT_EQ(ErrorCode::OK,
convert(AttestKey(AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_ATTESTATION_CHALLENGE, challenge)
.Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
&cert_chain)));
EXPECT_EQ(1U, cert_chain.size());
auto [err, attestation] = parse_attestation_record(cert_chain[0]);
EXPECT_EQ(ErrorCode::OK, err);
check_attestation_record(attestation, challenge,
/* sw_enforced */
AuthorizationSetBuilder()
.Authorization(TAG_CREATION_DATETIME, 1)
.Authorization(TAG_ATTESTATION_APPLICATION_ID, app_id),
/* hw_enforced */
AuthorizationSetBuilder()
.Authorization(TAG_DEVICE_UNIQUE_ATTESTATION)
.Authorization(TAG_NO_AUTH_REQUIRED)
.EcdsaSigningKey(256)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_EC_CURVE, EcCurve::P_256)
.Authorization(TAG_ORIGIN, KeyOrigin::GENERATED)
.Authorization(TAG_OS_VERSION, os_version())
.Authorization(TAG_OS_PATCHLEVEL, os_patch_level()),
SecLevel());
}
INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(DeviceUniqueAttestationTest);
} // namespace test
} // namespace android::hardware::keymaster::V4_1

View File

@@ -14,8 +14,78 @@
* limitations under the License.
*/
#include "Keymaster4_1HidlTest.h"
#include <keymasterV4_1/authorization_set.h>
namespace android::hardware::keymaster::V4_1::test {
using std::string;
using EarlyBootKeyTest = Keymaster4_1HidlTest;
// Because VTS tests are run on fully-booted machines, we can only run negative tests for early boot
// keys, which cannot be created or used after /data is mounted. This is the only test we can run
// in the normal case. The positive test will have to be done by the Android system, when it
// creates/uses early boot keys during boot. It should fail to boot if the early boot key usage
// fails.
TEST_P(EarlyBootKeyTest, CannotCreateEarlyBootKeys) {
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::EARLY_BOOT_ENDED);
CheckedDeleteKeyData(&aesKeyData);
CheckedDeleteKeyData(&hmacKeyData);
CheckedDeleteKeyData(&rsaKeyData);
CheckedDeleteKeyData(&ecdsaKeyData);
}
// This is a more comprenhensive test, but it can only be run on a machine which is still in early
// boot stage, which no proper Android device is by the time we can run VTS. To use this,
// un-disable it and modify vold to remove the call to earlyBootEnded(). Running the test will end
// early boot, so you'll have to reboot between runs.
TEST_P(EarlyBootKeyTest, DISABLED_FullTest) {
// Should be able to create keys, since early boot has not ended
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::OK);
// TAG_EARLY_BOOT_ONLY should be in hw-enforced.
EXPECT_TRUE(contains(aesKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
EXPECT_TRUE(contains(hmacKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
EXPECT_TRUE(contains(rsaKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
EXPECT_TRUE(contains(ecdsaKeyData.characteristics.hardwareEnforced, TAG_EARLY_BOOT_ONLY));
// Should be able to use keys, since early boot has not ended
EXPECT_EQ(ErrorCode::OK, UseAesKey(aesKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseHmacKey(hmacKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseRsaKey(rsaKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseEcdsaKey(ecdsaKeyData.blob));
// End early boot
Return<ErrorCode> earlyBootResult = keymaster().earlyBootEnded();
EXPECT_TRUE(earlyBootResult.isOk());
EXPECT_EQ(earlyBootResult, ErrorCode::OK);
// Should not be able to use already-created keys.
EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseAesKey(aesKeyData.blob));
EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseHmacKey(hmacKeyData.blob));
EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseRsaKey(rsaKeyData.blob));
EXPECT_EQ(ErrorCode::EARLY_BOOT_ENDED, UseEcdsaKey(ecdsaKeyData.blob));
CheckedDeleteKeyData(&aesKeyData);
CheckedDeleteKeyData(&hmacKeyData);
CheckedDeleteKeyData(&rsaKeyData);
CheckedDeleteKeyData(&ecdsaKeyData);
// Should not be able to create new keys
std::tie(aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData) =
CreateTestKeys(TAG_EARLY_BOOT_ONLY, ErrorCode::EARLY_BOOT_ENDED);
CheckedDeleteKeyData(&aesKeyData);
CheckedDeleteKeyData(&hmacKeyData);
CheckedDeleteKeyData(&rsaKeyData);
CheckedDeleteKeyData(&ecdsaKeyData);
}
INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(EarlyBootKeyTest);
} // namespace android::hardware::keymaster::V4_1::test

View File

@@ -0,0 +1,59 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Keymaster4_1HidlTest.h"
namespace android::hardware::keymaster::V4_1::test {
using std::string;
void Keymaster4_1HidlTest::SetUp() {
keymaster41_ = IKeymasterDevice::getService(GetParam());
InitializeKeymaster(keymaster41_);
}
auto Keymaster4_1HidlTest::ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation,
const string& message, const AuthorizationSet& in_params)
-> std::tuple<ErrorCode, string, AuthorizationSet /* out_params */> {
AuthorizationSet begin_out_params;
V4_0::ErrorCode result = Begin(operation, key_blob, in_params, &begin_out_params, &op_handle_);
AuthorizationSet out_params(std::move(begin_out_params));
if (result != V4_0::ErrorCode::OK) {
return {convert(result), {}, out_params};
}
string output;
size_t consumed = 0;
AuthorizationSet update_params;
AuthorizationSet update_out_params;
result = Update(op_handle_, update_params, message, &update_out_params, &output, &consumed);
out_params.push_back(update_out_params);
if (result != V4_0::ErrorCode::OK) {
return {convert(result), output, out_params};
}
string unused;
AuthorizationSet finish_params;
AuthorizationSet finish_out_params;
result = Finish(op_handle_, finish_params, message.substr(consumed), unused, &finish_out_params,
&output);
op_handle_ = V4_0::test::kOpHandleSentinel;
out_params.push_back(finish_out_params);
return {convert(result), output, out_params};
}
} // namespace android::hardware::keymaster::V4_1::test

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
#include <KeymasterHidlTest.h>
#include <keymasterV4_1/authorization_set.h>
namespace android::hardware::keymaster::V4_1::test {
using V4_0::test::HidlBuf;
class Keymaster4_1HidlTest : public V4_0::test::KeymasterHidlTest {
public:
using super = V4_0::test::KeymasterHidlTest;
ErrorCode convert(V4_0::ErrorCode error_code) { return static_cast<ErrorCode>(error_code); }
// These methods hide the base class versions.
void SetUp();
IKeymasterDevice& keymaster() { return *keymaster41_; };
struct KeyData {
HidlBuf blob;
KeyCharacteristics characteristics;
};
std::tuple<ErrorCode, KeyData> GenerateKeyData(const AuthorizationSet& keyDescription) {
KeyData keyData;
ErrorCode errorCode = convert(
super::GenerateKey(keyDescription, &keyData.blob, &keyData.characteristics));
return {errorCode, keyData};
}
void CheckedDeleteKeyData(KeyData* keyData) { CheckedDeleteKey(&keyData->blob); }
template <typename TagType>
std::tuple<KeyData /* aesKey */, KeyData /* hmacKey */, KeyData /* rsaKey */,
KeyData /* ecdsaKey */>
CreateTestKeys(TagType tagToTest, ErrorCode expectedReturn) {
ErrorCode errorCode;
/* AES */
KeyData aesKeyData;
std::tie(errorCode, aesKeyData) =
GenerateKeyData(AuthorizationSetBuilder()
.AesEncryptionKey(128)
.Authorization(tagToTest)
.BlockMode(BlockMode::ECB)
.Padding(PaddingMode::NONE)
.Authorization(TAG_NO_AUTH_REQUIRED));
EXPECT_EQ(expectedReturn, errorCode);
/* HMAC */
KeyData hmacKeyData;
std::tie(errorCode, hmacKeyData) =
GenerateKeyData(AuthorizationSetBuilder()
.HmacKey(128)
.Authorization(tagToTest)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_MIN_MAC_LENGTH, 128)
.Authorization(TAG_NO_AUTH_REQUIRED));
EXPECT_EQ(expectedReturn, errorCode);
/* RSA */
KeyData rsaKeyData;
std::tie(errorCode, rsaKeyData) =
GenerateKeyData(AuthorizationSetBuilder()
.RsaSigningKey(2048, 65537)
.Authorization(tagToTest)
.Digest(Digest::NONE)
.Padding(PaddingMode::NONE)
.Authorization(TAG_NO_AUTH_REQUIRED));
EXPECT_EQ(expectedReturn, errorCode);
/* ECDSA */
KeyData ecdsaKeyData;
std::tie(errorCode, ecdsaKeyData) =
GenerateKeyData(AuthorizationSetBuilder()
.EcdsaSigningKey(256)
.Authorization(tagToTest)
.Digest(Digest::SHA_2_256)
.Authorization(TAG_NO_AUTH_REQUIRED));
EXPECT_EQ(expectedReturn, errorCode);
return {aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData};
}
std::tuple<ErrorCode, std::string /* processedMessage */, AuthorizationSet /* out_params */>
ProcessMessage(const HidlBuf& key_blob, KeyPurpose operation, const std::string& message,
const AuthorizationSet& in_params);
ErrorCode UseAesKey(const HidlBuf& aesKeyBlob) {
auto [result, ciphertext, out_params] = ProcessMessage(
aesKeyBlob, KeyPurpose::ENCRYPT, "1234567890123456",
AuthorizationSetBuilder().BlockMode(BlockMode::ECB).Padding(PaddingMode::NONE));
return result;
}
ErrorCode UseHmacKey(const HidlBuf& hmacKeyBlob) {
auto [result, mac, out_params] =
ProcessMessage(hmacKeyBlob, KeyPurpose::SIGN, "1234567890123456",
AuthorizationSetBuilder().Authorization(TAG_MAC_LENGTH, 128));
return result;
}
ErrorCode UseRsaKey(const HidlBuf& rsaKeyBlob) {
std::string message(2048 / 8, 'a');
auto [result, signature, out_params] = ProcessMessage(
rsaKeyBlob, KeyPurpose::SIGN, message,
AuthorizationSetBuilder().Digest(Digest::NONE).Padding(PaddingMode::NONE));
return result;
}
ErrorCode UseEcdsaKey(const HidlBuf& ecdsaKeyBlob) {
auto [result, signature, out_params] =
ProcessMessage(ecdsaKeyBlob, KeyPurpose::SIGN, "a",
AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
return result;
}
static std::vector<std::string> build_params() {
auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
return params;
}
private:
sp<IKeymasterDevice> keymaster41_;
};
template <typename TypedTag>
bool contains(hidl_vec<KeyParameter>& set, TypedTag typedTag) {
return std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) {
return param.tag == static_cast<V4_0::Tag>(typedTag);
}) != set.end();
}
#define INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(name) \
INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
testing::ValuesIn(Keymaster4_1HidlTest::build_params()), \
android::hardware::PrintInstanceNameToString)
} // namespace android::hardware::keymaster::V4_1::test

View File

@@ -0,0 +1,63 @@
/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "Keymaster4_1HidlTest.h"
#include <keymasterV4_1/authorization_set.h>
namespace android::hardware::keymaster::V4_1::test {
using UnlockedDeviceRequiredTest = Keymaster4_1HidlTest;
// This may be a problematic test. It can't be run repeatedly without unlocking the device in
// between runs... and on most test devices there are no enrolled credentials so it can't be
// unlocked at all, meaning the only way to get the test to pass again on a properly-functioning
// device is to reboot it. For that reason, this is disabled by default. It can be used as part of
// a manual test process, which includes unlocking between runs, which is why it's included here.
// Well, that and the fact that it's the only test we can do without also making calls into the
// Gatekeeper HAL. We haven't written any cross-HAL tests, and don't know what all of the
// implications might be, so that may or may not be a solution.
//
// TODO(swillden): Use the Gatekeeper HAL to enroll some test credentials which we can verify to get
// an unlock auth token. If that works, enable the improved test.
TEST_P(UnlockedDeviceRequiredTest, DISABLED_KeysBecomeUnusable) {
auto [aesKeyData, hmacKeyData, rsaKeyData, ecdsaKeyData] =
CreateTestKeys(TAG_UNLOCKED_DEVICE_REQUIRED, ErrorCode::OK);
EXPECT_EQ(ErrorCode::OK, UseAesKey(aesKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseHmacKey(hmacKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseRsaKey(rsaKeyData.blob));
EXPECT_EQ(ErrorCode::OK, UseEcdsaKey(ecdsaKeyData.blob));
Return<ErrorCode> rc =
keymaster().deviceLocked(false /* passwordOnly */, {} /* verificationToken */);
ASSERT_TRUE(rc.isOk());
ASSERT_EQ(ErrorCode::OK, static_cast<ErrorCode>(rc));
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseAesKey(aesKeyData.blob));
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseHmacKey(hmacKeyData.blob));
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseRsaKey(rsaKeyData.blob));
EXPECT_EQ(ErrorCode::DEVICE_LOCKED, UseEcdsaKey(ecdsaKeyData.blob));
CheckedDeleteKeyData(&aesKeyData);
CheckedDeleteKeyData(&hmacKeyData);
CheckedDeleteKeyData(&rsaKeyData);
CheckedDeleteKeyData(&ecdsaKeyData);
}
INSTANTIATE_KEYMASTER_4_1_HIDL_TEST(UnlockedDeviceRequiredTest);
} // namespace android::hardware::keymaster::V4_1::test