| // Copyright 2023 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "arc/keymint/conversion.h" | |
| #include <array> | |
| #include <memory> | |
| #include <utility> | |
| #include <vector> | |
| #include <gtest/gtest.h> | |
| #include <keymaster/android_keymaster_utils.h> | |
| namespace arc::keymint { | |
| namespace { | |
| constexpr std::array<uint8_t, 3> kBlob1{{3, 23, 59}}; | |
| constexpr std::array<uint8_t, 4> kBlob2{{23, 46, 69, 92}}; | |
| constexpr std::array<uint8_t, 5> kBlob3{{1, 2, 3, 4, 5}}; | |
| constexpr int32_t kKeyMintMessageVersion = 4; | |
| constexpr uint64_t fakeChallenge = 224498432732987237; | |
| constexpr uint64_t fakeAuthenticatorId = 790712303; | |
| constexpr uint64_t fakeUserId = 321; | |
| constexpr uint64_t fakeTimeStamp = 4349843232312345627; | |
| ::testing::AssertionResult VerifyVectorUint8(const uint8_t* a, | |
| const size_t a_size, | |
| const std::vector<uint8_t>& b) { | |
| if (a_size != b.size()) { | |
| return ::testing::AssertionFailure() | |
| << "Sizes differ: a=" << a_size << " b=" << b.size(); | |
| } | |
| for (size_t i = 0; i < a_size; ++i) { | |
| if (a[i] != b[i]) { | |
| return ::testing::AssertionFailure() | |
| << "Elements differ: a=" << static_cast<int>(a[i]) | |
| << " b=" << static_cast<int>(b[i]); | |
| } | |
| } | |
| return ::testing::AssertionSuccess(); | |
| } | |
| ::testing::AssertionResult VerifyKeyParametersWithStrictInputs( | |
| const ::keymaster::AuthorizationSet& a, | |
| const std::vector<arc::mojom::keymint::KeyParameterPtr>& b) { | |
| if (a.size() != b.size()) { | |
| return ::testing::AssertionFailure() | |
| << "Sizes differ: a=" << a.size() << " b=" << b.size(); | |
| } | |
| for (size_t i = 0; i < a.size(); ++i) { | |
| if (a[i].tag != static_cast<uint32_t>(b[i]->tag)) { | |
| return ::testing::AssertionFailure() | |
| << "Tags differ: i=" << i | |
| << " a=" << static_cast<uint32_t>(a[i].tag) << " b=" << b[i]->tag; | |
| } | |
| } | |
| if (!(b[0]->value->is_bool_value() && b[1]->value->is_integer() && | |
| b[2]->value->is_long_integer() && b[3]->value->is_date_time() && | |
| b[4]->value->is_blob() && b[5]->value->is_algorithm())) { | |
| return ::testing::AssertionFailure() << "Incorrect union value type"; | |
| } | |
| if (!(a[0].boolean == b[0]->value->get_bool_value() && | |
| a[1].integer == b[1]->value->get_integer() && | |
| a[2].long_integer == b[2]->value->get_long_integer() && | |
| a[3].date_time == b[3]->value->get_date_time()) && | |
| a[5].enumerated == static_cast<uint32_t>(b[5]->value->get_algorithm())) { | |
| return ::testing::AssertionFailure() << "Values differ"; | |
| } | |
| return VerifyVectorUint8(a[4].blob.data, a[4].blob.data_length, | |
| b[4]->value->get_blob()); | |
| } | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> KeyParameterVector() { | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> parameters(6); | |
| // bool | |
| auto paramBool = arc::mojom::keymint::KeyParameterValue::NewBoolValue(true); | |
| parameters[0] = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_CALLER_NONCE), | |
| std::move(paramBool)); | |
| // int, int_rep | |
| auto paramInt = arc::mojom::keymint::KeyParameterValue::NewInteger(128); | |
| parameters[1] = arc::mojom::keymint::KeyParameter::New( | |
| arc::mojom::keymint::Tag::KEY_SIZE, std::move(paramInt)); | |
| // long | |
| auto paramLong = | |
| arc::mojom::keymint::KeyParameterValue::NewLongInteger(65537); | |
| parameters[2] = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_RSA_PUBLIC_EXPONENT), | |
| std::move(paramLong)); | |
| // date | |
| auto paramDate = arc::mojom::keymint::KeyParameterValue::NewDateTime(1337); | |
| parameters[3] = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_ACTIVE_DATETIME), | |
| std::move(paramDate)); | |
| // bignum, bytes | |
| auto paramBlob = arc::mojom::keymint::KeyParameterValue::NewBlob( | |
| std::vector<uint8_t>(kBlob1.begin(), kBlob1.end())); | |
| parameters[4] = arc::mojom::keymint::KeyParameter::New( | |
| static_cast<arc::mojom::keymint::Tag>(KM_TAG_APPLICATION_DATA), | |
| std::move(paramBlob)); | |
| // enum, enum_rep | |
| auto paramAlgo = arc::mojom::keymint::KeyParameterValue::NewAlgorithm( | |
| arc::mojom::keymint::Algorithm::TRIPLE_DES); | |
| parameters[5] = arc::mojom::keymint::KeyParameter::New( | |
| arc::mojom::keymint::Tag::ALGORITHM, std::move(paramAlgo)); | |
| return parameters; | |
| } | |
| arc::mojom::keymint::AttestationKeyPtr CreateAttestationKey() { | |
| std::vector<uint8_t> key_blob(kBlob1.begin(), kBlob1.end()); | |
| std::vector<uint8_t> issuer_subject_name(kBlob2.begin(), kBlob2.end()); | |
| return arc::mojom::keymint::AttestationKey::New( | |
| key_blob, KeyParameterVector(), issuer_subject_name); | |
| } | |
| ::testing::AssertionResult VerifyAttestationKey( | |
| const ::keymaster::KeymasterKeyBlob& key_blob, | |
| const ::keymaster::AuthorizationSet& attest_key_params, | |
| const ::keymaster::KeymasterBlob& issuer_subject, | |
| const arc::mojom::keymint::AttestationKeyPtr& mojo) { | |
| if (auto result = VerifyVectorUint8( | |
| key_blob.key_material, key_blob.key_material_size, mojo->key_blob); | |
| result != ::testing::AssertionSuccess()) { | |
| return result; | |
| } | |
| if (auto result = VerifyKeyParametersWithStrictInputs( | |
| attest_key_params, mojo->attest_key_params); | |
| result != ::testing::AssertionSuccess()) { | |
| return result; | |
| } | |
| if (auto result = | |
| VerifyVectorUint8(issuer_subject.data, issuer_subject.data_length, | |
| mojo->issuer_subject_name); | |
| result != ::testing::AssertionSuccess()) { | |
| return result; | |
| } | |
| return ::testing::AssertionSuccess(); | |
| } | |
| ::arc::mojom::keymint::HardwareAuthTokenPtr CreateHardwareAuthToken() { | |
| return ::arc::mojom::keymint::HardwareAuthToken::New( | |
| fakeChallenge, fakeUserId, fakeAuthenticatorId, | |
| arc::mojom::keymint::HardwareAuthenticatorType(HW_AUTH_ANY), | |
| ::arc::mojom::keymint::Timestamp::New(fakeTimeStamp), | |
| std::vector<uint8_t>{2, 3}); | |
| } | |
| ::arc::mojom::keymint::TimeStampTokenPtr CreateTimeStampToken() { | |
| return ::arc::mojom::keymint::TimeStampToken::New( | |
| fakeChallenge, ::arc::mojom::keymint::Timestamp::New(fakeTimeStamp), | |
| std::vector<uint8_t>{2, 3}); | |
| } | |
| ::testing::AssertionResult VerifyHardwareAuthToken( | |
| const ::keymaster::AuthorizationSet& a, | |
| const arc::mojom::keymint::HardwareAuthToken& b) { | |
| auto result = ::testing::AssertionResult(false); | |
| for (size_t i = 0; i < a.size(); ++i) { | |
| if (a[i].tag == static_cast<uint32_t>(KM_TAG_AUTH_TOKEN)) { | |
| keymaster_blob_t blob = a[i].blob; | |
| auto tokenAsVec(authToken2AidlVec(b)); | |
| result = VerifyVectorUint8(blob.data, blob.data_length, tokenAsVec); | |
| } | |
| } | |
| return result; | |
| } | |
| ::testing::AssertionResult VerifyVerificationToken( | |
| ::keymaster::VerificationToken& km, | |
| const arc::mojom::keymint::TimeStampTokenPtr& mojo) { | |
| if (mojo.is_null()) { | |
| return ::testing::AssertionFailure() | |
| << "Verification Token failed as mojo is null"; | |
| } | |
| if (mojo->timestamp.is_null()) { | |
| return ::testing::AssertionFailure() | |
| << "Verification Token failed as mojo timestamp is null"; | |
| } | |
| if (km.challenge != mojo->challenge) { | |
| return ::testing::AssertionFailure() | |
| << "Verification Token challenge mismatch: km=" << km.challenge | |
| << " mojo=" << mojo->challenge; | |
| } | |
| if (km.timestamp != mojo->timestamp->milli_seconds) { | |
| return ::testing::AssertionFailure() | |
| << "Verification Token timestamp mismatch: km=" << km.timestamp | |
| << " mojo=" << mojo->timestamp->milli_seconds; | |
| } | |
| if (auto vectorMatch = | |
| VerifyVectorUint8(km.mac.data, km.mac.size(), mojo->mac); | |
| !vectorMatch) { | |
| return vectorMatch; | |
| } | |
| return ::testing::AssertionSuccess(); | |
| } | |
| } // namespace | |
| TEST(ConvertFromKeymasterMessage, Uint8Vector) { | |
| // Convert. | |
| std::vector<uint8_t> output = | |
| ConvertFromKeymasterMessage(kBlob1.data(), kBlob1.size()); | |
| // Verify. | |
| EXPECT_TRUE(VerifyVectorUint8(kBlob1.data(), kBlob1.size(), output)); | |
| } | |
| TEST(ConvertFromKeymasterMessage, EnumConversionKeyFormat) { | |
| // Verify. | |
| EXPECT_EQ(KM_KEY_FORMAT_PKCS8, | |
| ConvertEnum(arc::mojom::keymint::KeyFormat::PKCS8)); | |
| EXPECT_EQ(KM_KEY_FORMAT_X509, | |
| ConvertEnum(arc::mojom::keymint::KeyFormat::X509)); | |
| EXPECT_EQ(KM_KEY_FORMAT_RAW, | |
| ConvertEnum(arc::mojom::keymint::KeyFormat::RAW)); | |
| } | |
| TEST(ConvertFromKeymasterMessage, EnumConversionTag) { | |
| // Verify. | |
| // TODO(b/274723521): Add KM_TAG_HARDWARE_TYPE | |
| EXPECT_EQ(KM_TAG_PURPOSE, ConvertEnum(arc::mojom::keymint::Tag::PURPOSE)); | |
| EXPECT_EQ(KM_TAG_ALGORITHM, ConvertEnum(arc::mojom::keymint::Tag::ALGORITHM)); | |
| EXPECT_EQ(KM_TAG_KEY_SIZE, ConvertEnum(arc::mojom::keymint::Tag::KEY_SIZE)); | |
| EXPECT_EQ(KM_TAG_BLOCK_MODE, | |
| ConvertEnum(arc::mojom::keymint::Tag::BLOCK_MODE)); | |
| EXPECT_EQ(KM_TAG_DIGEST, ConvertEnum(arc::mojom::keymint::Tag::DIGEST)); | |
| EXPECT_EQ(KM_TAG_PADDING, ConvertEnum(arc::mojom::keymint::Tag::PADDING)); | |
| EXPECT_EQ(KM_TAG_CALLER_NONCE, | |
| ConvertEnum(arc::mojom::keymint::Tag::CALLER_NONCE)); | |
| EXPECT_EQ(KM_TAG_MIN_MAC_LENGTH, | |
| ConvertEnum(arc::mojom::keymint::Tag::MIN_MAC_LENGTH)); | |
| EXPECT_EQ(KM_TAG_EC_CURVE, ConvertEnum(arc::mojom::keymint::Tag::EC_CURVE)); | |
| EXPECT_EQ(KM_TAG_RSA_PUBLIC_EXPONENT, | |
| ConvertEnum(arc::mojom::keymint::Tag::RSA_PUBLIC_EXPONENT)); | |
| EXPECT_EQ(KM_TAG_INCLUDE_UNIQUE_ID, | |
| ConvertEnum(arc::mojom::keymint::Tag::INCLUDE_UNIQUE_ID)); | |
| EXPECT_EQ(KM_TAG_RSA_OAEP_MGF_DIGEST, | |
| ConvertEnum(arc::mojom::keymint::Tag::RSA_OAEP_MGF_DIGEST)); | |
| EXPECT_EQ(KM_TAG_BOOTLOADER_ONLY, | |
| ConvertEnum(arc::mojom::keymint::Tag::BOOTLOADER_ONLY)); | |
| EXPECT_EQ(KM_TAG_ROLLBACK_RESISTANCE, | |
| ConvertEnum(arc::mojom::keymint::Tag::ROLLBACK_RESISTANCE)); | |
| EXPECT_EQ(KM_TAG_EARLY_BOOT_ONLY, | |
| ConvertEnum(arc::mojom::keymint::Tag::EARLY_BOOT_ONLY)); | |
| EXPECT_EQ(KM_TAG_ACTIVE_DATETIME, | |
| ConvertEnum(arc::mojom::keymint::Tag::ACTIVE_DATETIME)); | |
| EXPECT_EQ(KM_TAG_ORIGINATION_EXPIRE_DATETIME, | |
| ConvertEnum(arc::mojom::keymint::Tag::ORIGINATION_EXPIRE_DATETIME)); | |
| EXPECT_EQ(KM_TAG_USAGE_EXPIRE_DATETIME, | |
| ConvertEnum(arc::mojom::keymint::Tag::USAGE_EXPIRE_DATETIME)); | |
| EXPECT_EQ(KM_TAG_MIN_SECONDS_BETWEEN_OPS, | |
| ConvertEnum(arc::mojom::keymint::Tag::MIN_SECONDS_BETWEEN_OPS)); | |
| EXPECT_EQ(KM_TAG_MAX_USES_PER_BOOT, | |
| ConvertEnum(arc::mojom::keymint::Tag::MAX_USES_PER_BOOT)); | |
| EXPECT_EQ(KM_TAG_USAGE_COUNT_LIMIT, | |
| ConvertEnum(arc::mojom::keymint::Tag::USAGE_COUNT_LIMIT)); | |
| EXPECT_EQ(KM_TAG_USER_ID, ConvertEnum(arc::mojom::keymint::Tag::USER_ID)); | |
| EXPECT_EQ(KM_TAG_USER_SECURE_ID, | |
| ConvertEnum(arc::mojom::keymint::Tag::USER_SECURE_ID)); | |
| EXPECT_EQ(KM_TAG_NO_AUTH_REQUIRED, | |
| ConvertEnum(arc::mojom::keymint::Tag::NO_AUTH_REQUIRED)); | |
| EXPECT_EQ(KM_TAG_USER_AUTH_TYPE, | |
| ConvertEnum(arc::mojom::keymint::Tag::USER_AUTH_TYPE)); | |
| EXPECT_EQ(KM_TAG_AUTH_TIMEOUT, | |
| ConvertEnum(arc::mojom::keymint::Tag::AUTH_TIMEOUT)); | |
| EXPECT_EQ(KM_TAG_ALLOW_WHILE_ON_BODY, | |
| ConvertEnum(arc::mojom::keymint::Tag::ALLOW_WHILE_ON_BODY)); | |
| EXPECT_EQ( | |
| KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED, | |
| ConvertEnum(arc::mojom::keymint::Tag::TRUSTED_USER_PRESENCE_REQUIRED)); | |
| EXPECT_EQ( | |
| KM_TAG_TRUSTED_CONFIRMATION_REQUIRED, | |
| ConvertEnum(arc::mojom::keymint::Tag::TRUSTED_CONFIRMATION_REQUIRED)); | |
| EXPECT_EQ(KM_TAG_UNLOCKED_DEVICE_REQUIRED, | |
| ConvertEnum(arc::mojom::keymint::Tag::UNLOCKED_DEVICE_REQUIRED)); | |
| EXPECT_EQ(KM_TAG_APPLICATION_ID, | |
| ConvertEnum(arc::mojom::keymint::Tag::APPLICATION_ID)); | |
| EXPECT_EQ(KM_TAG_APPLICATION_DATA, | |
| ConvertEnum(arc::mojom::keymint::Tag::APPLICATION_DATA)); | |
| EXPECT_EQ(KM_TAG_CREATION_DATETIME, | |
| ConvertEnum(arc::mojom::keymint::Tag::CREATION_DATETIME)); | |
| EXPECT_EQ(KM_TAG_ORIGIN, ConvertEnum(arc::mojom::keymint::Tag::ORIGIN)); | |
| EXPECT_EQ(KM_TAG_ROOT_OF_TRUST, | |
| ConvertEnum(arc::mojom::keymint::Tag::ROOT_OF_TRUST)); | |
| EXPECT_EQ(KM_TAG_OS_VERSION, | |
| ConvertEnum(arc::mojom::keymint::Tag::OS_VERSION)); | |
| EXPECT_EQ(KM_TAG_OS_PATCHLEVEL, | |
| ConvertEnum(arc::mojom::keymint::Tag::OS_PATCHLEVEL)); | |
| EXPECT_EQ(KM_TAG_UNIQUE_ID, ConvertEnum(arc::mojom::keymint::Tag::UNIQUE_ID)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_CHALLENGE, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_CHALLENGE)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_APPLICATION_ID, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_APPLICATION_ID)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_BRAND, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_BRAND)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_DEVICE, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_DEVICE)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_PRODUCT, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_PRODUCT)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_SERIAL, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_SERIAL)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_IMEI, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_IMEI)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_MEID, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_MEID)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_MANUFACTURER, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_MANUFACTURER)); | |
| EXPECT_EQ(KM_TAG_ATTESTATION_ID_MODEL, | |
| ConvertEnum(arc::mojom::keymint::Tag::ATTESTATION_ID_MODEL)); | |
| EXPECT_EQ(KM_TAG_VENDOR_PATCHLEVEL, | |
| ConvertEnum(arc::mojom::keymint::Tag::VENDOR_PATCHLEVEL)); | |
| EXPECT_EQ(KM_TAG_BOOT_PATCHLEVEL, | |
| ConvertEnum(arc::mojom::keymint::Tag::BOOT_PATCHLEVEL)); | |
| EXPECT_EQ(KM_TAG_DEVICE_UNIQUE_ATTESTATION, | |
| ConvertEnum(arc::mojom::keymint::Tag::DEVICE_UNIQUE_ATTESTATION)); | |
| EXPECT_EQ(KM_TAG_IDENTITY_CREDENTIAL_KEY, | |
| ConvertEnum(arc::mojom::keymint::Tag::IDENTITY_CREDENTIAL_KEY)); | |
| EXPECT_EQ(KM_TAG_STORAGE_KEY, | |
| ConvertEnum(arc::mojom::keymint::Tag::STORAGE_KEY)); | |
| EXPECT_EQ(KM_TAG_ASSOCIATED_DATA, | |
| ConvertEnum(arc::mojom::keymint::Tag::ASSOCIATED_DATA)); | |
| EXPECT_EQ(KM_TAG_NONCE, ConvertEnum(arc::mojom::keymint::Tag::NONCE)); | |
| EXPECT_EQ(KM_TAG_MAC_LENGTH, | |
| ConvertEnum(arc::mojom::keymint::Tag::MAC_LENGTH)); | |
| EXPECT_EQ(KM_TAG_RESET_SINCE_ID_ROTATION, | |
| ConvertEnum(arc::mojom::keymint::Tag::RESET_SINCE_ID_ROTATION)); | |
| EXPECT_EQ(KM_TAG_CONFIRMATION_TOKEN, | |
| ConvertEnum(arc::mojom::keymint::Tag::CONFIRMATION_TOKEN)); | |
| EXPECT_EQ(KM_TAG_CERTIFICATE_SERIAL, | |
| ConvertEnum(arc::mojom::keymint::Tag::CERTIFICATE_SERIAL)); | |
| EXPECT_EQ(KM_TAG_CERTIFICATE_SUBJECT, | |
| ConvertEnum(arc::mojom::keymint::Tag::CERTIFICATE_SUBJECT)); | |
| EXPECT_EQ(KM_TAG_CERTIFICATE_NOT_BEFORE, | |
| ConvertEnum(arc::mojom::keymint::Tag::CERTIFICATE_NOT_BEFORE)); | |
| EXPECT_EQ(KM_TAG_CERTIFICATE_NOT_AFTER, | |
| ConvertEnum(arc::mojom::keymint::Tag::CERTIFICATE_NOT_AFTER)); | |
| EXPECT_EQ(KM_TAG_MAX_BOOT_LEVEL, | |
| ConvertEnum(arc::mojom::keymint::Tag::MAX_BOOT_LEVEL)); | |
| } | |
| TEST(ConvertFromKeymasterMessage, EnumConversionKeyPurpose) { | |
| // Verify. | |
| EXPECT_EQ(KM_PURPOSE_ENCRYPT, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::ENCRYPT)); | |
| EXPECT_EQ(KM_PURPOSE_DECRYPT, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::DECRYPT)); | |
| EXPECT_EQ(KM_PURPOSE_SIGN, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::SIGN)); | |
| EXPECT_EQ(KM_PURPOSE_VERIFY, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::VERIFY)); | |
| // TODO(b/274723521): Find why KM_PURPOSE_DERIVE_KEY doesn't exist in AIDL. | |
| EXPECT_EQ(KM_PURPOSE_WRAP, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::WRAP_KEY)); | |
| EXPECT_EQ(KM_PURPOSE_AGREE_KEY, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::AGREE_KEY)); | |
| EXPECT_EQ(KM_PURPOSE_ATTEST_KEY, | |
| ConvertEnum(arc::mojom::keymint::KeyPurpose::ATTEST_KEY)); | |
| } | |
| TEST(ConvertFromKeymasterMessage, KeyParameterVector) { | |
| // Prepare. | |
| ::keymaster::AuthorizationSet input; | |
| input.push_back(keymaster_param_bool(KM_TAG_EARLY_BOOT_ONLY)); // bool | |
| input.push_back(keymaster_param_int(KM_TAG_KEY_SIZE, | |
| 128)); // int, int_rep | |
| input.push_back(keymaster_param_long(KM_TAG_USER_SECURE_ID, 65537)); // long | |
| input.push_back( | |
| keymaster_param_date(KM_TAG_USAGE_EXPIRE_DATETIME, 1507)); // date | |
| input.push_back(keymaster_param_blob(KM_TAG_APPLICATION_DATA, kBlob1.data(), | |
| kBlob1.size())); // bignum, bytes | |
| input.push_back( | |
| keymaster_param_enum(KM_TAG_ALGORITHM, | |
| KM_ALGORITHM_TRIPLE_DES)); // enum, enum_rep | |
| // Convert. | |
| std::vector<arc::mojom::keymint::KeyParameterPtr> output = | |
| ConvertFromKeymasterMessage(input); | |
| // Verify. | |
| EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(input, output)); | |
| } | |
| TEST(ConvertFromKeyMintKeyBlob, KeyMintKeyBlob) { | |
| // Prepare. | |
| ::keymaster::KeymasterKeyBlob blob(kBlob1.data(), kBlob1.size()); | |
| // Convert. | |
| auto mojo = ConvertFromKeyMintKeyBlob(blob); | |
| // Verify. | |
| EXPECT_TRUE( | |
| VerifyVectorUint8(kBlob1.data(), kBlob1.size(), mojo->key_material)); | |
| } | |
| TEST(ConvertFromKeyMintBlob, KeyMintBlob) { | |
| // Prepare. | |
| ::keymaster::KeymasterBlob blob(kBlob2.data(), kBlob2.size()); | |
| // Convert. | |
| auto mojo = ConvertFromKeyMintBlob(blob); | |
| // Verify. | |
| EXPECT_TRUE(VerifyVectorUint8(blob.data, blob.data_length, mojo->data)); | |
| } | |
| TEST(ConvertToKeymasterMessage, Buffer) { | |
| // Prepare. | |
| std::vector<uint8_t> input(kBlob1.begin(), kBlob1.end()); | |
| // Convert. | |
| ::keymaster::Buffer buffer; | |
| ConvertToKeymasterMessage(input, &buffer); | |
| uint8_t output[kBlob1.size()]; | |
| // Verify. | |
| EXPECT_TRUE(buffer.read(output, input.size())); | |
| EXPECT_TRUE(VerifyVectorUint8(output, input.size(), input)); | |
| } | |
| TEST(ConvertToKeymasterMessage, ReusedBuffer) { | |
| // Prepare. | |
| std::vector<uint8_t> input1(kBlob1.begin(), kBlob1.end()); | |
| std::vector<uint8_t> input2(kBlob2.begin(), kBlob2.end()); | |
| // Convert. | |
| ::keymaster::Buffer buffer; | |
| ConvertToKeymasterMessage(input1, &buffer); | |
| ConvertToKeymasterMessage(input2, &buffer); | |
| uint8_t output[kBlob2.size()]; | |
| // Verify. | |
| EXPECT_TRUE(buffer.read(output, kBlob2.size())); | |
| EXPECT_TRUE(VerifyVectorUint8(output, kBlob2.size(), input2)); | |
| } | |
| TEST(ConvertToKeymasterMessage, ClientIdAndAppData) { | |
| // Prepare. | |
| std::vector<uint8_t> clientId(kBlob1.begin(), kBlob1.end()); | |
| std::vector<uint8_t> appData(kBlob2.begin(), kBlob2.end()); | |
| // Convert. | |
| ::keymaster::AuthorizationSet output; | |
| ConvertToKeymasterMessage(clientId, appData, &output); | |
| // Verify. | |
| ASSERT_EQ(2, output.size()); | |
| EXPECT_EQ(KM_TAG_APPLICATION_ID, output[0].tag); | |
| EXPECT_EQ(KM_TAG_APPLICATION_DATA, output[1].tag); | |
| EXPECT_TRUE(VerifyVectorUint8(output[0].blob.data, output[0].blob.data_length, | |
| clientId)); | |
| EXPECT_TRUE(VerifyVectorUint8(output[1].blob.data, output[1].blob.data_length, | |
| appData)); | |
| } | |
| TEST(ConvertToKeymasterMessage, GetKeyCharacteristicsRequest) { | |
| // Prepare. | |
| auto input = ::arc::mojom::keymint::GetKeyCharacteristicsRequest::New( | |
| std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), | |
| std::vector<uint8_t>(kBlob2.begin(), kBlob2.end()), | |
| std::vector<uint8_t>(kBlob3.begin(), kBlob3.end())); | |
| // Convert. | |
| auto output = MakeGetKeyCharacteristicsRequest(input, kKeyMintMessageVersion); | |
| // Verify. | |
| EXPECT_TRUE(VerifyVectorUint8(output->key_blob.key_material, | |
| output->key_blob.key_material_size, | |
| input->key_blob)); | |
| ASSERT_EQ(output->additional_params.size(), 2); | |
| EXPECT_TRUE(VerifyVectorUint8(output->additional_params[0].blob.data, | |
| output->additional_params[0].blob.data_length, | |
| input->app_id)); | |
| EXPECT_TRUE(VerifyVectorUint8(output->additional_params[1].blob.data, | |
| output->additional_params[1].blob.data_length, | |
| input->app_data)); | |
| } | |
| TEST(ConvertToKeymasterMessage, GenerateKeyRequest) { | |
| // Prepare. | |
| auto input = arc::mojom::keymint::GenerateKeyRequest::New( | |
| KeyParameterVector(), CreateAttestationKey()); | |
| // Convert. | |
| auto output = MakeGenerateKeyRequest(input, kKeyMintMessageVersion); | |
| // Verify. | |
| ASSERT_TRUE(output); | |
| EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(output->key_description, | |
| input->key_params)); | |
| ASSERT_TRUE(input->attestation_key); | |
| EXPECT_TRUE(VerifyAttestationKey( | |
| output->attestation_signing_key_blob, output->attest_key_params, | |
| output->issuer_subject, input->attestation_key)); | |
| } | |
| TEST(ConvertToMessage, ImportKeyRequest) { | |
| // Prepare. | |
| auto input = arc::mojom::keymint::ImportKeyRequest::New( | |
| KeyParameterVector(), arc::mojom::keymint::KeyFormat::PKCS8, | |
| std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), | |
| CreateAttestationKey()); | |
| // Convert. | |
| auto output = MakeImportKeyRequest(std::move(input), kKeyMintMessageVersion); | |
| // Verify. | |
| ASSERT_TRUE(output); | |
| EXPECT_EQ(static_cast<keymaster_key_format_t>(input->key_format), | |
| output->key_format); | |
| EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(output->key_description, | |
| input->key_params)); | |
| EXPECT_TRUE(VerifyVectorUint8(output->key_data.key_material, | |
| output->key_data.key_material_size, | |
| input->key_data)); | |
| ASSERT_TRUE(input->attestation_key); | |
| EXPECT_TRUE(VerifyAttestationKey( | |
| output->attestation_signing_key_blob, output->attest_key_params, | |
| output->issuer_subject, input->attestation_key)); | |
| } | |
| TEST(ConvertToMessage, ImportWrappedKeyRequest) { | |
| // Prepare. | |
| uint64_t password_sid = 703710923123; | |
| uint64_t biometric_sid = 2702433194597; | |
| auto input = arc::mojom::keymint::ImportWrappedKeyRequest::New( | |
| std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), | |
| std::vector<uint8_t>(kBlob2.begin(), kBlob2.end()), | |
| std::vector<uint8_t>(kBlob3.begin(), kBlob3.end()), KeyParameterVector(), | |
| password_sid, biometric_sid); | |
| // Convert. | |
| auto output = MakeImportWrappedKeyRequest(input, kKeyMintMessageVersion); | |
| // Verify. | |
| ASSERT_TRUE(output); | |
| EXPECT_TRUE(VerifyVectorUint8(output->wrapped_key.key_material, | |
| output->wrapped_key.key_material_size, | |
| input->wrapped_key_data)); | |
| EXPECT_TRUE(VerifyVectorUint8(output->wrapping_key.key_material, | |
| output->wrapping_key.key_material_size, | |
| input->wrapping_key_blob)); | |
| EXPECT_TRUE(VerifyVectorUint8(output->masking_key.key_material, | |
| output->masking_key.key_material_size, | |
| input->masking_key)); | |
| EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(output->additional_params, | |
| input->unwrapping_params)); | |
| EXPECT_EQ(output->password_sid, input->password_sid); | |
| EXPECT_EQ(output->biometric_sid, input->biometric_sid); | |
| } | |
| TEST(ConvertToMessage, UpgradeKeyRequest) { | |
| // Prepare. | |
| auto input = arc::mojom::keymint::UpgradeKeyRequest::New( | |
| std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), KeyParameterVector()); | |
| // Convert. | |
| auto output = MakeUpgradeKeyRequest(std::move(input), kKeyMintMessageVersion); | |
| // Verify. | |
| EXPECT_TRUE(VerifyVectorUint8(output->key_blob.key_material, | |
| output->key_blob.key_material_size, | |
| input->key_blob_to_upgrade)); | |
| EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(output->upgrade_params, | |
| input->upgrade_params)); | |
| } | |
| TEST(ConvertToKeymasterMessage, BeginOperationRequest) { | |
| // Prepare. | |
| ::arc::mojom::keymint::HardwareAuthTokenPtr auth_token_ptr = | |
| CreateHardwareAuthToken(); | |
| auto input = arc::mojom::keymint::BeginRequest::New( | |
| arc::mojom::keymint::KeyPurpose::AGREE_KEY, | |
| std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), KeyParameterVector(), | |
| std::move(auth_token_ptr)); | |
| // Convert. | |
| auto output = | |
| MakeBeginOperationRequest(std::move(input), kKeyMintMessageVersion); | |
| // Verify. | |
| EXPECT_EQ(output->purpose, | |
| static_cast<keymaster_purpose_t>(input->key_purpose)); | |
| EXPECT_TRUE(VerifyVectorUint8(output->key_blob.key_material, | |
| output->key_blob.key_material_size, | |
| input->key_blob)); | |
| EXPECT_TRUE(VerifyKeyParametersWithStrictInputs(output->additional_params, | |
| input->params)); | |
| EXPECT_TRUE( | |
| VerifyHardwareAuthToken(output->additional_params, *input->auth_token)); | |
| } | |
| TEST(ConvertToMessage, UpdateOperationRequest) { | |
| // Prepare. | |
| ::arc::mojom::keymint::HardwareAuthTokenPtr auth_token_ptr = | |
| CreateHardwareAuthToken(); | |
| ::arc::mojom::keymint::TimeStampTokenPtr time_token_ptr = | |
| CreateTimeStampToken(); | |
| auto input = arc::mojom::keymint::UpdateRequest::New( | |
| 65537, std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), | |
| std::move(auth_token_ptr), std::move(time_token_ptr)); | |
| // Convert. | |
| auto output = MakeUpdateOperationRequest(input, kKeyMintMessageVersion); | |
| // Verify. | |
| // We are not verifying the TimeStampTokenPtr now as it is not | |
| // used in the KeyMint Reference implementation. | |
| EXPECT_EQ(output->op_handle, input->op_handle); | |
| EXPECT_TRUE(VerifyVectorUint8(output->input.begin(), | |
| output->input.available_read(), input->input)); | |
| EXPECT_TRUE( | |
| VerifyHardwareAuthToken(output->additional_params, *input->auth_token)); | |
| } | |
| TEST(ConvertToMessage, DeviceLockedRequest) { | |
| // Prepare. | |
| bool password_only = true; | |
| ::arc::mojom::keymint::TimeStampTokenPtr time_token_ptr = | |
| CreateTimeStampToken(); | |
| // Convert. | |
| auto output = MakeDeviceLockedRequest(password_only, time_token_ptr, | |
| kKeyMintMessageVersion); | |
| // Verify. | |
| ASSERT_TRUE(output); | |
| EXPECT_EQ(output->passwordOnly, password_only); | |
| EXPECT_TRUE(VerifyVerificationToken(output->token, time_token_ptr)); | |
| } | |
| TEST(ConvertToMessage, FinishOperationRequest) { | |
| // Prepare. | |
| ::arc::mojom::keymint::HardwareAuthTokenPtr auth_token_ptr = | |
| CreateHardwareAuthToken(); | |
| ::arc::mojom::keymint::TimeStampTokenPtr time_token_ptr = | |
| CreateTimeStampToken(); | |
| auto input = arc::mojom::keymint::FinishRequest::New( | |
| 65537, std::vector<uint8_t>(kBlob1.begin(), kBlob1.end()), | |
| std::vector<uint8_t>(kBlob2.begin(), kBlob2.end()), | |
| std::move(auth_token_ptr), std::move(time_token_ptr), | |
| std::vector<uint8_t>(kBlob3.begin(), kBlob3.end())); | |
| // Convert. | |
| auto output = MakeFinishOperationRequest(input, kKeyMintMessageVersion); | |
| // Verify. | |
| ASSERT_TRUE(input); | |
| ASSERT_TRUE(output); | |
| EXPECT_EQ(output->op_handle, input->op_handle); | |
| EXPECT_TRUE(VerifyVectorUint8(output->input.begin(), | |
| output->input.available_read(), | |
| input->input.value())); | |
| EXPECT_TRUE(VerifyVectorUint8(output->signature.begin(), | |
| output->signature.available_read(), | |
| input->signature.value())); | |
| EXPECT_TRUE( | |
| VerifyHardwareAuthToken(output->additional_params, *input->auth_token)); | |
| } | |
| TEST(PrepareResult, GenerateEcdsaP256KeyPairResultOrErrorPtr) { | |
| // Prepare. | |
| ::keymaster::GenerateRkpKeyResponse input(kKeyMintMessageVersion); | |
| input.error = KM_ERROR_OK; | |
| ::keymaster::KeymasterBlob maced_public_key(kBlob1.data(), kBlob1.size()); | |
| input.maced_public_key = maced_public_key; | |
| ::keymaster::KeymasterKeyBlob key_blob(kBlob2.data(), kBlob2.size()); | |
| input.key_blob = key_blob; | |
| // Convert. | |
| auto mojo = MakeGenerateEcdsaP256KeyPairResult(input); | |
| // Verify. | |
| EXPECT_TRUE(mojo->is_key_pair_result()); | |
| EXPECT_TRUE( | |
| VerifyVectorUint8(maced_public_key.data, maced_public_key.data_length, | |
| mojo->get_key_pair_result()->maced_public_key->data)); | |
| // Verify. | |
| EXPECT_TRUE(VerifyVectorUint8( | |
| key_blob.key_material, key_blob.key_material_size, | |
| mojo->get_key_pair_result()->handle_to_private_key->key_material)); | |
| } | |
| } // namespace arc::keymint |