| // Copyright 2022 Google LLC |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| #include "tink/proto_keyset_format.h" |
| |
| #include <memory> |
| #include <string> |
| |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "absl/strings/escaping.h" |
| #include "tink/config/tink_config.h" |
| #include "tink/insecure_secret_key_access.h" |
| #include "tink/internal/legacy_proto_parameters.h" |
| #include "tink/internal/proto_parameters_serialization.h" |
| #include "tink/keyset_handle_builder.h" |
| #include "tink/mac.h" |
| #include "tink/mac/mac_key_templates.h" |
| #include "tink/signature/signature_key_templates.h" |
| #include "tink/util/secret_data.h" |
| #include "tink/util/test_matchers.h" |
| |
| namespace crypto { |
| namespace tink { |
| |
| namespace { |
| |
| using ::crypto::tink::internal::LegacyProtoParameters; |
| using ::crypto::tink::internal::ProtoParametersSerialization; |
| using ::crypto::tink::test::IsOk; |
| using ::crypto::tink::util::SecretData; |
| using ::crypto::tink::util::SecretDataAsStringView; |
| using ::testing::Eq; |
| using ::testing::Not; |
| |
| class SerializeKeysetToProtoKeysetFormatTest : public ::testing::Test { |
| protected: |
| void SetUp() override { |
| auto status = TinkConfig::Register(); |
| ASSERT_THAT(status, IsOk()); |
| } |
| }; |
| |
| util::StatusOr<LegacyProtoParameters> CmacParameters() { |
| util::StatusOr<ProtoParametersSerialization> serialization = |
| ProtoParametersSerialization::Create(MacKeyTemplates::AesCmac()); |
| if (!serialization.ok()) return serialization.status(); |
| |
| return LegacyProtoParameters(*serialization); |
| } |
| |
| util::StatusOr<LegacyProtoParameters> EcdsaParameters() { |
| util::StatusOr<ProtoParametersSerialization> serialization = |
| ProtoParametersSerialization::Create(SignatureKeyTemplates::EcdsaP256()); |
| if (!serialization.ok()) return serialization.status(); |
| |
| return LegacyProtoParameters(*serialization); |
| } |
| |
| TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParseSingleKey) { |
| util::StatusOr<internal::LegacyProtoParameters> parameters = |
| CmacParameters(); |
| ASSERT_THAT(parameters, IsOk()); |
| |
| util::StatusOr<KeysetHandle> handle = |
| KeysetHandleBuilder() |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kEnabled, /*is_primary=*/true, |
| /*id=*/123)) |
| .Build(); |
| ASSERT_THAT(handle, IsOk()); |
| |
| crypto::tink::util::StatusOr<SecretData> serialization = |
| SerializeKeysetToProtoKeysetFormat(*handle, |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(serialization, IsOk()); |
| |
| util::StatusOr<KeysetHandle> parsed_handle = ParseKeysetFromProtoKeysetFormat( |
| SecretDataAsStringView(*serialization), InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(parsed_handle, IsOk()); |
| ASSERT_THAT(handle->size(), Eq(1)); |
| ASSERT_THAT(parsed_handle->size(), Eq(1)); |
| |
| EXPECT_TRUE(*(*handle)[0].GetKey() == *(*parsed_handle)[0].GetKey()); |
| EXPECT_TRUE((*handle)[0].GetId() == (*parsed_handle)[0].GetId()); |
| EXPECT_TRUE((*handle)[0].GetStatus() == (*parsed_handle)[0].GetStatus()); |
| } |
| |
| TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParseMultipleKeys) { |
| util::StatusOr<internal::LegacyProtoParameters> parameters = |
| CmacParameters(); |
| ASSERT_THAT(parameters, IsOk()); |
| |
| util::StatusOr<KeysetHandle> handle = |
| KeysetHandleBuilder() |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kEnabled, /*is_primary=*/false, |
| /*id=*/123)) |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kEnabled, /*is_primary=*/true, |
| /*id=*/125)) |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kDisabled, /*is_primary=*/true, |
| /*id=*/127)) |
| .Build(); |
| ASSERT_THAT(handle, IsOk()); |
| |
| crypto::tink::util::StatusOr<SecretData> serialization = |
| SerializeKeysetToProtoKeysetFormat(*handle, |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(serialization, IsOk()); |
| |
| util::StatusOr<KeysetHandle> parsed_handle = ParseKeysetFromProtoKeysetFormat( |
| SecretDataAsStringView(*serialization), InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(parsed_handle, IsOk()); |
| ASSERT_THAT(handle->size(), Eq(3)); |
| ASSERT_THAT(parsed_handle->size(), Eq(3)); |
| |
| EXPECT_TRUE(*(*handle)[0].GetKey() == *(*parsed_handle)[0].GetKey()); |
| EXPECT_TRUE((*handle)[0].GetId() == (*parsed_handle)[0].GetId()); |
| EXPECT_TRUE((*handle)[0].GetStatus() == (*parsed_handle)[0].GetStatus()); |
| |
| EXPECT_TRUE(*(*handle)[1].GetKey() == *(*parsed_handle)[1].GetKey()); |
| EXPECT_TRUE((*handle)[1].GetId() == (*parsed_handle)[1].GetId()); |
| EXPECT_TRUE((*handle)[1].GetStatus() == (*parsed_handle)[1].GetStatus()); |
| |
| EXPECT_TRUE(*(*handle)[2].GetKey() == *(*parsed_handle)[2].GetKey()); |
| EXPECT_TRUE((*handle)[2].GetId() == (*parsed_handle)[2].GetId()); |
| EXPECT_TRUE((*handle)[2].GetStatus() == (*parsed_handle)[2].GetStatus()); |
| } |
| |
| TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeNoAccessFails) { |
| util::StatusOr<internal::LegacyProtoParameters> parameters = |
| CmacParameters(); |
| ASSERT_THAT(parameters, IsOk()); |
| |
| util::StatusOr<KeysetHandle> handle = |
| KeysetHandleBuilder() |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kEnabled, /*is_primary=*/true, |
| /*id=*/123)) |
| .Build(); |
| ASSERT_THAT(handle, IsOk()); |
| |
| crypto::tink::util::StatusOr<std::string> serialization = |
| SerializeKeysetWithoutSecretToProtoKeysetFormat(*handle); |
| ASSERT_THAT(serialization, Not(IsOk())); |
| } |
| |
| TEST_F(SerializeKeysetToProtoKeysetFormatTest, ParseNoAccessFails) { |
| util::StatusOr<internal::LegacyProtoParameters> parameters = |
| CmacParameters(); |
| ASSERT_THAT(parameters, IsOk()); |
| |
| util::StatusOr<KeysetHandle> handle = |
| KeysetHandleBuilder() |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kEnabled, /*is_primary=*/true, |
| /*id=*/123)) |
| .Build(); |
| ASSERT_THAT(handle, IsOk()); |
| |
| crypto::tink::util::StatusOr<SecretData> serialization = |
| SerializeKeysetToProtoKeysetFormat(*handle, |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(serialization, IsOk()); |
| |
| util::StatusOr<KeysetHandle> parsed_handle = |
| ParseKeysetWithoutSecretFromProtoKeysetFormat( |
| SecretDataAsStringView(*serialization)); |
| ASSERT_THAT(parsed_handle, Not(IsOk())); |
| } |
| |
| TEST_F(SerializeKeysetToProtoKeysetFormatTest, TestVector) { |
| std::string serialized_keyset = absl::HexStringToBytes( |
| "0895e59bcc0612680a5c0a2e747970652e676f6f676c65617069732e636f6d2f676f6f67" |
| "6c652e63727970746f2e74696e6b2e486d61634b657912281a20cca20f02278003b3513f" |
| "5d01759ac1302f7d883f2f4a40025532ee1b11f9e587120410100803180110011895e59b" |
| "cc062001"); |
| crypto::tink::util::StatusOr<KeysetHandle> keyset_handle = |
| ParseKeysetFromProtoKeysetFormat(serialized_keyset, |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(keyset_handle.status(), IsOk()); |
| crypto::tink::util::StatusOr<std::unique_ptr<Mac>> mac = |
| (*keyset_handle).GetPrimitive<Mac>(); |
| ASSERT_THAT(mac.status(), IsOk()); |
| ASSERT_THAT( |
| (*mac)->VerifyMac( |
| absl::HexStringToBytes("016986f2956092d259136923c6f4323557714ec499"), |
| "data"), |
| IsOk()); |
| } |
| |
| TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParsePublicKey) { |
| util::StatusOr<internal::LegacyProtoParameters> parameters = |
| EcdsaParameters(); |
| ASSERT_THAT(parameters, IsOk()); |
| |
| util::StatusOr<KeysetHandle> handle = |
| KeysetHandleBuilder() |
| .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams( |
| *parameters, KeyStatus::kEnabled, /*is_primary=*/true, |
| /*id=*/123)) |
| .Build(); |
| ASSERT_THAT(handle, IsOk()); |
| util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle = |
| handle->GetPublicKeysetHandle(); |
| ASSERT_THAT(public_handle, IsOk()); |
| |
| |
| crypto::tink::util::StatusOr<SecretData> serialization1 = |
| SerializeKeysetToProtoKeysetFormat(**public_handle, |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(serialization1, IsOk()); |
| crypto::tink::util::StatusOr<std::string> serialization2 = |
| SerializeKeysetWithoutSecretToProtoKeysetFormat(**public_handle); |
| ASSERT_THAT(serialization2, IsOk()); |
| |
| util::StatusOr<KeysetHandle> parsed_handle1 = |
| ParseKeysetFromProtoKeysetFormat(SecretDataAsStringView(*serialization1), |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(parsed_handle1, IsOk()); |
| util::StatusOr<KeysetHandle> parsed_handle2 = |
| ParseKeysetWithoutSecretFromProtoKeysetFormat( |
| SecretDataAsStringView(*serialization1)); |
| ASSERT_THAT(parsed_handle2, IsOk()); |
| util::StatusOr<KeysetHandle> parsed_handle3 = |
| ParseKeysetFromProtoKeysetFormat(*serialization2, |
| InsecureSecretKeyAccess::Get()); |
| ASSERT_THAT(parsed_handle3, IsOk()); |
| util::StatusOr<KeysetHandle> parsed_handle4 = |
| ParseKeysetWithoutSecretFromProtoKeysetFormat(*serialization2); |
| ASSERT_THAT(parsed_handle4, IsOk()); |
| |
| ASSERT_THAT((*public_handle)->size(), Eq(1)); |
| ASSERT_THAT(parsed_handle1->size(), Eq(1)); |
| ASSERT_THAT(parsed_handle2->size(), Eq(1)); |
| ASSERT_THAT(parsed_handle3->size(), Eq(1)); |
| ASSERT_THAT(parsed_handle4->size(), Eq(1)); |
| |
| // TODO(b/277791403): Replace with KeysetHandle::Entry equality checks. |
| EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle1)[0].GetKey()); |
| EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle2)[0].GetKey()); |
| EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle3)[0].GetKey()); |
| EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle4)[0].GetKey()); |
| |
| EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle1)[0].GetId()); |
| EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle2)[0].GetId()); |
| EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle3)[0].GetId()); |
| EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle4)[0].GetId()); |
| |
| EXPECT_TRUE((**public_handle)[0].GetStatus() == |
| (*parsed_handle1)[0].GetStatus()); |
| EXPECT_TRUE((**public_handle)[0].GetStatus() == |
| (*parsed_handle2)[0].GetStatus()); |
| EXPECT_TRUE((**public_handle)[0].GetStatus() == |
| (*parsed_handle3)[0].GetStatus()); |
| EXPECT_TRUE((**public_handle)[0].GetStatus() == |
| (*parsed_handle4)[0].GetStatus()); |
| } |
| |
| |
| } // namespace |
| |
| } // namespace tink |
| } // namespace crypto |