mirror of
https://github.com/Evolution-X/hardware_interfaces
synced 2026-02-01 16:50:18 +00:00
Merge "Add basic testing for KeyMint certs." am: 1ddde5e97e
Original change: https://android-review.googlesource.com/c/platform/hardware/interfaces/+/1533200 MUST ONLY BE SUBMITTED BY AUTOMERGER Change-Id: Ife12e342627db1717b3502eddee5d0b56584016e
This commit is contained in:
@@ -37,7 +37,7 @@ using std::optional;
|
||||
os << "(Empty)" << ::std::endl;
|
||||
else {
|
||||
os << "\n";
|
||||
for (size_t i = 0; i < set.size(); ++i) os << set[i] << ::std::endl;
|
||||
for (auto& entry : set) os << entry << ::std::endl;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
@@ -131,6 +131,17 @@ ErrorCode KeyMintAidlTestBase::GenerateKey(const AuthorizationSet& key_desc,
|
||||
*key_blob = std::move(creationResult.keyBlob);
|
||||
*key_characteristics = std::move(creationResult.keyCharacteristics);
|
||||
cert_chain_ = std::move(creationResult.certificateChain);
|
||||
|
||||
auto algorithm = key_desc.GetTagValue(TAG_ALGORITHM);
|
||||
EXPECT_TRUE(algorithm);
|
||||
if (algorithm &&
|
||||
(algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
|
||||
EXPECT_GE(cert_chain_.size(), 1);
|
||||
if (key_desc.Contains(TAG_ATTESTATION_CHALLENGE)) EXPECT_GT(cert_chain_.size(), 1);
|
||||
} else {
|
||||
// For symmetric keys there should be no certificates.
|
||||
EXPECT_EQ(cert_chain_.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
return GetReturnErrorCode(result);
|
||||
@@ -162,6 +173,17 @@ ErrorCode KeyMintAidlTestBase::ImportKey(const AuthorizationSet& key_desc, KeyFo
|
||||
*key_blob = std::move(creationResult.keyBlob);
|
||||
*key_characteristics = std::move(creationResult.keyCharacteristics);
|
||||
cert_chain_ = std::move(creationResult.certificateChain);
|
||||
|
||||
auto algorithm = key_desc.GetTagValue(TAG_ALGORITHM);
|
||||
EXPECT_TRUE(algorithm);
|
||||
if (algorithm &&
|
||||
(algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
|
||||
EXPECT_GE(cert_chain_.size(), 1);
|
||||
if (key_desc.Contains(TAG_ATTESTATION_CHALLENGE)) EXPECT_GT(cert_chain_.size(), 1);
|
||||
} else {
|
||||
// For symmetric keys there should be no certificates.
|
||||
EXPECT_EQ(cert_chain_.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
return GetReturnErrorCode(result);
|
||||
@@ -195,6 +217,20 @@ ErrorCode KeyMintAidlTestBase::ImportWrappedKey(string wrapped_key, string wrapp
|
||||
key_blob_ = std::move(creationResult.keyBlob);
|
||||
key_characteristics_ = std::move(creationResult.keyCharacteristics);
|
||||
cert_chain_ = std::move(creationResult.certificateChain);
|
||||
|
||||
AuthorizationSet allAuths;
|
||||
for (auto& entry : key_characteristics_) {
|
||||
allAuths.push_back(AuthorizationSet(entry.authorizations));
|
||||
}
|
||||
auto algorithm = allAuths.GetTagValue(TAG_ALGORITHM);
|
||||
EXPECT_TRUE(algorithm);
|
||||
if (algorithm &&
|
||||
(algorithm.value() == Algorithm::RSA || algorithm.value() == Algorithm::EC)) {
|
||||
EXPECT_GE(cert_chain_.size(), 1);
|
||||
} else {
|
||||
// For symmetric keys there should be no certificates.
|
||||
EXPECT_EQ(cert_chain_.size(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
return GetReturnErrorCode(result);
|
||||
@@ -788,6 +824,24 @@ const vector<KeyParameter>& KeyMintAidlTestBase::SecLevelAuthorizations(
|
||||
return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
|
||||
}
|
||||
|
||||
const vector<KeyParameter>& KeyMintAidlTestBase::HwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics) {
|
||||
auto found =
|
||||
std::find_if(key_characteristics.begin(), key_characteristics.end(), [](auto& entry) {
|
||||
return entry.securityLevel == SecurityLevel::STRONGBOX ||
|
||||
entry.securityLevel == SecurityLevel::TRUSTED_ENVIRONMENT;
|
||||
});
|
||||
return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
|
||||
}
|
||||
|
||||
const vector<KeyParameter>& KeyMintAidlTestBase::SwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics) {
|
||||
auto found = std::find_if(
|
||||
key_characteristics.begin(), key_characteristics.end(),
|
||||
[](auto& entry) { return entry.securityLevel == SecurityLevel::SOFTWARE; });
|
||||
return (found == key_characteristics.end()) ? kEmptyAuthList : found->authorizations;
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint
|
||||
|
||||
@@ -27,7 +27,11 @@
|
||||
|
||||
#include <keymint_support/authorization_set.h>
|
||||
|
||||
namespace aidl::android::hardware::security::keymint::test {
|
||||
namespace aidl::android::hardware::security::keymint {
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
|
||||
|
||||
namespace test {
|
||||
|
||||
using ::android::sp;
|
||||
using Status = ::ndk::ScopedAStatus;
|
||||
@@ -37,8 +41,6 @@ using ::std::vector;
|
||||
|
||||
constexpr uint64_t kOpHandleSentinel = 0xFFFFFFFFFFFFFFFF;
|
||||
|
||||
::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set);
|
||||
|
||||
class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
|
||||
public:
|
||||
void SetUp() override;
|
||||
@@ -173,6 +175,10 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
|
||||
inline const vector<KeyParameter>& SecLevelAuthorizations() {
|
||||
return SecLevelAuthorizations(key_characteristics_);
|
||||
}
|
||||
const vector<KeyParameter>& HwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics);
|
||||
const vector<KeyParameter>& SwEnforcedAuthorizations(
|
||||
const vector<KeyCharacteristics>& key_characteristics);
|
||||
|
||||
private:
|
||||
std::shared_ptr<IKeyMintDevice> keymint_;
|
||||
@@ -190,4 +196,6 @@ class KeyMintAidlTestBase : public ::testing::TestWithParam<string> {
|
||||
testing::ValuesIn(KeyMintAidlTestBase::build_params()), \
|
||||
::android::PrintInstanceNameToString)
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint::test
|
||||
} // namespace test
|
||||
|
||||
} // namespace aidl::android::hardware::security::keymint
|
||||
|
||||
@@ -180,9 +180,280 @@ struct RSA_Delete {
|
||||
void operator()(RSA* p) { RSA_free(p); }
|
||||
};
|
||||
|
||||
/* TODO(seleneh) add attestation verification codes like verify_chain() and
|
||||
* attestation tests after we decided on the keymint 1 attestation changes.
|
||||
*/
|
||||
char nibble2hex[16] = {'0', '1', '2', '3', '4', '5', '6', '7',
|
||||
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
string bin2hex(const vector<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;
|
||||
}
|
||||
|
||||
X509* parse_cert_blob(const vector<uint8_t>& blob) {
|
||||
const uint8_t* p = blob.data();
|
||||
return d2i_X509(nullptr, &p, blob.size());
|
||||
}
|
||||
|
||||
bool verify_chain(const vector<Certificate>& chain) {
|
||||
for (size_t i = 0; i < chain.size(); ++i) {
|
||||
X509_Ptr key_cert(parse_cert_blob(chain[i].encodedCertificate));
|
||||
X509_Ptr signing_cert;
|
||||
if (i < chain.size() - 1) {
|
||||
signing_cert.reset(parse_cert_blob(chain[i + 1].encodedCertificate));
|
||||
} else {
|
||||
signing_cert.reset(parse_cert_blob(chain[i].encodedCertificate));
|
||||
}
|
||||
EXPECT_TRUE(!!key_cert.get() && !!signing_cert.get());
|
||||
if (!key_cert.get() || !signing_cert.get()) return false;
|
||||
|
||||
EVP_PKEY_Ptr signing_pubkey(X509_get_pubkey(signing_cert.get()));
|
||||
EXPECT_TRUE(!!signing_pubkey.get());
|
||||
if (!signing_pubkey.get()) return false;
|
||||
|
||||
EXPECT_EQ(1, X509_verify(key_cert.get(), signing_pubkey.get()))
|
||||
<< "Verification of certificate " << i << " failed "
|
||||
<< "OpenSSL error string: " << ERR_error_string(ERR_get_error(), NULL);
|
||||
|
||||
char* cert_issuer = //
|
||||
X509_NAME_oneline(X509_get_issuer_name(key_cert.get()), nullptr, 0);
|
||||
char* signer_subj =
|
||||
X509_NAME_oneline(X509_get_subject_name(signing_cert.get()), nullptr, 0);
|
||||
EXPECT_STREQ(cert_issuer, signer_subj) << "Cert " << i << " has wrong issuer.";
|
||||
if (i == 0) {
|
||||
char* cert_sub = X509_NAME_oneline(X509_get_subject_name(key_cert.get()), nullptr, 0);
|
||||
EXPECT_STREQ("/CN=Android Keystore Key", cert_sub)
|
||||
<< "Cert " << i << " has wrong subject.";
|
||||
OPENSSL_free(cert_sub);
|
||||
}
|
||||
|
||||
OPENSSL_free(cert_issuer);
|
||||
OPENSSL_free(signer_subj);
|
||||
|
||||
if (dump_Attestations) std::cout << bin2hex(chain[i].encodedCertificate) << std::endl;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Extract attestation record from cert. Returned object is still part of cert; don't free it
|
||||
// separately.
|
||||
ASN1_OCTET_STRING* get_attestation_record(X509* certificate) {
|
||||
ASN1_OBJECT_Ptr oid(OBJ_txt2obj(kAttestionRecordOid, 1 /* dotted string format */));
|
||||
EXPECT_TRUE(!!oid.get());
|
||||
if (!oid.get()) return nullptr;
|
||||
|
||||
int location = X509_get_ext_by_OBJ(certificate, oid.get(), -1 /* search from beginning */);
|
||||
EXPECT_NE(-1, location) << "Attestation extension not found in certificate";
|
||||
if (location == -1) return nullptr;
|
||||
|
||||
X509_EXTENSION* attest_rec_ext = X509_get_ext(certificate, location);
|
||||
EXPECT_TRUE(!!attest_rec_ext)
|
||||
<< "Found attestation extension but couldn't retrieve it? Probably a BoringSSL bug.";
|
||||
if (!attest_rec_ext) return nullptr;
|
||||
|
||||
ASN1_OCTET_STRING* attest_rec = X509_EXTENSION_get_data(attest_rec_ext);
|
||||
EXPECT_TRUE(!!attest_rec) << "Attestation extension contained no data";
|
||||
return attest_rec;
|
||||
}
|
||||
|
||||
bool tag_in_list(const KeyParameter& entry) {
|
||||
// Attestations don't contain everything in key authorization lists, so we need to filter
|
||||
// the key lists to produce the lists that we expect to match the attestations.
|
||||
auto tag_list = {
|
||||
Tag::BLOB_USAGE_REQUIREMENTS, //
|
||||
Tag::CREATION_DATETIME, //
|
||||
Tag::EC_CURVE,
|
||||
Tag::HARDWARE_TYPE,
|
||||
Tag::INCLUDE_UNIQUE_ID,
|
||||
};
|
||||
return std::find(tag_list.begin(), tag_list.end(), entry.tag) != tag_list.end();
|
||||
}
|
||||
|
||||
AuthorizationSet filtered_tags(const AuthorizationSet& set) {
|
||||
AuthorizationSet filtered;
|
||||
std::remove_copy_if(set.begin(), set.end(), std::back_inserter(filtered), tag_in_list);
|
||||
return filtered;
|
||||
}
|
||||
|
||||
bool avb_verification_enabled() {
|
||||
char value[PROPERTY_VALUE_MAX];
|
||||
return property_get("ro.boot.vbmeta.device_state", value, "") != 0;
|
||||
}
|
||||
|
||||
bool verify_attestation_record(const string& challenge, //
|
||||
const string& app_id, //
|
||||
AuthorizationSet expected_sw_enforced, //
|
||||
AuthorizationSet expected_hw_enforced, //
|
||||
SecurityLevel security_level,
|
||||
const vector<uint8_t>& attestation_cert) {
|
||||
X509_Ptr cert(parse_cert_blob(attestation_cert));
|
||||
EXPECT_TRUE(!!cert.get());
|
||||
if (!cert.get()) return false;
|
||||
|
||||
ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get());
|
||||
EXPECT_TRUE(!!attest_rec);
|
||||
if (!attest_rec) return false;
|
||||
|
||||
AuthorizationSet att_sw_enforced;
|
||||
AuthorizationSet att_hw_enforced;
|
||||
uint32_t att_attestation_version;
|
||||
uint32_t att_keymaster_version;
|
||||
SecurityLevel att_attestation_security_level;
|
||||
SecurityLevel att_keymaster_security_level;
|
||||
vector<uint8_t> att_challenge;
|
||||
vector<uint8_t> att_unique_id;
|
||||
vector<uint8_t> att_app_id;
|
||||
|
||||
auto error = parse_attestation_record(attest_rec->data, //
|
||||
attest_rec->length, //
|
||||
&att_attestation_version, //
|
||||
&att_attestation_security_level, //
|
||||
&att_keymaster_version, //
|
||||
&att_keymaster_security_level, //
|
||||
&att_challenge, //
|
||||
&att_sw_enforced, //
|
||||
&att_hw_enforced, //
|
||||
&att_unique_id);
|
||||
EXPECT_EQ(ErrorCode::OK, error);
|
||||
if (error != ErrorCode::OK) return false;
|
||||
|
||||
EXPECT_GE(att_attestation_version, 3U);
|
||||
|
||||
expected_sw_enforced.push_back(TAG_ATTESTATION_APPLICATION_ID,
|
||||
vector<uint8_t>(app_id.begin(), app_id.end()));
|
||||
|
||||
EXPECT_GE(att_keymaster_version, 4U);
|
||||
EXPECT_EQ(security_level, att_keymaster_security_level);
|
||||
EXPECT_EQ(security_level, att_attestation_security_level);
|
||||
|
||||
EXPECT_EQ(challenge.length(), att_challenge.size());
|
||||
EXPECT_EQ(0, memcmp(challenge.data(), att_challenge.data(), challenge.length()));
|
||||
|
||||
char property_value[PROPERTY_VALUE_MAX] = {};
|
||||
// TODO(b/136282179): When running under VTS-on-GSI the TEE-backed
|
||||
// keymaster implementation will report YYYYMM dates instead of YYYYMMDD
|
||||
// for the BOOT_PATCH_LEVEL.
|
||||
if (avb_verification_enabled()) {
|
||||
for (int i = 0; i < att_hw_enforced.size(); i++) {
|
||||
if (att_hw_enforced[i].tag == TAG_BOOT_PATCHLEVEL ||
|
||||
att_hw_enforced[i].tag == TAG_VENDOR_PATCHLEVEL) {
|
||||
std::string date =
|
||||
std::to_string(att_hw_enforced[i].value.get<KeyParameterValue::dateTime>());
|
||||
// strptime seems to require delimiters, but the tag value will
|
||||
// be YYYYMMDD
|
||||
date.insert(6, "-");
|
||||
date.insert(4, "-");
|
||||
EXPECT_EQ(date.size(), 10);
|
||||
struct tm time;
|
||||
strptime(date.c_str(), "%Y-%m-%d", &time);
|
||||
|
||||
// Day of the month (0-31)
|
||||
EXPECT_GE(time.tm_mday, 0);
|
||||
EXPECT_LT(time.tm_mday, 32);
|
||||
// Months since Jan (0-11)
|
||||
EXPECT_GE(time.tm_mon, 0);
|
||||
EXPECT_LT(time.tm_mon, 12);
|
||||
// Years since 1900
|
||||
EXPECT_GT(time.tm_year, 110);
|
||||
EXPECT_LT(time.tm_year, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check to make sure boolean values are properly encoded. Presence of a boolean tag indicates
|
||||
// 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.
|
||||
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));
|
||||
|
||||
if (att_hw_enforced.Contains(TAG_ALGORITHM, Algorithm::EC)) {
|
||||
// For ECDSA keys, either an EC_CURVE or a KEY_SIZE can be specified, but one must be.
|
||||
EXPECT_TRUE(att_hw_enforced.Contains(TAG_EC_CURVE) ||
|
||||
att_hw_enforced.Contains(TAG_KEY_SIZE));
|
||||
}
|
||||
|
||||
// Test root of trust elements
|
||||
vector<uint8_t> verified_boot_key;
|
||||
VerifiedBoot verified_boot_state;
|
||||
bool device_locked;
|
||||
vector<uint8_t> verified_boot_hash;
|
||||
error = parse_root_of_trust(attest_rec->data, attest_rec->length, &verified_boot_key,
|
||||
&verified_boot_state, &device_locked, &verified_boot_hash);
|
||||
EXPECT_EQ(ErrorCode::OK, error);
|
||||
|
||||
if (avb_verification_enabled()) {
|
||||
EXPECT_NE(property_get("ro.boot.vbmeta.digest", property_value, ""), 0);
|
||||
string prop_string(property_value);
|
||||
EXPECT_EQ(prop_string.size(), 64);
|
||||
EXPECT_EQ(prop_string, bin2hex(verified_boot_hash));
|
||||
|
||||
EXPECT_NE(property_get("ro.boot.vbmeta.device_state", property_value, ""), 0);
|
||||
if (!strcmp(property_value, "unlocked")) {
|
||||
EXPECT_FALSE(device_locked);
|
||||
} else {
|
||||
EXPECT_TRUE(device_locked);
|
||||
}
|
||||
|
||||
// Check that the device is locked if not debuggable, e.g., user build
|
||||
// images in CTS. For VTS, debuggable images are used to allow adb root
|
||||
// and the device is unlocked.
|
||||
if (!property_get_bool("ro.debuggable", false)) {
|
||||
EXPECT_TRUE(device_locked);
|
||||
} else {
|
||||
EXPECT_FALSE(device_locked);
|
||||
}
|
||||
}
|
||||
|
||||
// Verified boot key should be all 0's if the boot state is not verified or self signed
|
||||
std::string empty_boot_key(32, '\0');
|
||||
std::string verified_boot_key_str((const char*)verified_boot_key.data(),
|
||||
verified_boot_key.size());
|
||||
EXPECT_NE(property_get("ro.boot.verifiedbootstate", property_value, ""), 0);
|
||||
if (!strcmp(property_value, "green")) {
|
||||
EXPECT_EQ(verified_boot_state, VerifiedBoot::VERIFIED);
|
||||
EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
|
||||
verified_boot_key.size()));
|
||||
} else if (!strcmp(property_value, "yellow")) {
|
||||
EXPECT_EQ(verified_boot_state, VerifiedBoot::SELF_SIGNED);
|
||||
EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
|
||||
verified_boot_key.size()));
|
||||
} else if (!strcmp(property_value, "orange")) {
|
||||
EXPECT_EQ(verified_boot_state, VerifiedBoot::UNVERIFIED);
|
||||
EXPECT_EQ(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
|
||||
verified_boot_key.size()));
|
||||
} else if (!strcmp(property_value, "red")) {
|
||||
EXPECT_EQ(verified_boot_state, VerifiedBoot::FAILED);
|
||||
} else {
|
||||
EXPECT_EQ(verified_boot_state, VerifiedBoot::UNVERIFIED);
|
||||
EXPECT_NE(0, memcmp(verified_boot_key.data(), empty_boot_key.data(),
|
||||
verified_boot_key.size()));
|
||||
}
|
||||
|
||||
att_sw_enforced.Sort();
|
||||
expected_sw_enforced.Sort();
|
||||
EXPECT_EQ(filtered_tags(expected_sw_enforced), filtered_tags(att_sw_enforced));
|
||||
|
||||
att_hw_enforced.Sort();
|
||||
expected_hw_enforced.Sort();
|
||||
EXPECT_EQ(filtered_tags(expected_hw_enforced), filtered_tags(att_hw_enforced));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string make_string(const uint8_t* data, size_t length) {
|
||||
return std::string(reinterpret_cast<const char*>(data), length);
|
||||
@@ -288,6 +559,51 @@ TEST_P(NewKeyGenerationTest, Rsa) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NewKeyGenerationTest.Rsa
|
||||
*
|
||||
* Verifies that keymint can generate all required RSA key sizes, and that the resulting keys
|
||||
* have correct characteristics.
|
||||
*/
|
||||
TEST_P(NewKeyGenerationTest, RsaWithAttestation) {
|
||||
for (auto key_size : ValidKeySizes(Algorithm::RSA)) {
|
||||
auto challenge = "hello";
|
||||
auto app_id = "foo";
|
||||
|
||||
vector<uint8_t> key_blob;
|
||||
vector<KeyCharacteristics> key_characteristics;
|
||||
ASSERT_EQ(ErrorCode::OK, GenerateKey(AuthorizationSetBuilder()
|
||||
.RsaSigningKey(key_size, 65537)
|
||||
.Digest(Digest::NONE)
|
||||
.Padding(PaddingMode::NONE)
|
||||
.AttestationChallenge(challenge)
|
||||
.AttestationApplicationId(app_id)
|
||||
.Authorization(TAG_NO_AUTH_REQUIRED),
|
||||
&key_blob, &key_characteristics));
|
||||
|
||||
ASSERT_GT(key_blob.size(), 0U);
|
||||
CheckBaseParams(key_characteristics);
|
||||
|
||||
AuthorizationSet crypto_params = SecLevelAuthorizations(key_characteristics);
|
||||
|
||||
EXPECT_TRUE(crypto_params.Contains(TAG_ALGORITHM, Algorithm::RSA));
|
||||
EXPECT_TRUE(crypto_params.Contains(TAG_KEY_SIZE, key_size))
|
||||
<< "Key size " << key_size << "missing";
|
||||
EXPECT_TRUE(crypto_params.Contains(TAG_RSA_PUBLIC_EXPONENT, 65537U));
|
||||
|
||||
EXPECT_TRUE(verify_chain(cert_chain_));
|
||||
ASSERT_GT(cert_chain_.size(), 0);
|
||||
|
||||
AuthorizationSet hw_enforced = HwEnforcedAuthorizations(key_characteristics);
|
||||
AuthorizationSet sw_enforced = SwEnforcedAuthorizations(key_characteristics);
|
||||
EXPECT_TRUE(verify_attestation_record(challenge, app_id, //
|
||||
sw_enforced, hw_enforced, SecLevel(),
|
||||
cert_chain_[0].encodedCertificate));
|
||||
|
||||
CheckedDeleteKey(&key_blob);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* NewKeyGenerationTest.NoInvalidRsaSizes
|
||||
*
|
||||
@@ -3895,16 +4211,6 @@ TEST_P(AddEntropyTest, AddLargeEntropy) {
|
||||
|
||||
INSTANTIATE_KEYMINT_AIDL_TEST(AddEntropyTest);
|
||||
|
||||
typedef KeyMintAidlTestBase AttestationTest;
|
||||
|
||||
/*
|
||||
* AttestationTest.RsaAttestation
|
||||
*
|
||||
* Verifies that attesting to RSA keys works and generates the expected output.
|
||||
*/
|
||||
// TODO(seleneh) add attestation tests back after decided on the new attestation
|
||||
// behavior under generateKey and importKey
|
||||
|
||||
typedef KeyMintAidlTestBase KeyDeletionTest;
|
||||
|
||||
/**
|
||||
|
||||
@@ -259,6 +259,12 @@ class AuthorizationSetBuilder : public AuthorizationSet {
|
||||
size - 1); // drop the terminating '\0'
|
||||
}
|
||||
|
||||
template <Tag tag>
|
||||
AuthorizationSetBuilder& Authorization(TypedTag<TagType::BYTES, tag> ttag,
|
||||
const std::string& data) {
|
||||
return Authorization(ttag, reinterpret_cast<const uint8_t*>(data.data()), data.size());
|
||||
}
|
||||
|
||||
AuthorizationSetBuilder& Authorizations(const AuthorizationSet& set) {
|
||||
for (const auto& entry : set) {
|
||||
push_back(entry);
|
||||
@@ -294,6 +300,20 @@ class AuthorizationSetBuilder : public AuthorizationSet {
|
||||
AuthorizationSetBuilder& Digest(std::vector<Digest> digests);
|
||||
AuthorizationSetBuilder& Padding(std::initializer_list<PaddingMode> paddings);
|
||||
|
||||
AuthorizationSetBuilder& AttestationChallenge(const std::string& challenge) {
|
||||
return Authorization(TAG_ATTESTATION_CHALLENGE, challenge);
|
||||
}
|
||||
AuthorizationSetBuilder& AttestationChallenge(std::vector<uint8_t> challenge) {
|
||||
return Authorization(TAG_ATTESTATION_CHALLENGE, challenge);
|
||||
}
|
||||
|
||||
AuthorizationSetBuilder& AttestationApplicationId(const std::string& id) {
|
||||
return Authorization(TAG_ATTESTATION_APPLICATION_ID, id);
|
||||
}
|
||||
AuthorizationSetBuilder& AttestationApplicationId(std::vector<uint8_t> id) {
|
||||
return Authorization(TAG_ATTESTATION_APPLICATION_ID, id);
|
||||
}
|
||||
|
||||
template <typename... T>
|
||||
AuthorizationSetBuilder& BlockMode(T&&... a) {
|
||||
return BlockMode({std::forward<T>(a)...});
|
||||
|
||||
Reference in New Issue
Block a user