diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp index 000d46e7db..27e00c173a 100644 --- a/keymaster/4.0/support/attestation_record.cpp +++ b/keymaster/4.0/support/attestation_record.cpp @@ -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( 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); diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp index d6b50f5172..a024ff9c60 100644 --- a/keymaster/4.0/support/authorization_set.cpp +++ b/keymaster/4.0/support/authorization_set.cpp @@ -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)) { diff --git a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h index cb29c64b1e..bc7f311097 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h +++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_tags.h @@ -355,95 +355,61 @@ inline NullOr>::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; } diff --git a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h index cc71dd1326..b3869f4ca3 100644 --- a/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h +++ b/keymaster/4.0/support/include/keymasterV4_0/openssl_utils.h @@ -18,6 +18,8 @@ #define HARDWARE_INTERFACES_KEYMASTER_4_0_SUPPORT_OPENSSL_UTILS_H_ #include +#include +#include template struct UniquePtrDeleter { diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp index 7244ae3c96..db500805dc 100644 --- a/keymaster/4.0/vts/functional/Android.bp +++ b/keymaster/4.0/vts/functional/Android.bp @@ -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", + ], +} diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp index 5d0e262ca5..d0ad433464 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp @@ -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 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 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 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 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 KeymasterHidlTest::ValidCurves() { @@ -704,6 +709,7 @@ std::vector KeymasterHidlTest::InvalidCurves() { std::vector 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 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 {}; } diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.h b/keymaster/4.0/vts/functional/KeymasterHidlTest.h index faa7c75409..f495516146 100644 --- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h +++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h @@ -38,12 +38,14 @@ using hidl::base::V1_0::DebugInfo; using ::std::string; class HidlBuf : public hidl_vec { - typedef hidl_vec super; + using super = hidl_vec; 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 { 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 { AbortIfNeeded(); } - void InitializeKeymaster(); + void InitializeKeymaster(sp 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 { KeyCharacteristics key_characteristics_; OperationHandle op_handle_ = kOpHandleSentinel; + static std::vector build_params() { + auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor); + return params; + } + private: sp keymaster_; uint32_t os_version_; @@ -214,10 +233,9 @@ class KeymasterHidlTest : public ::testing::TestWithParam { 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 diff --git a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp index d9131f59c7..6cbe4dafae 100644 --- a/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp +++ b/keymaster/4.0/vts/functional/keymaster_hidl_hal_test.cpp @@ -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 + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#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 +void copyAuthTag(const stack_st_ASN1_INTEGER* stack, TypedTag ttag, + AuthorizationSet* auth_list) { + typedef typename V4_0::TypedTag2ValueType::type ValueT; + for (size_t i = 0; i < sk_ASN1_INTEGER_num(stack); ++i) { + auth_list->push_back( + ttag, static_cast(ASN1_INTEGER_get(sk_ASN1_INTEGER_value(stack, i)))); + } +} + +template +void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag ttag, + AuthorizationSet* auth_list) { + typedef typename V4_0::TypedTag2ValueType::type ValueT; + if (!asn1_int) return; + auth_list->push_back(ttag, static_cast(ASN1_INTEGER_get(asn1_int))); +} + +template +void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag 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(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 +void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag 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 +void copyAuthTag(const ASN1_INTEGER* asn1_int, TypedTag 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 +void copyAuthTag(const ASN1_NULL* asn1_null, TypedTag ttag, + AuthorizationSet* auth_list) { + if (!asn1_null) return; + auth_list->push_back(ttag); +} + +template +void copyAuthTag(const ASN1_OCTET_STRING* asn1_string, TypedTag ttag, + AuthorizationSet* auth_list) { + if (!asn1_string) return; + hidl_vec 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 parse_attestation_record(const hidl_vec& 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(ASN1_ENUMERATED_get(record->attestation_security_level)); + result.keymaster_version = ASN1_INTEGER_get(record->keymaster_version); + result.keymaster_security_level = + static_cast(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( + 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 diff --git a/keymaster/4.1/support/include/keymasterV4_1/attestation_record.h b/keymaster/4.1/support/include/keymasterV4_1/attestation_record.h new file mode 100644 index 0000000000..b543bddf13 --- /dev/null +++ b/keymaster/4.1/support/include/keymasterV4_1/attestation_record.h @@ -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 +#include +#include +#include + +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 verified_boot_key; + hidl_vec 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 attestation_challenge; + AuthorizationSet software_enforced; + AuthorizationSet hardware_enforced; + hidl_vec unique_id; +}; + +std::tuple parse_attestation_record(const hidl_vec& cert); + +} // namespace V4_1 +} // namespace keymaster +} // namespace hardware +} // namespace android diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h index 6ffe8e104e..a90ad8ef14 100644 --- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h +++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h @@ -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; diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp index f5a0c9c1aa..c2d7fa3547 100644 --- a/keymaster/4.1/vts/functional/Android.bp +++ b/keymaster/4.1/vts/functional/Android.bp @@ -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"], } diff --git a/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp new file mode 100644 index 0000000000..7ea3275851 --- /dev/null +++ b/keymaster/4.1/vts/functional/DeviceUniqueAttestationTest.cpp @@ -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 + +#include + +#include +#include + +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& 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> 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> 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> 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 diff --git a/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp index d1978a9cdf..a26c688be9 100644 --- a/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp +++ b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp @@ -14,8 +14,78 @@ * limitations under the License. */ +#include "Keymaster4_1HidlTest.h" + +#include + 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 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 diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.cpp b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.cpp new file mode 100644 index 0000000000..efedf284c3 --- /dev/null +++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.cpp @@ -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 { + 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 diff --git a/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h new file mode 100644 index 0000000000..6332c43200 --- /dev/null +++ b/keymaster/4.1/vts/functional/Keymaster4_1HidlTest.h @@ -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 + +#include +#include + +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(error_code); } + + // These methods hide the base class versions. + void SetUp(); + IKeymasterDevice& keymaster() { return *keymaster41_; }; + + struct KeyData { + HidlBuf blob; + KeyCharacteristics characteristics; + }; + + std::tuple 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 + std::tuple + 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 + 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 build_params() { + auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor); + return params; + } + + private: + sp keymaster41_; +}; + +template +bool contains(hidl_vec& set, TypedTag typedTag) { + return std::find_if(set.begin(), set.end(), [&](const KeyParameter& param) { + return param.tag == static_cast(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 diff --git a/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp b/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp new file mode 100644 index 0000000000..671bbbfe80 --- /dev/null +++ b/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp @@ -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 + +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 rc = + keymaster().deviceLocked(false /* passwordOnly */, {} /* verificationToken */); + ASSERT_TRUE(rc.isOk()); + ASSERT_EQ(ErrorCode::OK, static_cast(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