blob: 5ac23e60b981e7ede78d75dab724a2bf5d1e852d [file] [log] [blame]
// 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