Skip to content

Commit

Permalink
Register PRF-based key derivation proto serialization.
Browse files Browse the repository at this point in the history
PiperOrigin-RevId: 707586106
Change-Id: Ieab1caa2f62f779111d1e5cd6edae1fe28a36770
  • Loading branch information
willinois authored and copybara-github committed Dec 18, 2024
1 parent a3af058 commit 4b887da
Show file tree
Hide file tree
Showing 4 changed files with 275 additions and 3 deletions.
24 changes: 24 additions & 0 deletions tink/keyderivation/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ cc_library(
visibility = ["//visibility:public"],
deps = [
":keyset_deriver_wrapper",
":prf_based_key_derivation_proto_serialization",
"//tink:registry",
"//tink/config:tink_fips",
"//tink/keyderivation/internal:prf_based_deriver_key_manager",
Expand Down Expand Up @@ -169,18 +170,41 @@ cc_test(
":key_derivation_config",
":key_derivation_key_templates",
":keyset_deriver",
":prf_based_key_derivation_key",
":prf_based_key_derivation_parameters",
"//proto:aes_cmac_prf_cc_proto",
"//proto:prf_based_deriver_cc_proto",
"//proto:tink_cc_proto",
"//proto:xchacha20_poly1305_cc_proto",
"//tink:aead",
"//tink:key_status",
"//tink:keyset_handle",
"//tink:parameters",
"//tink:partial_key_access",
"//tink:proto_parameters_format",
"//tink:registry",
"//tink:restricted_data",
"//tink/aead:aead_config",
"//tink/aead:aead_key_templates",
"//tink/aead:aes_gcm_key_manager",
"//tink/aead:xchacha20_poly1305_parameters",
"//tink/config:global_registry",
"//tink/internal:fips_utils",
"//tink/internal:internal_insecure_secret_key_access",
"//tink/internal:legacy_proto_key",
"//tink/internal:legacy_proto_parameters",
"//tink/internal:mutable_serialization_registry",
"//tink/keyderivation/internal:prf_based_deriver_key_manager",
"//tink/prf:aes_cmac_prf_key",
"//tink/prf:aes_cmac_prf_parameters",
"//tink/prf:prf_config",
"//tink/prf:prf_key_templates",
"//tink/util:statusor",
"//tink/util:test_matchers",
"@com_google_absl//absl/log:check",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/strings:string_view",
"@com_google_googletest//:gtest_main",
],
)
Expand Down
24 changes: 24 additions & 0 deletions tink/keyderivation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ tink_cc_library(
key_derivation_config.h
DEPS
tink::keyderivation::keyset_deriver_wrapper
tink::keyderivation::prf_based_key_derivation_proto_serialization
absl::memory
tink::core::registry
tink::config::tink_fips
Expand Down Expand Up @@ -161,19 +162,42 @@ tink_cc_test(
tink::keyderivation::key_derivation_config
tink::keyderivation::key_derivation_key_templates
tink::keyderivation::keyset_deriver
tink::keyderivation::prf_based_key_derivation_key
tink::keyderivation::prf_based_key_derivation_parameters
gmock
absl::check
absl::memory
absl::status
absl::string_view
tink::core::aead
tink::core::key_status
tink::core::keyset_handle
tink::core::parameters
tink::core::partial_key_access
tink::core::proto_parameters_format
tink::core::registry
tink::core::restricted_data
tink::aead::aead_config
tink::aead::aead_key_templates
tink::aead::aes_gcm_key_manager
tink::aead::xchacha20_poly1305_parameters
tink::config::global_registry
tink::internal::fips_utils
tink::internal::internal_insecure_secret_key_access
tink::internal::legacy_proto_key
tink::internal::legacy_proto_parameters
tink::internal::mutable_serialization_registry
tink::keyderivation::internal::prf_based_deriver_key_manager
tink::prf::aes_cmac_prf_key
tink::prf::aes_cmac_prf_parameters
tink::prf::prf_config
tink::prf::prf_key_templates
tink::util::statusor
tink::util::test_matchers
tink::proto::aes_cmac_prf_cc_proto
tink::proto::prf_based_deriver_cc_proto
tink::proto::tink_cc_proto
tink::proto::xchacha20_poly1305_cc_proto
)

tink_cc_test(
Expand Down
6 changes: 6 additions & 0 deletions tink/keyderivation/key_derivation_config.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "tink/config/tink_fips.h"
#include "tink/keyderivation/internal/prf_based_deriver_key_manager.h"
#include "tink/keyderivation/keyset_deriver_wrapper.h"
#include "tink/keyderivation/prf_based_key_derivation_proto_serialization.h"
#include "tink/prf/hkdf_prf_key_manager.h"
#include "tink/registry.h"
#include "tink/util/status.h"
Expand All @@ -42,6 +43,11 @@ util::Status KeyDerivationConfig::Register() {
return util::OkStatus();
}

status = RegisterPrfBasedKeyDerivationProtoSerialization();
if (!status.ok()) {
return status;
}

// Register required key manager for PrfBasedDeriverKeyManager.
status = Registry::RegisterKeyTypeManager(
absl::make_unique<HkdfPrfKeyManager>(), true);
Expand Down
224 changes: 221 additions & 3 deletions tink/keyderivation/key_derivation_config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,79 @@

#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/log/check.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "tink/aead.h"
#include "tink/aead/aead_config.h"
#include "tink/aead/aead_key_templates.h"
#include "tink/aead/aes_gcm_key_manager.h"
#include "tink/aead/xchacha20_poly1305_parameters.h"
#include "tink/config/global_registry.h"
#include "tink/internal/fips_utils.h"
#include "tink/internal/internal_insecure_secret_key_access.h"
#include "tink/internal/legacy_proto_key.h"
#include "tink/internal/legacy_proto_parameters.h"
#include "tink/internal/mutable_serialization_registry.h"
#include "tink/key_status.h"
#include "tink/keyderivation/internal/prf_based_deriver_key_manager.h"
#include "tink/keyderivation/key_derivation_key_templates.h"
#include "tink/keyderivation/keyset_deriver.h"
#include "tink/keyderivation/prf_based_key_derivation_key.h"
#include "tink/keyderivation/prf_based_key_derivation_parameters.h"
#include "tink/keyset_handle.h"
#include "tink/parameters.h"
#include "tink/partial_key_access.h"
#include "tink/prf/aes_cmac_prf_key.h"
#include "tink/prf/aes_cmac_prf_parameters.h"
#include "tink/prf/prf_config.h"
#include "tink/prf/prf_key_templates.h"
#include "tink/proto_parameters_format.h"
#include "tink/registry.h"
#include "tink/restricted_data.h"
#include "tink/util/statusor.h"
#include "tink/util/test_matchers.h"
#include "proto/aes_cmac_prf.pb.h"
#include "proto/prf_based_deriver.pb.h"
#include "proto/tink.pb.h"
#include "proto/xchacha20_poly1305.pb.h"

namespace crypto {
namespace tink {

namespace internal {
namespace {

using ::crypto::tink::test::IsOk;
using ::crypto::tink::test::StatusIs;
using ::google::crypto::tink::AesCmacPrfKeyFormat;
using ::google::crypto::tink::KeyTemplate;
using ::google::crypto::tink::OutputPrefixType;
using ::google::crypto::tink::PrfBasedDeriverKeyFormat;
using ::google::crypto::tink::PrfBasedDeriverParams;
using ::google::crypto::tink::XChaCha20Poly1305KeyFormat;
using ::testing::HasSubstr;
using ::testing::Not;
using ::testing::NotNull;
using ::testing::Test;

constexpr absl::string_view kTypeUrl =
"type.googleapis.com/google.crypto.tink.PrfBasedDeriverKey";
constexpr absl::string_view kPrfKeyTypeUrl =
"type.googleapis.com/google.crypto.tink.AesCmacPrfKey";
constexpr absl::string_view kDerivedKeyTypeUrl =
"type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key";
constexpr absl::string_view kPrfKeyValue = "0123456789abcdef0123456789abcdef";

TEST(KeyDerivationConfigTest, Register) {
Registry::Reset();
class KeyDerivationConfigTest : public Test {
protected:
void SetUp() override {
Registry::Reset();
internal::MutableSerializationRegistry::GlobalInstance().Reset();
}
};

TEST_F(KeyDerivationConfigTest, Register) {
EXPECT_THAT(KeyDerivationKeyTemplates::CreatePrfBasedKeyTemplate(
PrfKeyTemplates::HkdfSha256(), AeadKeyTemplates::Aes256Gcm()),
Not(IsOk()));
Expand Down Expand Up @@ -85,6 +132,177 @@ TEST(KeyDerivationConfigTest, Register) {
EXPECT_EQ(plaintext, *got);
}

KeyTemplate GetAesCmacPrfKeyTemplate() {
AesCmacPrfKeyFormat key_format;
key_format.set_version(0);
key_format.set_key_size(kPrfKeyValue.size());
KeyTemplate key_template;
key_template.set_type_url(kPrfKeyTypeUrl);
key_template.set_value(key_format.SerializeAsString());
key_template.set_output_prefix_type(OutputPrefixType::RAW);
return key_template;
}

AesCmacPrfParameters GetAesCmacPrfParameters() {
util::StatusOr<AesCmacPrfParameters> parameters =
AesCmacPrfParameters::Create(kPrfKeyValue.size());
CHECK_OK(parameters);
return *parameters;
}

AesCmacPrfKey GetAesCmacPrfKey() {
util::StatusOr<AesCmacPrfKey> key = AesCmacPrfKey::Create(
RestrictedData(kPrfKeyValue,
internal::GetInsecureSecretKeyAccessInternal()),
GetPartialKeyAccess());
CHECK_OK(key);
return *key;
}

KeyTemplate GetXChaCha20Poly1305KeyTemplate() {
XChaCha20Poly1305KeyFormat key_format;
key_format.set_version(0);
KeyTemplate key_template;
key_template.set_type_url(kDerivedKeyTypeUrl);
key_template.set_value(key_format.SerializeAsString());
key_template.set_output_prefix_type(OutputPrefixType::TINK);
return key_template;
}

XChaCha20Poly1305Parameters GetXChaCha20Poly1305Parameters() {
util::StatusOr<XChaCha20Poly1305Parameters> parameters =
XChaCha20Poly1305Parameters::Create(
XChaCha20Poly1305Parameters::Variant::kTink);
CHECK_OK(parameters);
return *parameters;
}

TEST_F(KeyDerivationConfigTest,
PrfBasedKeyDerivationProtoParamsSerializationRegistered) {
if (IsFipsModeEnabled()) {
GTEST_SKIP() << "Not supported in FIPS-only mode";
}

KeyTemplate derived_key_template = GetXChaCha20Poly1305KeyTemplate();

PrfBasedDeriverKeyFormat key_format_proto;
*key_format_proto.mutable_prf_key_template() = GetAesCmacPrfKeyTemplate();
PrfBasedDeriverParams prf_based_deriver_params;
*prf_based_deriver_params.mutable_derived_key_template() =
derived_key_template;
*key_format_proto.mutable_params() = prf_based_deriver_params;

KeyTemplate key_template;
key_template.set_type_url(kTypeUrl);
key_template.set_output_prefix_type(
derived_key_template.output_prefix_type());
key_format_proto.SerializeToString(key_template.mutable_value());

util::StatusOr<std::unique_ptr<Parameters>> proto_parameters =
ParseParametersFromProtoFormat(key_template.SerializeAsString());
ASSERT_THAT(proto_parameters, IsOk());
EXPECT_THAT(
dynamic_cast<internal::LegacyProtoParameters*>(proto_parameters->get()),
NotNull());

util::StatusOr<PrfBasedKeyDerivationParameters> parameters =
PrfBasedKeyDerivationParameters::Builder()
.SetPrfParameters(GetAesCmacPrfParameters())
.SetDerivedKeyParameters(GetXChaCha20Poly1305Parameters())
.Build();
ASSERT_THAT(parameters, IsOk());
EXPECT_THAT(SerializeParametersToProtoFormat(*parameters),
StatusIs(absl::StatusCode::kNotFound));

ASSERT_THAT(KeyDerivationConfig::Register(), IsOk());

util::StatusOr<std::unique_ptr<Parameters>> parsed_parameters =
ParseParametersFromProtoFormat(key_template.SerializeAsString());
ASSERT_THAT(parsed_parameters, IsOk());
EXPECT_THAT(
dynamic_cast<PrfBasedKeyDerivationParameters*>(parsed_parameters->get()),
NotNull());

EXPECT_THAT(SerializeParametersToProtoFormat(*parameters), IsOk());
}

TEST_F(KeyDerivationConfigTest,
PrfBasedKeyDerivationProtoKeySerializationRegistered) {
if (IsFipsModeEnabled()) {
GTEST_SKIP() << "Not supported in FIPS-only mode";
}

ASSERT_THAT(AeadConfig::Register(), IsOk()); // For XChaCha20Poly1305Key
ASSERT_THAT(PrfConfig::Register(), IsOk()); // For AesCmacPrfKey

KeyTemplate derived_key_template = GetXChaCha20Poly1305KeyTemplate();

PrfBasedDeriverKeyFormat key_format_proto;
*key_format_proto.mutable_prf_key_template() = GetAesCmacPrfKeyTemplate();
PrfBasedDeriverParams prf_based_deriver_params;
*prf_based_deriver_params.mutable_derived_key_template() =
derived_key_template;
*key_format_proto.mutable_params() = prf_based_deriver_params;

KeyTemplate key_template;
key_template.set_type_url(kTypeUrl);
key_template.set_output_prefix_type(
derived_key_template.output_prefix_type());
key_format_proto.SerializeToString(key_template.mutable_value());

// NOTE: No key generation config available yet for PrfBasedDeriver keys.
ASSERT_THAT(
Registry::RegisterKeyTypeManager(
absl::make_unique<internal::PrfBasedDeriverKeyManager>(), true),
IsOk());
util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry());
ASSERT_THAT(handle, IsOk());

// Fails to parse this key type, so falls back to legacy proto key.
EXPECT_THAT(dynamic_cast<const internal::LegacyProtoKey*>(
(*handle)->GetPrimary().GetKey().get()),
NotNull());

util::StatusOr<PrfBasedKeyDerivationParameters> parameters =
PrfBasedKeyDerivationParameters::Builder()
.SetPrfParameters(GetAesCmacPrfParameters())
.SetDerivedKeyParameters(GetXChaCha20Poly1305Parameters())
.Build();
ASSERT_THAT(parameters, IsOk());
util::StatusOr<PrfBasedKeyDerivationKey> key =
PrfBasedKeyDerivationKey::Create(*parameters, GetAesCmacPrfKey(),
/*id_requirement=*/123,
GetPartialKeyAccess());
ASSERT_THAT(key, IsOk());

// Fails to serialize this key type.
EXPECT_THAT(KeysetHandleBuilder()
.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey(
*key, KeyStatus::kEnabled, /*is_primary=*/true))
.Build()
.status(),
StatusIs(absl::StatusCode::kInvalidArgument,
HasSubstr("Failed to serialize")));

ASSERT_THAT(KeyDerivationConfig::Register(), IsOk());

util::StatusOr<std::unique_ptr<KeysetHandle>> handle2 =
KeysetHandle::GenerateNew(key_template, KeyGenConfigGlobalRegistry());
ASSERT_THAT(handle2, IsOk());

EXPECT_THAT(dynamic_cast<const PrfBasedKeyDerivationKey*>(
(*handle2)->GetPrimary().GetKey().get()),
NotNull());

EXPECT_THAT(KeysetHandleBuilder()
.AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableKey(
*key, KeyStatus::kEnabled, /*is_primary=*/true))
.Build(),
IsOk());
}

} // namespace
} // namespace internal
} // namespace tink
} // namespace crypto

0 comments on commit 4b887da

Please sign in to comment.