Merge "Strictly enforce DeviceInfo entries." am: 6f135a7a19
am: 52ac82b75d
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/2503517 Change-Id: Id43e994b9c7cad078270118beee00180dc5cee42 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
commit
bf7fc8196d
1 changed files with 60 additions and 11 deletions
|
@ -22,6 +22,7 @@
|
||||||
#include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
|
#include "aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.h"
|
||||||
|
|
||||||
#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
|
#include <aidl/android/hardware/security/keymint/RpcHardwareInfo.h>
|
||||||
|
#include <android-base/macros.h>
|
||||||
#include <android-base/properties.h>
|
#include <android-base/properties.h>
|
||||||
#include <cppbor.h>
|
#include <cppbor.h>
|
||||||
#include <hwtrust/hwtrust.h>
|
#include <hwtrust/hwtrust.h>
|
||||||
|
@ -43,6 +44,7 @@ constexpr uint32_t kBccPayloadSubject = 2;
|
||||||
constexpr int32_t kBccPayloadSubjPubKey = -4670552;
|
constexpr int32_t kBccPayloadSubjPubKey = -4670552;
|
||||||
constexpr int32_t kBccPayloadKeyUsage = -4670553;
|
constexpr int32_t kBccPayloadKeyUsage = -4670553;
|
||||||
constexpr int kP256AffinePointSize = 32;
|
constexpr int kP256AffinePointSize = 32;
|
||||||
|
constexpr uint32_t kNumTeeDeviceInfoEntries = 14;
|
||||||
|
|
||||||
using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
|
using EC_KEY_Ptr = bssl::UniquePtr<EC_KEY>;
|
||||||
using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
|
using EVP_PKEY_Ptr = bssl::UniquePtr<EVP_PKEY>;
|
||||||
|
@ -388,6 +390,11 @@ std::string checkMapEntry(bool isFactory, const cppbor::Map& devInfo, cppbor::Ma
|
||||||
return entryName + " has an invalid value.\n";
|
return entryName + " has an invalid value.\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isTeeDeviceInfo(const cppbor::Map& devInfo) {
|
||||||
|
return devInfo.get("security_level") && devInfo.get("security_level")->asTstr() &&
|
||||||
|
devInfo.get("security_level")->asTstr()->value() == "tee";
|
||||||
|
}
|
||||||
|
|
||||||
ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
|
ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
|
||||||
const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
|
const std::vector<uint8_t>& deviceInfoBytes, IRemotelyProvisionedComponent* provisionable,
|
||||||
bool isFactory) {
|
bool isFactory) {
|
||||||
|
@ -396,6 +403,21 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
|
||||||
const cppbor::Array kValidSecurityLevels = {"tee", "strongbox"};
|
const cppbor::Array kValidSecurityLevels = {"tee", "strongbox"};
|
||||||
const cppbor::Array kValidAttIdStates = {"locked", "open"};
|
const cppbor::Array kValidAttIdStates = {"locked", "open"};
|
||||||
const cppbor::Array kValidFused = {0, 1};
|
const cppbor::Array kValidFused = {0, 1};
|
||||||
|
constexpr std::array<std::string_view, kNumTeeDeviceInfoEntries> kDeviceInfoKeys = {
|
||||||
|
"brand",
|
||||||
|
"manufacturer",
|
||||||
|
"product",
|
||||||
|
"model",
|
||||||
|
"device",
|
||||||
|
"vb_state",
|
||||||
|
"bootloader_state",
|
||||||
|
"vbmeta_digest",
|
||||||
|
"os_version",
|
||||||
|
"system_patch_level",
|
||||||
|
"boot_patch_level",
|
||||||
|
"vendor_patch_level",
|
||||||
|
"security_level",
|
||||||
|
"fused"};
|
||||||
|
|
||||||
struct AttestationIdEntry {
|
struct AttestationIdEntry {
|
||||||
const char* id;
|
const char* id;
|
||||||
|
@ -439,20 +461,48 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string error;
|
std::string error;
|
||||||
|
std::string tmp;
|
||||||
|
std::set<std::string_view> previousKeys;
|
||||||
switch (info.versionNumber) {
|
switch (info.versionNumber) {
|
||||||
case 3:
|
case 3:
|
||||||
|
if (isTeeDeviceInfo(*parsed) && parsed->size() != kNumTeeDeviceInfoEntries) {
|
||||||
|
error += fmt::format(
|
||||||
|
"Err: Incorrect number of device info entries. Expected {} but got"
|
||||||
|
"{}\n",
|
||||||
|
kNumTeeDeviceInfoEntries, parsed->size());
|
||||||
|
}
|
||||||
|
// TEE IRPC instances require all entries to be present in DeviceInfo. Non-TEE instances
|
||||||
|
// may omit `os_version`
|
||||||
|
if (!isTeeDeviceInfo(*parsed) && (parsed->size() != kNumTeeDeviceInfoEntries ||
|
||||||
|
parsed->size() != kNumTeeDeviceInfoEntries - 1)) {
|
||||||
|
error += fmt::format(
|
||||||
|
"Err: Incorrect number of device info entries. Expected {} or {} but got"
|
||||||
|
"{}\n",
|
||||||
|
kNumTeeDeviceInfoEntries - 1, kNumTeeDeviceInfoEntries, parsed->size());
|
||||||
|
}
|
||||||
|
for (auto& [key, _] : *parsed) {
|
||||||
|
const std::string& keyValue = key->asTstr()->value();
|
||||||
|
if (!previousKeys.insert(keyValue).second) {
|
||||||
|
error += "Err: Duplicate device info entry: <" + keyValue + ">,\n";
|
||||||
|
}
|
||||||
|
if (std::find(kDeviceInfoKeys.begin(), kDeviceInfoKeys.end(), keyValue) ==
|
||||||
|
kDeviceInfoKeys.end()) {
|
||||||
|
error += "Err: Unrecognized key entry: <" + key->asTstr()->value() + ">,\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FALLTHROUGH_INTENDED;
|
||||||
case 2:
|
case 2:
|
||||||
for (const auto& entry : kAttestationIdEntrySet) {
|
for (const auto& entry : kAttestationIdEntrySet) {
|
||||||
error += checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
|
tmp = checkMapEntry(isFactory && !entry.alwaysValidate, *parsed, cppbor::TSTR,
|
||||||
entry.id);
|
entry.id);
|
||||||
}
|
}
|
||||||
if (!error.empty()) {
|
if (!tmp.empty()) {
|
||||||
return error +
|
error += tmp +
|
||||||
"Attestation IDs are missing or malprovisioned. If this test is being\n"
|
"Attestation IDs are missing or malprovisioned. If this test is being\n"
|
||||||
"run against an early proto or EVT build, this error is probably WAI\n"
|
"run against an early proto or EVT build, this error is probably WAI\n"
|
||||||
"and indicates that Device IDs were not provisioned in the factory. If\n"
|
"and indicates that Device IDs were not provisioned in the factory. If\n"
|
||||||
"this error is returned on a DVT or later build revision, then\n"
|
"this error is returned on a DVT or later build revision, then\n"
|
||||||
"something is likely wrong with the factory provisioning process.";
|
"something is likely wrong with the factory provisioning process.";
|
||||||
}
|
}
|
||||||
// TODO: Refactor the KeyMint code that validates these fields and include it here.
|
// TODO: Refactor the KeyMint code that validates these fields and include it here.
|
||||||
error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "vb_state", kValidVbStates);
|
error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "vb_state", kValidVbStates);
|
||||||
|
@ -465,8 +515,7 @@ ErrMsgOr<std::unique_ptr<cppbor::Map>> parseAndValidateDeviceInfo(
|
||||||
error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "fused", kValidFused);
|
error += checkMapEntry(isFactory, *parsed, cppbor::UINT, "fused", kValidFused);
|
||||||
error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
|
error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "security_level",
|
||||||
kValidSecurityLevels);
|
kValidSecurityLevels);
|
||||||
if (parsed->get("security_level") && parsed->get("security_level")->asTstr() &&
|
if (isTeeDeviceInfo(*parsed)) {
|
||||||
parsed->get("security_level")->asTstr()->value() == "tee") {
|
|
||||||
error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "os_version");
|
error += checkMapEntry(isFactory, *parsed, cppbor::TSTR, "os_version");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue