Merge "Add NNAPI control flow"
diff --git a/keymaster/4.0/support/Android.bp b/keymaster/4.0/support/Android.bp
index 2f40282..9c5fbab 100644
--- a/keymaster/4.0/support/Android.bp
+++ b/keymaster/4.0/support/Android.bp
@@ -27,11 +27,10 @@
"authorization_set.cpp",
"key_param_output.cpp",
"keymaster_utils.cpp",
- "Keymaster.cpp",
- "Keymaster3.cpp",
- "Keymaster4.cpp",
],
- export_include_dirs: ["include"],
+ export_include_dirs: [
+ "include",
+ ],
shared_libs: [
"android.hardware.keymaster@3.0",
"android.hardware.keymaster@4.0",
@@ -39,6 +38,5 @@
"libcrypto",
"libhardware",
"libhidlbase",
- "libutils",
- ]
+ ],
}
diff --git a/keymaster/4.0/support/Keymaster4.cpp b/keymaster/4.0/support/Keymaster4.cpp
deleted file mode 100644
index cc3d656..0000000
--- a/keymaster/4.0/support/Keymaster4.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
-**
-** Copyright 2017, 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_0/Keymaster4.h>
-
-#include <android-base/logging.h>
-
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
-
-void Keymaster4::getVersionIfNeeded() {
- if (haveVersion_) return;
-
- auto rc =
- dev_->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& keymasterName,
- const hidl_string& authorName) {
- version_ = {keymasterName, authorName, 4 /* major version */, securityLevel,
- true /* supportsEc */};
- haveVersion_ = true;
- });
-
- CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info";
-}
-
-} // namespace support
-} // namespace V4_0
-} // namespace keymaster
-} // namespace hardware
-} // namespace android
diff --git a/keymaster/4.0/support/OWNERS b/keymaster/4.0/support/OWNERS
index 335660d..a9efe66 100644
--- a/keymaster/4.0/support/OWNERS
+++ b/keymaster/4.0/support/OWNERS
@@ -1,2 +1,3 @@
jdanis@google.com
swillden@google.com
+jbires@google.com
diff --git a/keymaster/4.0/support/attestation_record.cpp b/keymaster/4.0/support/attestation_record.cpp
index 000d46e..27e00c1 100644
--- a/keymaster/4.0/support/attestation_record.cpp
+++ b/keymaster/4.0/support/attestation_record.cpp
@@ -321,19 +321,20 @@
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 @@
*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);
diff --git a/keymaster/4.0/support/authorization_set.cpp b/keymaster/4.0/support/authorization_set.cpp
index d6b50f5..a024ff9 100644
--- a/keymaster/4.0/support/authorization_set.cpp
+++ b/keymaster/4.0/support/authorization_set.cpp
@@ -25,7 +25,7 @@
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 @@
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/Keymaster4.h b/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
deleted file mode 100644
index dfd03ef..0000000
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster4.h
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- **
- ** Copyright 2017, 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.
- */
-
-#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
-#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
-
-#include "Keymaster.h"
-
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
-
-using android::sp;
-using IKeymaster4Device = ::android::hardware::keymaster::V4_0::IKeymasterDevice;
-
-class Keymaster4 : public Keymaster {
- public:
- using WrappedIKeymasterDevice = IKeymaster4Device;
- Keymaster4(sp<IKeymasterDevice> km4_dev, const hidl_string& instanceName)
- : Keymaster(IKeymaster4Device::descriptor, instanceName),
- haveVersion_(false),
- dev_(km4_dev) {}
-
- const VersionResult& halVersion() const override {
- const_cast<Keymaster4*>(this)->getVersionIfNeeded();
- return version_;
- }
-
- Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
- return dev_->getHardwareInfo(_hidl_cb);
- }
-
- Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
- return dev_->getHmacSharingParameters(_hidl_cb);
- }
-
- Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
- computeSharedHmac_cb _hidl_cb) override {
- return dev_->computeSharedHmac(params, _hidl_cb);
- }
-
- Return<void> verifyAuthorization(uint64_t operationHandle, const hidl_vec<KeyParameter>& params,
- const HardwareAuthToken& authToken,
- verifyAuthorization_cb _hidl_cb) override {
- return dev_->verifyAuthorization(operationHandle, params, authToken, _hidl_cb);
- }
-
- Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
- return dev_->addRngEntropy(data);
- }
-
- Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
- generateKey_cb _hidl_cb) override {
- return dev_->generateKey(keyParams, _hidl_cb);
- }
-
- Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId,
- const hidl_vec<uint8_t>& appData,
- getKeyCharacteristics_cb _hidl_cb) override {
- return dev_->getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
- }
-
- Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
- const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override {
- return dev_->importKey(params, keyFormat, keyData, _hidl_cb);
- }
-
- Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
- const hidl_vec<uint8_t>& wrappingKeyBlob,
- const hidl_vec<uint8_t>& maskingKey,
- const hidl_vec<KeyParameter>& unwrappingParams,
- uint64_t passwordSid, uint64_t biometricSid,
- importWrappedKey_cb _hidl_cb) {
- return dev_->importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey, unwrappingParams,
- passwordSid, biometricSid, _hidl_cb);
- }
-
- Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
- const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
- exportKey_cb _hidl_cb) override {
- return dev_->exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
- }
-
- Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
- const hidl_vec<KeyParameter>& attestParams,
- attestKey_cb _hidl_cb) override {
- return dev_->attestKey(keyToAttest, attestParams, _hidl_cb);
- }
-
- Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
- const hidl_vec<KeyParameter>& upgradeParams,
- upgradeKey_cb _hidl_cb) override {
- return dev_->upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
- }
-
- Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
- return dev_->deleteKey(keyBlob);
- }
-
- Return<ErrorCode> deleteAllKeys() override { return dev_->deleteAllKeys(); }
-
- Return<ErrorCode> destroyAttestationIds() override { return dev_->destroyAttestationIds(); }
-
- Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
- const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
- begin_cb _hidl_cb) override {
- return dev_->begin(purpose, key, inParams, authToken, _hidl_cb);
- }
-
- Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
- const VerificationToken& verificationToken, update_cb _hidl_cb) override {
- return dev_->update(operationHandle, inParams, input, authToken, verificationToken,
- _hidl_cb);
- }
-
- Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
- const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
- const HardwareAuthToken& authToken,
- const VerificationToken& verificationToken, finish_cb _hidl_cb) override {
- return dev_->finish(operationHandle, inParams, input, signature, authToken,
- verificationToken, _hidl_cb);
- }
-
- Return<ErrorCode> abort(uint64_t operationHandle) override {
- return dev_->abort(operationHandle);
- }
-
- private:
- void getVersionIfNeeded();
-
- bool haveVersion_;
- VersionResult version_;
- sp<IKeymaster4Device> dev_;
-};
-
-} // namespace support
-} // namespace V4_0
-} // namespace keymaster
-} // namespace hardware
-} // namespace android
-
-#endif // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_4_H_
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 cb29c64..bc7f311 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 @@
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/keymaster_utils.h b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
index 5e5ae8d..61645f8 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
+++ b/keymaster/4.0/support/include/keymasterV4_0/keymaster_utils.h
@@ -52,6 +52,9 @@
HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer);
hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token);
+uint32_t getOsVersion();
+uint32_t getOsPatchlevel();
+
} // namespace support
} // namespace V4_0
} // namespace keymaster
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 cc71dd1..b3869f4 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 <android/hardware/keymaster/4.0/types.h>
+#include <openssl/evp.h>
+#include <openssl/x509.h>
template <typename T, void (*F)(T*)>
struct UniquePtrDeleter {
diff --git a/keymaster/4.0/support/keymaster_utils.cpp b/keymaster/4.0/support/keymaster_utils.cpp
index e35fdd3..850a776 100644
--- a/keymaster/4.0/support/keymaster_utils.cpp
+++ b/keymaster/4.0/support/keymaster_utils.cpp
@@ -14,11 +14,13 @@
* limitations under the License.
*/
+#include <regex.h>
+
+#include <android-base/properties.h>
#include <hardware/hw_auth_token.h>
#include <keymasterV4_0/keymaster_utils.h>
-namespace android {
-namespace hardware {
+namespace android::hardware {
inline static bool operator<(const hidl_vec<uint8_t>& a, const hidl_vec<uint8_t>& b) {
auto result = memcmp(a.data(), b.data(), std::min(a.size(), b.size()));
@@ -32,8 +34,7 @@
return memcmp(a.data(), b.data(), SIZE) == -1;
}
-namespace keymaster {
-namespace V4_0 {
+namespace keymaster::V4_0 {
bool operator<(const HmacSharingParameters& a, const HmacSharingParameters& b) {
return std::tie(a.seed, a.nonce) < std::tie(b.seed, b.nonce);
@@ -58,9 +59,9 @@
hidl_vec<uint8_t> authToken2HidlVec(const HardwareAuthToken& token) {
static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
- sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
- sizeof(token.timestamp) + kHmacSize ==
- sizeof(hw_auth_token_t),
+ sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+ sizeof(token.timestamp) + kHmacSize ==
+ sizeof(hw_auth_token_t),
"HardwareAuthToken content size does not match hw_auth_token_t size");
hidl_vec<uint8_t> result;
@@ -86,9 +87,9 @@
HardwareAuthToken hidlVec2AuthToken(const hidl_vec<uint8_t>& buffer) {
HardwareAuthToken token;
static_assert(1 /* version size */ + sizeof(token.challenge) + sizeof(token.userId) +
- sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
- sizeof(token.timestamp) + kHmacSize ==
- sizeof(hw_auth_token_t),
+ sizeof(token.authenticatorId) + sizeof(token.authenticatorType) +
+ sizeof(token.timestamp) + kHmacSize ==
+ sizeof(hw_auth_token_t),
"HardwareAuthToken content size does not match hw_auth_token_t size");
if (buffer.size() != sizeof(hw_auth_token_t)) return {};
@@ -100,7 +101,7 @@
pos = copy_bytes_from_iterator(&token.authenticatorId, pos);
pos = copy_bytes_from_iterator(&token.authenticatorType, pos);
token.authenticatorType = static_cast<HardwareAuthenticatorType>(
- ntohl(static_cast<uint32_t>(token.authenticatorType)));
+ ntohl(static_cast<uint32_t>(token.authenticatorType)));
pos = copy_bytes_from_iterator(&token.timestamp, pos);
token.timestamp = ntohq(token.timestamp);
token.mac.resize(kHmacSize);
@@ -109,8 +110,93 @@
return token;
}
+namespace {
+
+constexpr char kPlatformVersionProp[] = "ro.build.version.release";
+constexpr char kPlatformVersionRegex[] = "^([0-9]{1,2})(\\.([0-9]{1,2}))?(\\.([0-9]{1,2}))?";
+constexpr size_t kMajorVersionMatch = 1;
+constexpr size_t kMinorVersionMatch = 3;
+constexpr size_t kSubminorVersionMatch = 5;
+constexpr size_t kPlatformVersionMatchCount = kSubminorVersionMatch + 1;
+
+constexpr char kPlatformPatchlevelProp[] = "ro.build.version.security_patch";
+constexpr char kPlatformPatchlevelRegex[] = "^([0-9]{4})-([0-9]{2})-[0-9]{2}$";
+constexpr size_t kYearMatch = 1;
+constexpr size_t kMonthMatch = 2;
+constexpr size_t kPlatformPatchlevelMatchCount = kMonthMatch + 1;
+
+uint32_t match_to_uint32(const char* expression, const regmatch_t& match) {
+ if (match.rm_so == -1) return 0;
+
+ size_t len = match.rm_eo - match.rm_so;
+ std::string s(expression + match.rm_so, len);
+ return std::stoul(s);
+}
+
+std::string wait_and_get_property(const char* prop) {
+ std::string prop_value;
+ while (!android::base::WaitForPropertyCreation(prop))
+ ;
+ prop_value = android::base::GetProperty(prop, "" /* default */);
+ return prop_value;
+}
+
+} // anonymous namespace
+
+uint32_t getOsVersion(const char* version_str) {
+ regex_t regex;
+ if (regcomp(®ex, kPlatformVersionRegex, REG_EXTENDED)) {
+ return 0;
+ }
+
+ regmatch_t matches[kPlatformVersionMatchCount];
+ int not_match =
+ regexec(®ex, version_str, kPlatformVersionMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
+ return 0;
+ }
+
+ uint32_t major = match_to_uint32(version_str, matches[kMajorVersionMatch]);
+ uint32_t minor = match_to_uint32(version_str, matches[kMinorVersionMatch]);
+ uint32_t subminor = match_to_uint32(version_str, matches[kSubminorVersionMatch]);
+
+ return (major * 100 + minor) * 100 + subminor;
+}
+
+uint32_t getOsVersion() {
+ std::string version = wait_and_get_property(kPlatformVersionProp);
+ return getOsVersion(version.c_str());
+}
+
+uint32_t getOsPatchlevel(const char* patchlevel_str) {
+ regex_t regex;
+ if (regcomp(®ex, kPlatformPatchlevelRegex, REG_EXTENDED) != 0) {
+ return 0;
+ }
+
+ regmatch_t matches[kPlatformPatchlevelMatchCount];
+ int not_match =
+ regexec(®ex, patchlevel_str, kPlatformPatchlevelMatchCount, matches, 0 /* flags */);
+ regfree(®ex);
+ if (not_match) {
+ return 0;
+ }
+
+ uint32_t year = match_to_uint32(patchlevel_str, matches[kYearMatch]);
+ uint32_t month = match_to_uint32(patchlevel_str, matches[kMonthMatch]);
+
+ if (month < 1 || month > 12) {
+ return 0;
+ }
+ return year * 100 + month;
+}
+
+uint32_t getOsPatchlevel() {
+ std::string patchlevel = wait_and_get_property(kPlatformPatchlevelProp);
+ return getOsPatchlevel(patchlevel.c_str());
+}
+
} // namespace support
-} // namespace V4_0
-} // namespace keymaster
-} // namespace hardware
-} // namespace android
+} // namespace keymaster::V4_0
+} // namespace android::hardware
diff --git a/keymaster/4.0/vts/functional/Android.bp b/keymaster/4.0/vts/functional/Android.bp
index 5649f20..db50080 100644
--- a/keymaster/4.0/vts/functional/Android.bp
+++ b/keymaster/4.0/vts/functional/Android.bp
@@ -19,7 +19,6 @@
defaults: ["VtsHalTargetTestDefaults"],
srcs: [
"HmacKeySharingTest.cpp",
- "KeymasterHidlTest.cpp",
"VerificationTokenTest.cpp",
"keymaster_hidl_hal_test.cpp",
],
@@ -27,7 +26,25 @@
"android.hardware.keymaster@4.0",
"libcrypto_static",
"libkeymaster4support",
- "libsoftkeymasterdevice",
+ "libkeymaster4vtstest",
],
- test_suites: ["general-tests", "vts-core"],
+ 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/HmacKeySharingTest.cpp b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
index c228ef7..f57a668 100644
--- a/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
+++ b/keymaster/4.0/vts/functional/HmacKeySharingTest.cpp
@@ -28,6 +28,16 @@
*/
class HmacKeySharingTest : public KeymasterHidlTest {
protected:
+ const std::vector<sp<IKeymasterDevice>>& allKeymasters() {
+ if (all_keymasters_.empty()) {
+ auto names = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
+ for (const auto& name : names) {
+ all_keymasters_.push_back(IKeymasterDevice::getService(name));
+ }
+ }
+ return all_keymasters_;
+ }
+
struct GetParamsResult {
ErrorCode error;
HmacSharingParameters params;
@@ -99,8 +109,13 @@
EXPECT_EQ(expected, response.sharing_check) << "Sharing check values should match.";
}
}
+
+ private:
+ static std::vector<sp<IKeymasterDevice>> all_keymasters_;
};
+std::vector<sp<IKeymasterDevice>> HmacKeySharingTest::all_keymasters_;
+
TEST_P(HmacKeySharingTest, GetParameters) {
auto result1 = getHmacSharingParameters(keymaster());
EXPECT_EQ(ErrorCode::OK, result1.error);
@@ -115,26 +130,26 @@
}
TEST_P(HmacKeySharingTest, ComputeSharedHmac) {
- auto params = getHmacSharingParameters(all_keymasters());
- ASSERT_EQ(all_keymasters().size(), params.size())
- << "One or more keymasters failed to provide parameters.";
+ auto params = getHmacSharingParameters(allKeymasters());
+ ASSERT_EQ(allKeymasters().size(), params.size())
+ << "One or more keymasters failed to provide parameters.";
auto nonces = copyNonces(params);
- EXPECT_EQ(all_keymasters().size(), nonces.size());
+ EXPECT_EQ(allKeymasters().size(), nonces.size());
std::sort(nonces.begin(), nonces.end());
std::unique(nonces.begin(), nonces.end());
- EXPECT_EQ(all_keymasters().size(), nonces.size());
+ EXPECT_EQ(allKeymasters().size(), nonces.size());
- auto responses = computeSharedHmac(all_keymasters(), params);
+ auto responses = computeSharedHmac(allKeymasters(), params);
ASSERT_GT(responses.size(), 0U);
verifyResponses(responses[0].sharing_check, responses);
// Do it a second time. Should get the same answers.
- params = getHmacSharingParameters(all_keymasters());
- ASSERT_EQ(all_keymasters().size(), params.size())
- << "One or more keymasters failed to provide parameters.";
+ params = getHmacSharingParameters(allKeymasters());
+ ASSERT_EQ(allKeymasters().size(), params.size())
+ << "One or more keymasters failed to provide parameters.";
- responses = computeSharedHmac(all_keymasters(), params);
+ responses = computeSharedHmac(allKeymasters(), params);
ASSERT_GT(responses.size(), 0U);
ASSERT_EQ(32U, responses[0].sharing_check.size());
verifyResponses(responses[0].sharing_check, responses);
@@ -160,15 +175,16 @@
// sync with respect to the HMAC key. Granted that VTS tests aren't run on in-use production
// devices, this still has the potential to cause confusion. To mitigate that, we always
// (barring crashes :-/) re-run the unmodified agreement process on our way out.
- auto fixup_hmac = finally(
- [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+ auto fixup_hmac = finally([&]() {
+ computeSharedHmac(allKeymasters(), getHmacSharingParameters(allKeymasters()));
+ });
- auto params = getHmacSharingParameters(all_keymasters());
- ASSERT_EQ(all_keymasters().size(), params.size())
- << "One or more keymasters failed to provide parameters.";
+ auto params = getHmacSharingParameters(allKeymasters());
+ ASSERT_EQ(allKeymasters().size(), params.size())
+ << "One or more keymasters failed to provide parameters.";
// All should be well in the normal case
- auto responses = computeSharedHmac(all_keymasters(), params);
+ auto responses = computeSharedHmac(allKeymasters(), params);
ASSERT_GT(responses.size(), 0U);
HidlBuf correct_response = responses[0].sharing_check;
@@ -181,7 +197,7 @@
uint8_t bit_to_tweak = rand() % 8;
params[param_to_tweak].nonce[byte_to_tweak] ^= (1 << bit_to_tweak);
- responses = computeSharedHmac(all_keymasters(), params);
+ responses = computeSharedHmac(allKeymasters(), params);
for (size_t i = 0; i < responses.size(); ++i) {
if (i == param_to_tweak) {
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
@@ -199,15 +215,16 @@
// sync with respect to the HMAC key. Granted that VTS tests aren't run on in-use production
// devices, this still has the potential to cause confusion. To mitigate that, we always
// (barring crashes :-/) re-run the unmodified agreement process on our way out.
- auto fixup_hmac = finally(
- [&]() { computeSharedHmac(all_keymasters(), getHmacSharingParameters(all_keymasters())); });
+ auto fixup_hmac = finally([&]() {
+ computeSharedHmac(allKeymasters(), getHmacSharingParameters(allKeymasters()));
+ });
- auto params = getHmacSharingParameters(all_keymasters());
- ASSERT_EQ(all_keymasters().size(), params.size())
- << "One or more keymasters failed to provide parameters.";
+ auto params = getHmacSharingParameters(allKeymasters());
+ ASSERT_EQ(allKeymasters().size(), params.size())
+ << "One or more keymasters failed to provide parameters.";
// All should be well in the normal case
- auto responses = computeSharedHmac(all_keymasters(), params);
+ auto responses = computeSharedHmac(allKeymasters(), params);
ASSERT_GT(responses.size(), 0U);
HidlBuf correct_response = responses[0].sharing_check;
@@ -223,7 +240,7 @@
}
to_tweak[0]++;
- responses = computeSharedHmac(all_keymasters(), params);
+ responses = computeSharedHmac(allKeymasters(), params);
for (size_t i = 0; i < responses.size(); ++i) {
if (i == param_to_tweak) {
EXPECT_EQ(ErrorCode::INVALID_ARGUMENT, responses[i].error)
@@ -236,10 +253,7 @@
}
}
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, HmacKeySharingTest,
- testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor)),
- android::hardware::PrintInstanceNameToString);
+INSTANTIATE_KEYMASTER_HIDL_TEST(HmacKeySharingTest);
} // namespace test
} // namespace V4_0
diff --git a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
index 7241984..d0ad433 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.cpp
@@ -23,6 +23,7 @@
#include <android/hidl/manager/1.0/IServiceManager.h>
#include <keymasterV4_0/key_param_output.h>
+#include <keymasterV4_0/keymaster_utils.h>
namespace android {
namespace hardware {
@@ -41,39 +42,26 @@
namespace test {
-void KeymasterHidlTest::InitializeKeymaster() {
- service_name_ = GetParam();
- keymaster_ = IKeymasterDevice::getService(service_name_);
- ASSERT_NE(keymaster_, nullptr);
+using namespace std::literals::chrono_literals;
+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) {
- securityLevel_ = securityLevel;
- name_ = name;
- author_ = author;
- })
- .isOk());
+ ->getHardwareInfo([&](SecurityLevel securityLevel, const hidl_string& name,
+ const hidl_string& author) {
+ securityLevel_ = securityLevel;
+ name_ = name;
+ author_ = author;
+ })
+ .isOk());
+
+ os_version_ = support::getOsVersion();
+ os_patch_level_ = support::getOsPatchlevel();
}
void KeymasterHidlTest::SetUp() {
- InitializeKeymaster();
-
- os_version_ = ::keymaster::GetOsVersion();
- os_patch_level_ = ::keymaster::GetOsPatchlevel();
-
- auto service_manager = android::hidl::manager::V1_0::IServiceManager::getService();
- ASSERT_NE(nullptr, service_manager.get());
- all_keymasters_.push_back(keymaster_);
- service_manager->listByInterface(
- IKeymasterDevice::descriptor, [&](const hidl_vec<hidl_string>& names) {
- for (auto& name : names) {
- if (name == service_name_) continue;
- auto keymaster = IKeymasterDevice::getService(name);
- ASSERT_NE(keymaster, nullptr);
- all_keymasters_.push_back(keymaster);
- }
- });
+ InitializeKeymaster(IKeymasterDevice::getService(GetParam()));
}
ErrorCode KeymasterHidlTest::GenerateKey(const AuthorizationSet& key_desc, HidlBuf* key_blob,
@@ -138,7 +126,7 @@
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 */,
@@ -207,7 +195,9 @@
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,
@@ -647,23 +637,25 @@
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;
@@ -678,25 +670,27 @@
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() {
@@ -715,6 +709,7 @@
std::vector<Digest> KeymasterHidlTest::ValidDigests(bool withNone, bool withMD5) {
switch (SecLevel()) {
+ case SecurityLevel::SOFTWARE:
case SecurityLevel::TRUSTED_ENVIRONMENT:
if (withNone) {
if (withMD5)
@@ -740,10 +735,10 @@
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 4bd8b26..f495516 100644
--- a/keymaster/4.0/vts/functional/KeymasterHidlTest.h
+++ b/keymaster/4.0/vts/functional/KeymasterHidlTest.h
@@ -21,7 +21,6 @@
#include <gtest/gtest.h>
#include <hidl/GtestPrinter.h>
#include <hidl/ServiceManagement.h>
-#include <keymaster/keymaster_configuration.h>
#include <keymasterV4_0/authorization_set.h>
@@ -35,16 +34,18 @@
namespace test {
using ::android::sp;
-using ::std::string;
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:
+ 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) {
@@ -54,6 +55,18 @@
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;
}
@@ -70,20 +83,16 @@
class KeymasterHidlTest : public ::testing::TestWithParam<std::string> {
public:
- void SetUp();
+ void SetUp() override;
void TearDown() override {
if (key_blob_.size()) {
CheckedDeleteKey();
}
AbortIfNeeded();
- keymaster_.clear();
- all_keymasters_.clear();
}
- void InitializeKeymaster();
-
+ void InitializeKeymaster(sp<IKeymasterDevice> keymaster);
IKeymasterDevice& keymaster() { return *keymaster_; }
- const std::vector<sp<IKeymasterDevice>>& all_keymasters() { return all_keymasters_; }
uint32_t os_version() { return os_version_; }
uint32_t os_patch_level() { return os_patch_level_; }
@@ -209,18 +218,26 @@
KeyCharacteristics key_characteristics_;
OperationHandle op_handle_ = kOpHandleSentinel;
- private:
- sp<IKeymasterDevice> keymaster_;
- std::vector<sp<IKeymasterDevice>> all_keymasters_;
- uint32_t os_version_;
- uint32_t os_patch_level_;
+ static std::vector<std::string> build_params() {
+ auto params = android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor);
+ return params;
+ }
- SecurityLevel securityLevel_;
- hidl_string name_;
- hidl_string author_;
- string service_name_;
+ private:
+ sp<IKeymasterDevice> keymaster_;
+ uint32_t os_version_;
+ uint32_t os_patch_level_;
+
+ SecurityLevel securityLevel_;
+ hidl_string name_;
+ hidl_string author_;
};
+#define INSTANTIATE_KEYMASTER_HIDL_TEST(name) \
+ INSTANTIATE_TEST_SUITE_P(PerInstance, name, \
+ testing::ValuesIn(KeymasterHidlTest::build_params()), \
+ android::hardware::PrintInstanceNameToString)
+
} // namespace test
} // namespace V4_0
} // namespace keymaster
diff --git a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
index 693f4ae..bab1439 100644
--- a/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
+++ b/keymaster/4.0/vts/functional/VerificationTokenTest.cpp
@@ -185,10 +185,7 @@
memcmp(result1.token.mac.data(), result2.token.mac.data(), result1.token.mac.size()));
}
-INSTANTIATE_TEST_SUITE_P(
- PerInstance, VerificationTokenTest,
- testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor)),
- android::hardware::PrintInstanceNameToString);
+INSTANTIATE_KEYMASTER_HIDL_TEST(VerificationTokenTest);
} // namespace test
} // namespace V4_0
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 66132ad..6cbe4da 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 @@
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 @@
// 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 @@
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();
@@ -840,6 +846,8 @@
.Authorization(TAG_MIN_MAC_LENGTH, 128)));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(NewKeyGenerationTest);
+
typedef KeymasterHidlTest SigningOperationsTest;
/*
@@ -1509,6 +1517,8 @@
}
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(SigningOperationsTest);
+
typedef KeymasterHidlTest VerificationOperationsTest;
/*
@@ -1749,6 +1759,8 @@
CheckedDeleteKey(&verification_key);
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(VerificationOperationsTest);
+
typedef KeymasterHidlTest ExportKeyTest;
/*
@@ -1828,6 +1840,8 @@
EXPECT_EQ(ErrorCode::UNSUPPORTED_KEY_FORMAT, ExportKey(KeyFormat::RAW, &export_data));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(ExportKeyTest);
+
class ImportKeyTest : public KeymasterHidlTest {
public:
template <TagType tag_type, Tag tag, typename ValueT>
@@ -2093,6 +2107,8 @@
VerifyMessage(message, signature, AuthorizationSetBuilder().Digest(Digest::SHA_2_256));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(ImportKeyTest);
+
auto wrapped_key = hex2str(
"3082017902010004820100934bf94e2aa28a3f83c9f79297250262fbe3276b5a1c91159bbfa3ef8957aac84b59b30b"
"455a79c2973480823d8b3863c3deef4a8e243590268d80e18751a0e130f67ce6a1ace9f79b95e097474febc981195b"
@@ -2214,6 +2230,8 @@
.Padding(PaddingMode::RSA_OAEP)));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(ImportWrappedKeyTest);
+
typedef KeymasterHidlTest EncryptionOperationsTest;
/*
@@ -4111,6 +4129,8 @@
EXPECT_EQ(message, plaintext);
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(EncryptionOperationsTest);
+
typedef KeymasterHidlTest MaxOperationsTest;
/*
@@ -4166,6 +4186,8 @@
EXPECT_EQ(ErrorCode::KEY_MAX_OPS_EXCEEDED, Begin(KeyPurpose::SIGN, params));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(MaxOperationsTest);
+
typedef KeymasterHidlTest AddEntropyTest;
/*
@@ -4196,6 +4218,8 @@
EXPECT_EQ(ErrorCode::OK, keymaster().addRngEntropy(HidlBuf(string(2 * 1024, 'a'))));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(AddEntropyTest);
+
typedef KeymasterHidlTest AttestationTest;
/*
@@ -4373,6 +4397,8 @@
&cert_chain));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(AttestationTest);
+
typedef KeymasterHidlTest KeyDeletionTest;
/**
@@ -4478,6 +4504,8 @@
}
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(KeyDeletionTest);
+
using UpgradeKeyTest = KeymasterHidlTest;
/*
@@ -4497,6 +4525,8 @@
EXPECT_EQ(result, std::make_pair(ErrorCode::OK, HidlBuf()));
}
+INSTANTIATE_KEYMASTER_HIDL_TEST(UpgradeKeyTest);
+
using ClearOperationsTest = KeymasterHidlTest;
/*
@@ -4533,51 +4563,14 @@
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()
@@ -4586,7 +4579,7 @@
.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);
@@ -4597,71 +4590,22 @@
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();
}
-static const auto kKeymasterDeviceChoices =
- testing::ValuesIn(android::hardware::getAllHalInstanceNames(IKeymasterDevice::descriptor));
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, NewKeyGenerationTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, ImportKeyTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, ImportWrappedKeyTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, SigningOperationsTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, VerificationOperationsTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, ExportKeyTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, EncryptionOperationsTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, MaxOperationsTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, AddEntropyTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, AttestationTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, KeyDeletionTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
-
-INSTANTIATE_TEST_SUITE_P(PerInstance, TransportLimitTest, kKeymasterDeviceChoices,
- android::hardware::PrintInstanceNameToString);
+INSTANTIATE_KEYMASTER_HIDL_TEST(TransportLimitTest);
} // namespace test
} // namespace V4_0
diff --git a/keymaster/4.1/default/Android.bp b/keymaster/4.1/default/Android.bp
index b06878b..27297b9 100644
--- a/keymaster/4.1/default/Android.bp
+++ b/keymaster/4.1/default/Android.bp
@@ -31,6 +31,7 @@
"libhidlbase",
"libkeymaster4",
"libkeymaster41",
+ "libkeymaster4_1support",
"liblog",
"libutils",
],
diff --git a/keymaster/4.1/support/Android.bp b/keymaster/4.1/support/Android.bp
index 34b6108..bdd0ca8 100644
--- a/keymaster/4.1/support/Android.bp
+++ b/keymaster/4.1/support/Android.bp
@@ -22,11 +22,25 @@
"-Wextra",
"-Werror",
],
+ srcs: [
+ "attestation_record.cpp",
+ "Keymaster.cpp",
+ "Keymaster3.cpp",
+ "Keymaster4.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",
- ]
+ "libutils",
+ ],
+ export_shared_lib_headers: [
+ "android.hardware.keymaster@4.1",
+ "libkeymaster4support",
+ ],
}
diff --git a/keymaster/4.0/support/Keymaster.cpp b/keymaster/4.1/support/Keymaster.cpp
similarity index 85%
rename from keymaster/4.0/support/Keymaster.cpp
rename to keymaster/4.1/support/Keymaster.cpp
index f20f951..ea6604e 100644
--- a/keymaster/4.0/support/Keymaster.cpp
+++ b/keymaster/4.1/support/Keymaster.cpp
@@ -14,19 +14,18 @@
** limitations under the License.
*/
-#include <keymasterV4_0/Keymaster.h>
+#include <keymasterV4_1/Keymaster.h>
#include <iomanip>
#include <android-base/logging.h>
#include <android/hidl/manager/1.2/IServiceManager.h>
-#include <keymasterV4_0/Keymaster3.h>
-#include <keymasterV4_0/Keymaster4.h>
#include <keymasterV4_0/key_param_output.h>
#include <keymasterV4_0/keymaster_utils.h>
+#include <keymasterV4_1/Keymaster3.h>
+#include <keymasterV4_1/Keymaster4.h>
-namespace android {
-namespace hardware {
+namespace android::hardware {
template <class T>
std::ostream& operator<<(std::ostream& os, const hidl_vec<T>& vec) {
@@ -57,6 +56,7 @@
}
namespace keymaster {
+
namespace V4_0 {
std::ostream& operator<<(std::ostream& os, const HmacSharingParameters& params) {
@@ -66,7 +66,9 @@
return os;
}
-namespace support {
+} // namespace V4_0
+
+namespace V4_1::support {
using ::android::sp;
using ::android::hidl::manager::V1_2::IServiceManager;
@@ -140,14 +142,14 @@
}
static hidl_vec<HmacSharingParameters> getHmacParameters(
- const Keymaster::KeymasterSet& keymasters) {
+ const Keymaster::KeymasterSet& keymasters) {
std::vector<HmacSharingParameters> params_vec;
params_vec.reserve(keymasters.size());
for (auto& keymaster : keymasters) {
if (keymaster->halVersion().majorVersion < 4) continue;
auto rc = keymaster->getHmacSharingParameters([&](auto error, auto& params) {
- CHECK(error == ErrorCode::OK)
- << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
+ CHECK(error == V4_0::ErrorCode::OK)
+ << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
params_vec.push_back(params);
});
CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster
@@ -169,18 +171,18 @@
if (keymaster->halVersion().majorVersion < 4) continue;
LOG(DEBUG) << "Computing HMAC for " << *keymaster;
auto rc = keymaster->computeSharedHmac(
- params, [&](ErrorCode error, const hidl_vec<uint8_t>& curSharingCheck) {
- CHECK(error == ErrorCode::OK)
- << "Failed to get HMAC parameters from " << *keymaster << " error " << error;
- if (firstKeymaster) {
- sharingCheck = curSharingCheck;
- firstKeymaster = false;
- }
- if (curSharingCheck != sharingCheck)
- LOG(WARNING) << "HMAC computation failed for " << *keymaster //
- << " Expected: " << sharingCheck //
- << " got: " << curSharingCheck;
- });
+ params, [&](V4_0::ErrorCode error, const hidl_vec<uint8_t>& curSharingCheck) {
+ CHECK(error == V4_0::ErrorCode::OK) << "Failed to get HMAC parameters from "
+ << *keymaster << " error " << error;
+ if (firstKeymaster) {
+ sharingCheck = curSharingCheck;
+ firstKeymaster = false;
+ }
+ if (curSharingCheck != sharingCheck)
+ LOG(WARNING) << "HMAC computation failed for " << *keymaster //
+ << " Expected: " << sharingCheck //
+ << " got: " << curSharingCheck;
+ });
CHECK(rc.isOk()) << "Failed to communicate with " << *keymaster
<< " error: " << rc.description();
}
@@ -190,8 +192,6 @@
computeHmac(keymasters, getHmacParameters(keymasters));
}
-} // namespace support
-} // namespace V4_0
+} // namespace V4_1::support
} // namespace keymaster
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware
diff --git a/keymaster/4.0/support/Keymaster3.cpp b/keymaster/4.1/support/Keymaster3.cpp
similarity index 81%
rename from keymaster/4.0/support/Keymaster3.cpp
rename to keymaster/4.1/support/Keymaster3.cpp
index b2cdbd9..b665689 100644
--- a/keymaster/4.0/support/Keymaster3.cpp
+++ b/keymaster/4.1/support/Keymaster3.cpp
@@ -15,23 +15,19 @@
** limitations under the License.
*/
-#include <keymasterV4_0/Keymaster3.h>
+#include <keymasterV4_1/Keymaster3.h>
#include <android-base/logging.h>
#include <keymasterV4_0/keymaster_utils.h>
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
+namespace android::hardware::keymaster::V4_1::support {
using android::hardware::details::StatusOf;
namespace {
-ErrorCode convert(V3_0::ErrorCode error) {
- return static_cast<ErrorCode>(error);
+V4_0::ErrorCode convert(V3_0::ErrorCode error) {
+ return static_cast<V4_0::ErrorCode>(error);
}
V3_0::KeyPurpose convert(KeyPurpose purpose) {
@@ -53,7 +49,7 @@
KeyParameter convert(const V3_0::KeyParameter& param) {
KeyParameter converted;
- converted.tag = static_cast<Tag>(param.tag);
+ converted.tag = static_cast<V4_0::Tag>(param.tag);
static_assert(sizeof(converted.f) == sizeof(param.f), "This function assumes sizes match");
memcpy(&converted.f, ¶m.f, sizeof(param.f));
converted.blob = param.blob;
@@ -89,7 +85,7 @@
converted[i] = convert(params[i]);
}
converted[params.size()].tag = V3_0::Tag::AUTH_TOKEN;
- converted[params.size()].blob = authToken2HidlVec(authToken);
+ converted[params.size()].blob = V4_0::support::authToken2HidlVec(authToken);
return converted;
}
@@ -107,16 +103,19 @@
if (haveVersion_) return;
auto rc = km3_dev_->getHardwareFeatures(
- [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
- bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName,
- const hidl_string& keymasterAuthorName) {
- version_ = {keymasterName, keymasterAuthorName, 0 /* major version, filled below */,
- isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE,
- supportsEllipticCurve};
- supportsSymmetricCryptography_ = supportsSymmetricCryptography;
- supportsAttestation_ = supportsAttestation;
- supportsAllDigests_ = supportsAllDigests;
- });
+ [&](bool isSecure, bool supportsEllipticCurve, bool supportsSymmetricCryptography,
+ bool supportsAttestation, bool supportsAllDigests, const hidl_string& keymasterName,
+ const hidl_string& keymasterAuthorName) {
+ version_ = {keymasterName,
+ keymasterAuthorName,
+ 0 /* major version, filled below */,
+ 0 /* minor version */,
+ isSecure ? SecurityLevel::TRUSTED_ENVIRONMENT : SecurityLevel::SOFTWARE,
+ supportsEllipticCurve};
+ supportsSymmetricCryptography_ = supportsSymmetricCryptography;
+ supportsAttestation_ = supportsAttestation;
+ supportsAllDigests_ = supportsAllDigests;
+ });
CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware features";
@@ -139,10 +138,10 @@
return Void();
}
-Return<ErrorCode> Keymaster3::addRngEntropy(const hidl_vec<uint8_t>& data) {
+Return<V4_0::ErrorCode> Keymaster3::addRngEntropy(const hidl_vec<uint8_t>& data) {
auto rc = km3_dev_->addRngEntropy(data);
if (!rc.isOk()) {
- return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+ return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
}
return convert(rc);
}
@@ -215,21 +214,21 @@
return rc;
}
-Return<ErrorCode> Keymaster3::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
+Return<V4_0::ErrorCode> Keymaster3::deleteKey(const hidl_vec<uint8_t>& keyBlob) {
auto rc = km3_dev_->deleteKey(keyBlob);
- if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+ if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
return convert(rc);
}
-Return<ErrorCode> Keymaster3::deleteAllKeys() {
+Return<V4_0::ErrorCode> Keymaster3::deleteAllKeys() {
auto rc = km3_dev_->deleteAllKeys();
- if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+ if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
return convert(rc);
}
-Return<ErrorCode> Keymaster3::destroyAttestationIds() {
+Return<V4_0::ErrorCode> Keymaster3::destroyAttestationIds() {
auto rc = km3_dev_->destroyAttestationIds();
- if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+ if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
return convert(rc);
}
@@ -242,7 +241,7 @@
};
auto rc =
- km3_dev_->begin(convert(purpose), key, convertAndAddAuthToken(inParams, authToken), cb);
+ km3_dev_->begin(convert(purpose), key, convertAndAddAuthToken(inParams, authToken), cb);
rc.isOk(); // move ctor prereq
return rc;
}
@@ -256,8 +255,8 @@
_hidl_cb(convert(error), inputConsumed, convert(outParams), output);
};
- auto rc =
- km3_dev_->update(operationHandle, convertAndAddAuthToken(inParams, authToken), input, cb);
+ auto rc = km3_dev_->update(operationHandle, convertAndAddAuthToken(inParams, authToken), input,
+ cb);
rc.isOk(); // move ctor prereq
return rc;
}
@@ -278,14 +277,10 @@
return rc;
}
-Return<ErrorCode> Keymaster3::abort(uint64_t operationHandle) {
+Return<V4_0::ErrorCode> Keymaster3::abort(uint64_t operationHandle) {
auto rc = km3_dev_->abort(operationHandle);
- if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, ErrorCode>(rc);
+ if (!rc.isOk()) return StatusOf<V3_0::ErrorCode, V4_0::ErrorCode>(rc);
return convert(rc);
}
-} // namespace support
-} // namespace V4_0
-} // namespace keymaster
-} // namespace hardware
-} // namespace android
+} // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/Keymaster4.cpp b/keymaster/4.1/support/Keymaster4.cpp
new file mode 100644
index 0000000..33f4bb1
--- /dev/null
+++ b/keymaster/4.1/support/Keymaster4.cpp
@@ -0,0 +1,41 @@
+/*
+** Copyright 2017, 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/Keymaster4.h>
+
+#include <android-base/logging.h>
+
+namespace android::hardware::keymaster::V4_1::support {
+
+void Keymaster4::getVersionIfNeeded() {
+ if (haveVersion_) return;
+
+ auto rc = km4_0_dev_->getHardwareInfo([&](SecurityLevel securityLevel,
+ const hidl_string& keymasterName,
+ const hidl_string& authorName) {
+ version_ = {keymasterName,
+ authorName,
+ 4 /* major version */,
+ static_cast<uint8_t>((km4_1_dev_) ? 1 : 0) /* minor version */,
+ securityLevel,
+ true /* supportsEc */};
+ haveVersion_ = true;
+ });
+
+ CHECK(rc.isOk()) << "Got error " << rc.description() << " trying to get hardware info";
+}
+
+} // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/OWNERS b/keymaster/4.1/support/OWNERS
new file mode 100644
index 0000000..a9efe66
--- /dev/null
+++ b/keymaster/4.1/support/OWNERS
@@ -0,0 +1,3 @@
+jdanis@google.com
+swillden@google.com
+jbires@google.com
diff --git a/keymaster/4.1/support/attestation_record.cpp b/keymaster/4.1/support/attestation_record.cpp
new file mode 100644
index 0000000..9eab1db
--- /dev/null
+++ b/keymaster/4.1/support/attestation_record.cpp
@@ -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
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster.h
similarity index 73%
rename from keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
rename to keymaster/4.1/support/include/keymasterV4_1/Keymaster.h
index ad83f17..1f49e18 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster.h
@@ -15,28 +15,28 @@
** limitations under the License.
*/
-#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
-#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
-
-#include <android/hardware/keymaster/4.0/IKeymasterDevice.h>
+#pragma once
#include <memory>
#include <vector>
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
+#include <android/hardware/keymaster/4.1/IKeymasterDevice.h>
+#include <keymasterV4_1/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1::support {
/**
- * Keymaster abstracts the underlying V4_0::IKeymasterDevice. There is one implementation
- * (Keymaster4) which is a trivial passthrough and one that wraps a V3_0::IKeymasterDevice.
+ * Keymaster abstracts the underlying V4_1::IKeymasterDevice. There are two implementations,
+ * Keymaster3 which wraps a V3_0::IKeymasterDevice and Keymaster4, which wraps either a
+ * V4_0::IKeymasterDevice or a V4_1::IKeymasterDevice. There is a V3_0::IKeymasterDevice
+ * implementation that is used to wrap pre-HIDL keymaster implementations, and Keymaster3 will wrap
+ * that.
*
* The reason for adding this additional layer, rather than simply using the latest HAL directly and
* subclassing it to wrap any older HAL, is because this provides a place to put additional methods
* which clients can use when they need to distinguish between different underlying HAL versions,
- * while still having to use only the latest interface.
+ * while still having to use only the latest interface. Plus it's a handy place to keep some
+ * convenience methods.
*/
class Keymaster : public IKeymasterDevice {
public:
@@ -50,12 +50,14 @@
hidl_string keymasterName;
hidl_string authorName;
uint8_t majorVersion;
+ uint8_t minorVersion;
SecurityLevel securityLevel;
bool supportsEc;
bool operator>(const VersionResult& other) const {
- auto lhs = std::tie(securityLevel, majorVersion, supportsEc);
- auto rhs = std::tie(other.securityLevel, other.majorVersion, other.supportsEc);
+ auto lhs = std::tie(securityLevel, majorVersion, minorVersion, supportsEc);
+ auto rhs = std::tie(other.securityLevel, other.majorVersion, other.minorVersion,
+ other.supportsEc);
return lhs > rhs;
}
};
@@ -69,6 +71,9 @@
* There are no side effects otherwise.
*/
void logIfKeymasterVendorError(ErrorCode ec) const;
+ void logIfKeymasterVendorError(V4_0::ErrorCode ec) const {
+ logIfKeymasterVendorError(static_cast<ErrorCode>(ec));
+ }
/**
* Returns all available Keymaster3 and Keymaster4 instances, in order of most secure to least
@@ -93,10 +98,4 @@
std::ostream& operator<<(std::ostream& os, const Keymaster& keymaster);
-} // namespace support
-} // namespace V4_0
-} // namespace keymaster
-} // namespace hardware
-} // namespace android
-
-#endif // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_H_
+} // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
similarity index 72%
rename from keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
rename to keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
index c40be7c..c201e8c 100644
--- a/keymaster/4.0/support/include/keymasterV4_0/Keymaster3.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster3.h
@@ -1,5 +1,4 @@
/*
- **
** Copyright 2017, The Android Open Source Project
**
** Licensed under the Apache License, Version 2.0 (the "License");
@@ -15,18 +14,14 @@
** limitations under the License.
*/
-#ifndef HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
-#define HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+#pragma once
#include <android/hardware/keymaster/3.0/IKeymasterDevice.h>
#include "Keymaster.h"
+#include "Operation.h"
-namespace android {
-namespace hardware {
-namespace keymaster {
-namespace V4_0 {
-namespace support {
+namespace android::hardware::keymaster::V4_1::support {
using IKeymaster3Device = ::android::hardware::keymaster::V3_0::IKeymasterDevice;
@@ -38,8 +33,10 @@
using ::android::hardware::details::return_status;
class Keymaster3 : public Keymaster {
- public:
+ public:
+ // This definition is used for device enumeration.
using WrappedIKeymasterDevice = IKeymaster3Device;
+
Keymaster3(sp<IKeymaster3Device> km3_dev, const hidl_string& instanceName)
: Keymaster(IKeymaster3Device::descriptor, instanceName),
km3_dev_(km3_dev),
@@ -53,24 +50,24 @@
Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb);
Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
- _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+ _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {});
return Void();
}
Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>&,
computeSharedHmac_cb _hidl_cb) override {
- _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+ _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {});
return Void();
}
Return<void> verifyAuthorization(uint64_t, const hidl_vec<KeyParameter>&,
const HardwareAuthToken&,
verifyAuthorization_cb _hidl_cb) override {
- _hidl_cb(ErrorCode::UNIMPLEMENTED, {});
+ _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {});
return Void();
}
- Return<ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
+ Return<V4_0::ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override;
Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
generateKey_cb _hidl_cb) override;
Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
@@ -86,7 +83,7 @@
const hidl_vec<KeyParameter>& /* unwrappingParams */,
uint64_t /* passwordSid */, uint64_t /* biometricSid */,
importWrappedKey_cb _hidl_cb) {
- _hidl_cb(ErrorCode::UNIMPLEMENTED, {}, {});
+ _hidl_cb(V4_0::ErrorCode::UNIMPLEMENTED, {}, {});
return Void();
}
@@ -99,9 +96,9 @@
Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
const hidl_vec<KeyParameter>& upgradeParams,
upgradeKey_cb _hidl_cb) override;
- Return<ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
- Return<ErrorCode> deleteAllKeys() override;
- Return<ErrorCode> destroyAttestationIds() override;
+ Return<V4_0::ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override;
+ Return<V4_0::ErrorCode> deleteAllKeys() override;
+ Return<V4_0::ErrorCode> destroyAttestationIds() override;
Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
begin_cb _hidl_cb) override;
@@ -112,9 +109,31 @@
const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
const HardwareAuthToken& authToken,
const VerificationToken& verificationToken, finish_cb _hidl_cb) override;
- Return<ErrorCode> abort(uint64_t operationHandle) override;
+ Return<V4_0::ErrorCode> abort(uint64_t operationHandle) override;
- private:
+ /**********************************
+ * V4_1::IKeymasterDevice methods *
+ *********************************/
+
+ Return<ErrorCode> deviceLocked(bool /* passwordOnly */,
+ const VerificationToken& /* verificationToken */) override {
+ return ErrorCode::UNIMPLEMENTED;
+ }
+
+ Return<ErrorCode> earlyBootEnded() override { return ErrorCode::UNIMPLEMENTED; }
+
+ Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+ beginOp_cb _hidl_cb) override {
+ return begin(purpose, keyBlob, inParams, authToken,
+ [&_hidl_cb](V4_0::ErrorCode errorCode, const hidl_vec<KeyParameter>& outParams,
+ OperationHandle operationHandle) {
+ _hidl_cb(static_cast<ErrorCode>(errorCode), outParams,
+ new Operation(operationHandle));
+ });
+ }
+
+ private:
void getVersionIfNeeded();
sp<IKeymaster3Device> km3_dev_;
@@ -126,10 +145,4 @@
bool supportsAllDigests_;
};
-} // namespace support
-} // namespace V4_0
-} // namespace keymaster
-} // namespace hardware
-} // namespace android
-
-#endif // HARDWARE_INTERFACES_KEYMASTER_40_SUPPORT_KEYMASTER_3_H_
+} // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
new file mode 100644
index 0000000..6d74d98
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/Keymaster4.h
@@ -0,0 +1,197 @@
+/*
+ ** 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 "Keymaster.h"
+#include "Operation.h"
+
+namespace android::hardware::keymaster::V4_1::support {
+
+using android::sp;
+
+/**
+ * This class can wrap either a V4_0 or V4_1 IKeymasterDevice.
+ */
+class Keymaster4 : public Keymaster {
+ public:
+ // This definition is used for device enumeration; enumerating 4.0 devices will also
+ // enumerate 4.1. devices.
+ using WrappedIKeymasterDevice = V4_0::IKeymasterDevice;
+
+ Keymaster4(sp<V4_1::IKeymasterDevice> km4_1_dev, const hidl_string& instanceName)
+ : Keymaster(V4_1::IKeymasterDevice::descriptor, instanceName),
+ haveVersion_(false),
+ km4_0_dev_(km4_1_dev),
+ km4_1_dev_(km4_1_dev) {}
+
+ Keymaster4(sp<V4_0::IKeymasterDevice> km4_0_dev, const hidl_string& instanceName)
+ : Keymaster(V4_1::IKeymasterDevice::descriptor, instanceName),
+ haveVersion_(false),
+ km4_0_dev_(km4_0_dev),
+ km4_1_dev_() {}
+
+ const VersionResult& halVersion() const override {
+ const_cast<Keymaster4*>(this)->getVersionIfNeeded();
+ return version_;
+ }
+
+ /**********************************
+ * V4_0::IKeymasterDevice methods *
+ *********************************/
+
+ Return<void> getHardwareInfo(getHardwareInfo_cb _hidl_cb) override {
+ return km4_0_dev_->getHardwareInfo(_hidl_cb);
+ }
+
+ Return<void> getHmacSharingParameters(getHmacSharingParameters_cb _hidl_cb) override {
+ return km4_0_dev_->getHmacSharingParameters(_hidl_cb);
+ }
+
+ Return<void> computeSharedHmac(const hidl_vec<HmacSharingParameters>& params,
+ computeSharedHmac_cb _hidl_cb) override {
+ return km4_0_dev_->computeSharedHmac(params, _hidl_cb);
+ }
+
+ Return<void> verifyAuthorization(uint64_t operationHandle, const hidl_vec<KeyParameter>& params,
+ const HardwareAuthToken& authToken,
+ verifyAuthorization_cb _hidl_cb) override {
+ return km4_0_dev_->verifyAuthorization(operationHandle, params, authToken, _hidl_cb);
+ }
+
+ Return<V4_0::ErrorCode> addRngEntropy(const hidl_vec<uint8_t>& data) override {
+ return km4_0_dev_->addRngEntropy(data);
+ }
+
+ Return<void> generateKey(const hidl_vec<KeyParameter>& keyParams,
+ generateKey_cb _hidl_cb) override {
+ return km4_0_dev_->generateKey(keyParams, _hidl_cb);
+ }
+
+ Return<void> getKeyCharacteristics(const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId,
+ const hidl_vec<uint8_t>& appData,
+ getKeyCharacteristics_cb _hidl_cb) override {
+ return km4_0_dev_->getKeyCharacteristics(keyBlob, clientId, appData, _hidl_cb);
+ }
+
+ Return<void> importKey(const hidl_vec<KeyParameter>& params, KeyFormat keyFormat,
+ const hidl_vec<uint8_t>& keyData, importKey_cb _hidl_cb) override {
+ return km4_0_dev_->importKey(params, keyFormat, keyData, _hidl_cb);
+ }
+
+ Return<void> importWrappedKey(const hidl_vec<uint8_t>& wrappedKeyData,
+ const hidl_vec<uint8_t>& wrappingKeyBlob,
+ const hidl_vec<uint8_t>& maskingKey,
+ const hidl_vec<KeyParameter>& unwrappingParams,
+ uint64_t passwordSid, uint64_t biometricSid,
+ importWrappedKey_cb _hidl_cb) {
+ return km4_0_dev_->importWrappedKey(wrappedKeyData, wrappingKeyBlob, maskingKey,
+ unwrappingParams, passwordSid, biometricSid, _hidl_cb);
+ }
+
+ Return<void> exportKey(KeyFormat exportFormat, const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<uint8_t>& clientId, const hidl_vec<uint8_t>& appData,
+ exportKey_cb _hidl_cb) override {
+ return km4_0_dev_->exportKey(exportFormat, keyBlob, clientId, appData, _hidl_cb);
+ }
+
+ Return<void> attestKey(const hidl_vec<uint8_t>& keyToAttest,
+ const hidl_vec<KeyParameter>& attestParams,
+ attestKey_cb _hidl_cb) override {
+ return km4_0_dev_->attestKey(keyToAttest, attestParams, _hidl_cb);
+ }
+
+ Return<void> upgradeKey(const hidl_vec<uint8_t>& keyBlobToUpgrade,
+ const hidl_vec<KeyParameter>& upgradeParams,
+ upgradeKey_cb _hidl_cb) override {
+ return km4_0_dev_->upgradeKey(keyBlobToUpgrade, upgradeParams, _hidl_cb);
+ }
+
+ Return<V4_0::ErrorCode> deleteKey(const hidl_vec<uint8_t>& keyBlob) override {
+ return km4_0_dev_->deleteKey(keyBlob);
+ }
+
+ Return<V4_0::ErrorCode> deleteAllKeys() override { return km4_0_dev_->deleteAllKeys(); }
+
+ Return<V4_0::ErrorCode> destroyAttestationIds() override {
+ return km4_0_dev_->destroyAttestationIds();
+ }
+
+ Return<void> begin(KeyPurpose purpose, const hidl_vec<uint8_t>& key,
+ const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+ begin_cb _hidl_cb) override {
+ return km4_0_dev_->begin(purpose, key, inParams, authToken, _hidl_cb);
+ }
+
+ Return<void> update(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, const HardwareAuthToken& authToken,
+ const VerificationToken& verificationToken, update_cb _hidl_cb) override {
+ return km4_0_dev_->update(operationHandle, inParams, input, authToken, verificationToken,
+ _hidl_cb);
+ }
+
+ Return<void> finish(uint64_t operationHandle, const hidl_vec<KeyParameter>& inParams,
+ const hidl_vec<uint8_t>& input, const hidl_vec<uint8_t>& signature,
+ const HardwareAuthToken& authToken,
+ const VerificationToken& verificationToken, finish_cb _hidl_cb) override {
+ return km4_0_dev_->finish(operationHandle, inParams, input, signature, authToken,
+ verificationToken, _hidl_cb);
+ }
+
+ Return<V4_0::ErrorCode> abort(uint64_t operationHandle) override {
+ return km4_0_dev_->abort(operationHandle);
+ }
+
+ /**********************************
+ * V4_1::IKeymasterDevice methods *
+ *********************************/
+
+ Return<ErrorCode> deviceLocked(bool passwordOnly,
+ const VerificationToken& verificationToken) override {
+ if (km4_1_dev_) return km4_1_dev_->deviceLocked(passwordOnly, verificationToken);
+ return ErrorCode::UNIMPLEMENTED;
+ }
+
+ Return<ErrorCode> earlyBootEnded() override {
+ if (km4_1_dev_) return km4_1_dev_->earlyBootEnded();
+ return ErrorCode::UNIMPLEMENTED;
+ }
+
+ Return<void> beginOp(KeyPurpose purpose, const hidl_vec<uint8_t>& keyBlob,
+ const hidl_vec<KeyParameter>& inParams, const HardwareAuthToken& authToken,
+ beginOp_cb _hidl_cb) override {
+ if (km4_1_dev_) return km4_1_dev_->beginOp(purpose, keyBlob, inParams, authToken, _hidl_cb);
+
+ return km4_0_dev_->begin(
+ purpose, keyBlob, inParams, authToken,
+ [&_hidl_cb](V4_0::ErrorCode errorCode, const hidl_vec<KeyParameter>& outParams,
+ OperationHandle operationHandle) {
+ _hidl_cb(static_cast<ErrorCode>(errorCode), outParams,
+ new Operation(operationHandle));
+ });
+ }
+
+ private:
+ void getVersionIfNeeded();
+
+ bool haveVersion_;
+ VersionResult version_;
+ sp<V4_0::IKeymasterDevice> km4_0_dev_;
+ sp<V4_1::IKeymasterDevice> km4_1_dev_;
+}; // namespace android::hardware::keymaster::V4_1::support
+
+} // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/support/include/keymasterV4_1/Operation.h b/keymaster/4.1/support/include/keymasterV4_1/Operation.h
new file mode 100644
index 0000000..902d49a
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/Operation.h
@@ -0,0 +1,38 @@
+/*
+ ** 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/IOperation.h>
+
+#include <keymasterV4_1/keymaster_tags.h>
+
+namespace android::hardware::keymaster::V4_1::support {
+
+class Operation : public IOperation {
+ public:
+ Operation(OperationHandle handle) : handle_(handle) {}
+
+ Return<void> getOperationChallenge(getOperationChallenge_cb _hidl_cb) override {
+ _hidl_cb(V4_1::ErrorCode::OK, handle_);
+ return Void();
+ }
+
+ private:
+ OperationHandle handle_;
+};
+
+} // namespace android::hardware::keymaster::V4_1::support
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 0000000..b543bdd
--- /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 <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
diff --git a/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
index afc0eaf..01605b7 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/authorization_set.h
@@ -14,8 +14,7 @@
* limitations under the License.
*/
-#ifndef HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
-#define HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
+#pragma once
#include <keymasterV4_0/authorization_set.h>
@@ -28,5 +27,3 @@
using V4_0::KeyParameter;
} // namespace android::hardware::keymaster::V4_1
-
-#endif // HARDWARE_INTERFACES_KEYMASTER_V4_1_SUPPORT_INCLUDE_AUTHORIZATION_SET_H_
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 6ffe8e1..c5ce950 100644
--- a/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_tags.h
@@ -23,16 +23,26 @@
namespace android::hardware::keymaster::V4_1 {
+using V4_0::Algorithm;
using V4_0::BlockMode;
using V4_0::Digest;
using V4_0::EcCurve;
-using V4_0::ErrorCode;
+using V4_0::HardwareAuthenticatorType;
using V4_0::HardwareAuthToken;
+using V4_0::HmacSharingParameters;
+using V4_0::KeyBlobUsageRequirements;
+using V4_0::KeyCharacteristics;
+using V4_0::KeyFormat;
+using V4_0::KeyOrigin;
using V4_0::KeyParameter;
+using V4_0::KeyPurpose;
+using V4_0::OperationHandle;
using V4_0::PaddingMode;
+using V4_0::SecurityLevel;
using V4_0::TagType;
using V4_0::VerificationToken;
+using V4_0::NullOr;
using V4_0::TypedTag;
using V4_0::TAG_ACTIVE_DATETIME;
diff --git a/keymaster/4.1/support/include/keymasterV4_1/keymaster_utils.h b/keymaster/4.1/support/include/keymasterV4_1/keymaster_utils.h
new file mode 100644
index 0000000..2e28002
--- /dev/null
+++ b/keymaster/4.1/support/include/keymasterV4_1/keymaster_utils.h
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+#pragma once
+
+#include <keymasterV4_0/keymaster_utils.h>
+
+namespace android::hardware::keymaster::V4_1::support {
+
+using V4_0::support::blob2hidlVec;
+using V4_0::support::hidlVec2AuthToken;
+
+} // namespace android::hardware::keymaster::V4_1::support
diff --git a/keymaster/4.1/vts/functional/Android.bp b/keymaster/4.1/vts/functional/Android.bp
index f5a0c9c..c2d7fa3 100644
--- a/keymaster/4.1/vts/functional/Android.bp
+++ b/keymaster/4.1/vts/functional/Android.bp
@@ -19,12 +19,24 @@
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",
],
- test_suites: ["vts-core"],
+ cflags: [
+ "-Wall",
+ "-O0",
+ ],
+ test_suites: [
+ "general-tests",
+ "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 0000000..7ea3275
--- /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 <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
diff --git a/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp b/keymaster/4.1/vts/functional/EarlyBootKeyTest.cpp
index 4a19010..a26c688 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 <keymasterV4_1/authorization_set.h>
+
namespace android::hardware::keymaster::V4_1::test {
-// TODO(swillden): Put tests here.
+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
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 0000000..efedf28
--- /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<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
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 0000000..6332c43
--- /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 <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
diff --git a/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp b/keymaster/4.1/vts/functional/UnlockedDeviceRequiredTest.cpp
new file mode 100644
index 0000000..671bbbf
--- /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 <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
diff --git a/tv/tuner/1.0/types.hal b/tv/tuner/1.0/types.hal
index 3afe37d..2eaab36 100644
--- a/tv/tuner/1.0/types.hal
+++ b/tv/tuner/1.0/types.hal
@@ -1131,9 +1131,14 @@
@export
enum FrontendAnalogType : uint32_t {
UNDEFINED = 0,
- PAL = 1 << 0,
- SECAM = 1 << 1,
- NTSC = 1 << 2,
+ AUTO = 1 << 0,
+ PAL = 1 << 1,
+ PAL_M = 1 << 2,
+ PAL_N = 1 << 3,
+ PAL_60 = 1 << 4,
+ NTSC = 1 << 5,
+ NTSC_443 = 1 << 6,
+ SECAM = 1 << 7,
};
/**
@@ -1142,23 +1147,24 @@
@export
enum FrontendAnalogSifStandard : uint32_t {
UNDEFINED = 0,
- BG = 1 << 0,
- BG_A2 = 1 << 1,
- BG_NICAM = 1 << 2,
- I = 1 << 3,
- DK = 1 << 4,
- DK1 = 1 << 5,
- DK2 = 1 << 6,
- DK3 = 1 << 7,
- DK_NICAM = 1 << 8,
- L = 1 << 9,
- M = 1 << 10,
- M_BTSC = 1 << 11,
- M_A2 = 1 << 12,
- M_EIA_J = 1 << 13,
- I_NICAM = 1 << 14,
- L_NICAM = 1 << 15,
- L_PRIME = 1 << 16,
+ AUTO = 1 << 0,
+ BG = 1 << 1,
+ BG_A2 = 1 << 2,
+ BG_NICAM = 1 << 3,
+ I = 1 << 4,
+ DK = 1 << 5,
+ DK1_A2 = 1 << 6,
+ DK2_A2 = 1 << 7,
+ DK3_A2 = 1 << 8,
+ DK_NICAM = 1 << 9,
+ L = 1 << 10,
+ M = 1 << 11,
+ M_BTSC = 1 << 12,
+ M_A2 = 1 << 13,
+ M_EIAJ = 1 << 14,
+ I_NICAM = 1 << 15,
+ L_NICAM = 1 << 16,
+ L_PRIME = 1 << 17,
};
/**