diff options
author | David Drysdale <drysdale@google.com> | 2021-04-01 12:17:35 +0100 |
---|---|---|
committer | David Drysdale <drysdale@google.com> | 2021-04-12 14:48:31 +0100 |
commit | 4dc010739d287542518ba65701e5f2ac7a400a2e (patch) | |
tree | b523a7a6940a4d56ea015b0da94edb00be272024 /security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp | |
parent | 303991b322f7e47c5106efd651f59536e5719d96 (diff) |
Check that KeyMint provides IRemotelyProvisionedComponent
Move helper utilities across into KeyMintAidlTestBase to allow re-use.
Test: VtsHalRemotelyProvisionedComponentTargetTest, VtsAidlKeyMintTargetTest
Change-Id: Ib9e55a7d72fd197016ae1a1f073dadedafa09c25
Diffstat (limited to 'security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp')
-rw-r--r-- | security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp index ce6f67a84a..ec2194454f 100644 --- a/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp +++ b/security/keymint/aidl/vts/functional/KeyMintAidlTestBase.cpp @@ -22,8 +22,12 @@ #include <android-base/logging.h> #include <android/binder_manager.h> +#include <cppbor_parse.h> +#include <cppcose/cppcose.h> #include <cutils/properties.h> +#include <gmock/gmock.h> #include <openssl/mem.h> +#include <remote_prov/remote_prov_utils.h> #include <keymint_support/attestation_record.h> #include <keymint_support/key_param_output.h> @@ -32,6 +36,7 @@ namespace aidl::android::hardware::security::keymint { +using namespace cppcose; using namespace std::literals::chrono_literals; using std::endl; using std::optional; @@ -39,6 +44,7 @@ using std::unique_ptr; using ::testing::AssertionFailure; using ::testing::AssertionResult; using ::testing::AssertionSuccess; +using ::testing::MatchesRegex; ::std::ostream& operator<<(::std::ostream& os, const AuthorizationSet& set) { if (set.size() == 0) @@ -1118,6 +1124,121 @@ vector<uint8_t> make_name_from_str(const string& name) { return retval; } +namespace { + +void check_cose_key(const vector<uint8_t>& data, bool testMode) { + auto [parsedPayload, __, payloadParseErr] = cppbor::parse(data); + ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr; + + // The following check assumes that canonical CBOR encoding is used for the COSE_Key. + if (testMode) { + EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()), + MatchesRegex("{\n" + " 1 : 2,\n" // kty: EC2 + " 3 : -7,\n" // alg: ES256 + " -1 : 1,\n" // EC id: P256 + // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a + // sequence of 32 hexadecimal bytes, enclosed in braces and + // separated by commas. In this case, some Ed25519 public key. + " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data + " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data + " -70000 : null,\n" // test marker + "}")); + } else { + EXPECT_THAT(cppbor::prettyPrint(parsedPayload.get()), + MatchesRegex("{\n" + " 1 : 2,\n" // kty: EC2 + " 3 : -7,\n" // alg: ES256 + " -1 : 1,\n" // EC id: P256 + // The regex {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}} matches a + // sequence of 32 hexadecimal bytes, enclosed in braces and + // separated by commas. In this case, some Ed25519 public key. + " -2 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_x: data + " -3 : {(0x[0-9a-f]{2}, ){31}0x[0-9a-f]{2}},\n" // pub_y: data + "}")); + } +} + +} // namespace + +void check_maced_pubkey(const MacedPublicKey& macedPubKey, bool testMode, + vector<uint8_t>* payload_value) { + auto [coseMac0, _, mac0ParseErr] = cppbor::parse(macedPubKey.macedKey); + ASSERT_TRUE(coseMac0) << "COSE Mac0 parse failed " << mac0ParseErr; + + ASSERT_NE(coseMac0->asArray(), nullptr); + ASSERT_EQ(coseMac0->asArray()->size(), kCoseMac0EntryCount); + + auto protParms = coseMac0->asArray()->get(kCoseMac0ProtectedParams)->asBstr(); + ASSERT_NE(protParms, nullptr); + + // Header label:value of 'alg': HMAC-256 + ASSERT_EQ(cppbor::prettyPrint(protParms->value()), "{\n 1 : 5,\n}"); + + auto unprotParms = coseMac0->asArray()->get(kCoseMac0UnprotectedParams)->asMap(); + ASSERT_NE(unprotParms, nullptr); + ASSERT_EQ(unprotParms->size(), 0); + + // The payload is a bstr holding an encoded COSE_Key + auto payload = coseMac0->asArray()->get(kCoseMac0Payload)->asBstr(); + ASSERT_NE(payload, nullptr); + check_cose_key(payload->value(), testMode); + + auto coseMac0Tag = coseMac0->asArray()->get(kCoseMac0Tag)->asBstr(); + ASSERT_TRUE(coseMac0Tag); + auto extractedTag = coseMac0Tag->value(); + EXPECT_EQ(extractedTag.size(), 32U); + + // Compare with tag generated with kTestMacKey. Should only match in test mode + auto testTag = cppcose::generateCoseMac0Mac(remote_prov::kTestMacKey, {} /* external_aad */, + payload->value()); + ASSERT_TRUE(testTag) << "Tag calculation failed: " << testTag.message(); + + if (testMode) { + EXPECT_EQ(*testTag, extractedTag); + } else { + EXPECT_NE(*testTag, extractedTag); + } + if (payload_value != nullptr) { + *payload_value = payload->value(); + } +} + +void p256_pub_key(const vector<uint8_t>& coseKeyData, EVP_PKEY_Ptr* signingKey) { + // Extract x and y affine coordinates from the encoded Cose_Key. + auto [parsedPayload, __, payloadParseErr] = cppbor::parse(coseKeyData); + ASSERT_TRUE(parsedPayload) << "Key parse failed: " << payloadParseErr; + auto coseKey = parsedPayload->asMap(); + const std::unique_ptr<cppbor::Item>& xItem = coseKey->get(cppcose::CoseKey::PUBKEY_X); + ASSERT_NE(xItem->asBstr(), nullptr); + vector<uint8_t> x = xItem->asBstr()->value(); + const std::unique_ptr<cppbor::Item>& yItem = coseKey->get(cppcose::CoseKey::PUBKEY_Y); + ASSERT_NE(yItem->asBstr(), nullptr); + vector<uint8_t> y = yItem->asBstr()->value(); + + // Concatenate: 0x04 (uncompressed form marker) | x | y + vector<uint8_t> pubKeyData{0x04}; + pubKeyData.insert(pubKeyData.end(), x.begin(), x.end()); + pubKeyData.insert(pubKeyData.end(), y.begin(), y.end()); + + EC_KEY_Ptr ecKey = EC_KEY_Ptr(EC_KEY_new()); + ASSERT_NE(ecKey, nullptr); + EC_GROUP_Ptr group = EC_GROUP_Ptr(EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)); + ASSERT_NE(group, nullptr); + ASSERT_EQ(EC_KEY_set_group(ecKey.get(), group.get()), 1); + EC_POINT_Ptr point = EC_POINT_Ptr(EC_POINT_new(group.get())); + ASSERT_NE(point, nullptr); + ASSERT_EQ(EC_POINT_oct2point(group.get(), point.get(), pubKeyData.data(), pubKeyData.size(), + nullptr), + 1); + ASSERT_EQ(EC_KEY_set_public_key(ecKey.get(), point.get()), 1); + + EVP_PKEY_Ptr pubKey = EVP_PKEY_Ptr(EVP_PKEY_new()); + ASSERT_NE(pubKey, nullptr); + EVP_PKEY_assign_EC_KEY(pubKey.get(), ecKey.release()); + *signingKey = std::move(pubKey); +} + } // namespace test } // namespace aidl::android::hardware::security::keymint |