From ec50ee162a7bfd3dedad98141d762f20417fef02 Mon Sep 17 00:00:00 2001 From: Tri Vo Date: Tue, 14 Feb 2023 16:29:53 -0800 Subject: [PATCH] Add test for IRPC DeviceInfo Bug: 243148852 Test: atest VtsHalRemotelyProvisionedComponentTargetTest Change-Id: If873996f0d756662808d785d2ef57118737a5aab --- .../vts/functional/KeyMintAidlTestBase.cpp | 42 +++--- .../aidl/vts/functional/KeyMintAidlTestBase.h | 1 + .../VtsRemotelyProvisionedComponentTests.cpp | 123 ++++++++++++++++++ 3 files changed, 145 insertions(+), 21 deletions(-) diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp index 588a1d44a0..e05867de23 100644 --- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp +++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp @@ -108,27 +108,6 @@ bool KeyCharacteristicsBasicallyValid(SecurityLevel secLevel, 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; -} - void check_attestation_version(uint32_t attestation_version, int32_t aidl_version) { // Version numbers in attestation extensions should be a multiple of 100. EXPECT_EQ(attestation_version % 100, 0); @@ -1896,6 +1875,27 @@ X509_Ptr parse_cert_blob(const vector& blob) { return X509_Ptr(d2i_X509(nullptr /* allocate new */, &p, blob.size())); } +// 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; +} + vector make_name_from_str(const string& name) { X509_NAME_Ptr x509_name(X509_NAME_new()); EXPECT_TRUE(x509_name.get() != nullptr); diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h index fae9459171..8fa99e1aff 100644 --- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h +++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.h @@ -397,6 +397,7 @@ bool verify_attestation_record(int aidl_version, // string bin2hex(const vector& data); X509_Ptr parse_cert_blob(const vector& blob); +ASN1_OCTET_STRING* get_attestation_record(X509* certificate); vector make_name_from_str(const string& name); void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode, vector* payload_value); diff --git a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp index 573f10bc5b..bf40976ec3 100644 --- a/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp +++ b/security/rkp/aidl/vts/functional/VtsRemotelyProvisionedComponentTests.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -797,6 +798,128 @@ TEST_P(CertificateRequestV2Test, NonEmptyRequest_testKeyInProdCert) { BnRemotelyProvisionedComponent::STATUS_TEST_KEY_IN_PRODUCTION_REQUEST); } +void parse_root_of_trust(const vector& attestation_cert, + vector* verified_boot_key, VerifiedBoot* verified_boot_state, + bool* device_locked, vector* verified_boot_hash) { + X509_Ptr cert(parse_cert_blob(attestation_cert)); + ASSERT_TRUE(cert.get()); + + ASN1_OCTET_STRING* attest_rec = get_attestation_record(cert.get()); + ASSERT_TRUE(attest_rec); + + auto error = parse_root_of_trust(attest_rec->data, attest_rec->length, verified_boot_key, + verified_boot_state, device_locked, verified_boot_hash); + ASSERT_EQ(error, ErrorCode::OK); +} + +/** + * Generate a CSR and verify DeviceInfo against IDs attested by KeyMint. + */ +TEST_P(CertificateRequestV2Test, DeviceInfo) { + // See if there is a matching IKeyMintDevice for this IRemotelyProvisionedComponent. + std::shared_ptr keyMint; + if (!matching_keymint_device(GetParam(), &keyMint)) { + // No matching IKeyMintDevice. + GTEST_SKIP() << "Skipping key use test as no matching KeyMint device found"; + return; + } + KeyMintHardwareInfo info; + ASSERT_TRUE(keyMint->getHardwareInfo(&info).isOk()); + + // Get IDs attested by KeyMint. + MacedPublicKey macedPubKey; + bytevec privateKeyBlob; + auto irpcStatus = + provisionable_->generateEcdsaP256KeyPair(false, &macedPubKey, &privateKeyBlob); + ASSERT_TRUE(irpcStatus.isOk()); + + AttestationKey attestKey; + attestKey.keyBlob = std::move(privateKeyBlob); + attestKey.issuerSubjectName = make_name_from_str("Android Keystore Key"); + + // Generate an ECDSA key that is attested by the generated P256 keypair. + AuthorizationSet keyDesc = AuthorizationSetBuilder() + .Authorization(TAG_NO_AUTH_REQUIRED) + .EcdsaSigningKey(EcCurve::P_256) + .AttestationChallenge("foo") + .AttestationApplicationId("bar") + .Digest(Digest::NONE) + .SetDefaultValidity(); + KeyCreationResult creationResult; + auto kmStatus = keyMint->generateKey(keyDesc.vector_data(), attestKey, &creationResult); + ASSERT_TRUE(kmStatus.isOk()); + + vector key_characteristics = std::move(creationResult.keyCharacteristics); + vector key_cert_chain = std::move(creationResult.certificateChain); + // We didn't provision the attestation key. + ASSERT_EQ(key_cert_chain.size(), 1); + + // Parse attested patch levels. + auto auths = HwEnforcedAuthorizations(key_characteristics); + + auto attestedSystemPatchLevel = auths.GetTagValue(TAG_OS_PATCHLEVEL); + auto attestedVendorPatchLevel = auths.GetTagValue(TAG_VENDOR_PATCHLEVEL); + auto attestedBootPatchLevel = auths.GetTagValue(TAG_BOOT_PATCHLEVEL); + + ASSERT_TRUE(attestedSystemPatchLevel.has_value()); + ASSERT_TRUE(attestedVendorPatchLevel.has_value()); + ASSERT_TRUE(attestedBootPatchLevel.has_value()); + + // Parse attested AVB values. + vector key; + VerifiedBoot attestedVbState; + bool attestedBootloaderState; + vector attestedVbmetaDigest; + parse_root_of_trust(key_cert_chain[0].encodedCertificate, &key, &attestedVbState, + &attestedBootloaderState, &attestedVbmetaDigest); + + // Get IDs from DeviceInfo. + bytevec csr; + irpcStatus = + provisionable_->generateCertificateRequestV2({} /* keysToSign */, challenge_, &csr); + ASSERT_TRUE(irpcStatus.isOk()) << irpcStatus.getMessage(); + + auto result = verifyProductionCsr(cppbor::Array(), csr, provisionable_.get(), challenge_); + ASSERT_TRUE(result) << result.message(); + + std::unique_ptr csrPayload = std::move(*result); + ASSERT_TRUE(csrPayload); + + auto deviceInfo = csrPayload->get(2)->asMap(); + ASSERT_TRUE(deviceInfo); + + auto vbState = deviceInfo->get("vb_state")->asTstr(); + auto bootloaderState = deviceInfo->get("bootloader_state")->asTstr(); + auto vbmetaDigest = deviceInfo->get("vbmeta_digest")->asBstr(); + auto systemPatchLevel = deviceInfo->get("system_patch_level")->asUint(); + auto vendorPatchLevel = deviceInfo->get("vendor_patch_level")->asUint(); + auto bootPatchLevel = deviceInfo->get("boot_patch_level")->asUint(); + auto securityLevel = deviceInfo->get("security_level")->asTstr(); + + ASSERT_TRUE(vbState); + ASSERT_TRUE(bootloaderState); + ASSERT_TRUE(vbmetaDigest); + ASSERT_TRUE(systemPatchLevel); + ASSERT_TRUE(vendorPatchLevel); + ASSERT_TRUE(bootPatchLevel); + ASSERT_TRUE(securityLevel); + + auto kmDeviceName = device_suffix(GetParam()); + + // Compare DeviceInfo against IDs attested by KeyMint. + ASSERT_TRUE((securityLevel->value() == "tee" && kmDeviceName == "default") || + (securityLevel->value() == "strongbox" && kmDeviceName == "strongbox")); + ASSERT_TRUE((vbState->value() == "green" && attestedVbState == VerifiedBoot::VERIFIED) || + (vbState->value() == "yellow" && attestedVbState == VerifiedBoot::SELF_SIGNED) || + (vbState->value() == "orange" && attestedVbState == VerifiedBoot::UNVERIFIED)); + ASSERT_TRUE((bootloaderState->value() == "locked" && attestedBootloaderState) || + (bootloaderState->value() == "unlocked" && !attestedBootloaderState)); + ASSERT_EQ(vbmetaDigest->value(), attestedVbmetaDigest); + ASSERT_EQ(systemPatchLevel->value(), attestedSystemPatchLevel.value()); + ASSERT_EQ(vendorPatchLevel->value(), attestedVendorPatchLevel.value()); + ASSERT_EQ(bootPatchLevel->value(), attestedBootPatchLevel.value()); +} + INSTANTIATE_REM_PROV_AIDL_TEST(CertificateRequestV2Test); using VsrRequirementTest = VtsRemotelyProvisionedComponentTests;