1 // Copyright 2017 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/daead/deterministic_aead_config.h"
18
19 #include <list>
20 #include <memory>
21 #include <utility>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "tink/config/tink_fips.h"
27 #include "tink/daead/aes_siv_key.h"
28 #include "tink/daead/aes_siv_key_manager.h"
29 #include "tink/daead/aes_siv_parameters.h"
30 #include "tink/daead/deterministic_aead_key_templates.h"
31 #include "tink/deterministic_aead.h"
32 #include "tink/insecure_secret_key_access.h"
33 #include "tink/internal/mutable_serialization_registry.h"
34 #include "tink/internal/proto_key_serialization.h"
35 #include "tink/internal/proto_parameters_serialization.h"
36 #include "tink/keyset_handle.h"
37 #include "tink/partial_key_access.h"
38 #include "tink/registry.h"
39 #include "tink/util/status.h"
40 #include "tink/util/test_matchers.h"
41 #include "tink/util/test_util.h"
42
43 namespace crypto {
44 namespace tink {
45 namespace {
46
47 using ::crypto::tink::test::DummyDeterministicAead;
48 using ::crypto::tink::test::IsOk;
49 using ::crypto::tink::test::StatusIs;
50 using ::google::crypto::tink::KeyData;
51 using ::google::crypto::tink::OutputPrefixType;
52 using ::testing::Eq;
53
54 class DeterministicAeadConfigTest : public ::testing::Test {
55 protected:
SetUp()56 void SetUp() override {
57 Registry::Reset();
58 internal::MutableSerializationRegistry::GlobalInstance().Reset();
59 }
60 };
61
TEST_F(DeterministicAeadConfigTest,Basic)62 TEST_F(DeterministicAeadConfigTest, Basic) {
63 if (IsFipsModeEnabled()) {
64 GTEST_SKIP() << "Not supported in FIPS-only mode";
65 }
66
67 EXPECT_THAT(Registry::get_key_manager<DeterministicAead>(
68 AesSivKeyManager().get_key_type())
69 .status(),
70 StatusIs(absl::StatusCode::kNotFound));
71 EXPECT_THAT(DeterministicAeadConfig::Register(), IsOk());
72 EXPECT_THAT(Registry::get_key_manager<DeterministicAead>(
73 AesSivKeyManager().get_key_type())
74 .status(),
75 IsOk());
76 }
77
78 // Tests that the DeterministicAeadWrapper has been properly registered and we
79 // can wrap primitives.
TEST_F(DeterministicAeadConfigTest,WrappersRegistered)80 TEST_F(DeterministicAeadConfigTest, WrappersRegistered) {
81 if (IsFipsModeEnabled()) {
82 GTEST_SKIP() << "Not supported in FIPS-only mode";
83 }
84
85 ASSERT_TRUE(DeterministicAeadConfig::Register().ok());
86
87 google::crypto::tink::KeysetInfo::KeyInfo key_info;
88 key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED);
89 key_info.set_key_id(1234);
90 key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::RAW);
91 auto primitive_set = absl::make_unique<PrimitiveSet<DeterministicAead>>();
92 ASSERT_THAT(
93 primitive_set->set_primary(
94 primitive_set
95 ->AddPrimitive(absl::make_unique<DummyDeterministicAead>("dummy"),
96 key_info)
97 .value()),
98 IsOk());
99
100 auto registry_wrapped = Registry::Wrap(std::move(primitive_set));
101
102 ASSERT_TRUE(registry_wrapped.ok()) << registry_wrapped.status();
103 auto encryption_result =
104 registry_wrapped.value()->EncryptDeterministically("secret", "");
105 ASSERT_TRUE(encryption_result.ok());
106
107 auto decryption_result =
108 DummyDeterministicAead("dummy").DecryptDeterministically(
109 encryption_result.value(), "");
110 ASSERT_TRUE(decryption_result.status().ok());
111 EXPECT_THAT(decryption_result.value(), Eq("secret"));
112
113 decryption_result = DummyDeterministicAead("dummy").DecryptDeterministically(
114 encryption_result.value(), "wrong");
115 EXPECT_FALSE(decryption_result.status().ok());
116 }
117
TEST_F(DeterministicAeadConfigTest,RegisterFipsValidTemplates)118 TEST_F(DeterministicAeadConfigTest, RegisterFipsValidTemplates) {
119 if (!IsFipsModeEnabled()) {
120 GTEST_SKIP() << "Only supported in FIPS-only mode";
121 }
122
123 EXPECT_THAT(DeterministicAeadConfig::Register(), IsOk());
124
125 // Check that we can not retrieve non-FIPS key handle
126 std::list<google::crypto::tink::KeyTemplate> non_fips_key_templates;
127 non_fips_key_templates.push_back(DeterministicAeadKeyTemplates::Aes256Siv());
128
129 for (auto key_template : non_fips_key_templates) {
130 auto new_keyset_handle_result = KeysetHandle::GenerateNew(key_template);
131 EXPECT_THAT(new_keyset_handle_result.status(),
132 StatusIs(absl::StatusCode::kNotFound));
133 }
134 }
135
TEST_F(DeterministicAeadConfigTest,AesSivProtoParamsSerializationRegistered)136 TEST_F(DeterministicAeadConfigTest, AesSivProtoParamsSerializationRegistered) {
137 if (IsFipsModeEnabled()) {
138 GTEST_SKIP() << "Not supported in FIPS-only mode";
139 }
140
141 util::StatusOr<internal::ProtoParametersSerialization>
142 proto_params_serialization =
143 internal::ProtoParametersSerialization::Create(
144 DeterministicAeadKeyTemplates::Aes256Siv());
145 ASSERT_THAT(proto_params_serialization, IsOk());
146
147 util::StatusOr<std::unique_ptr<Parameters>> parsed_params =
148 internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
149 *proto_params_serialization);
150 ASSERT_THAT(parsed_params.status(), StatusIs(absl::StatusCode::kNotFound));
151
152 util::StatusOr<AesSivParameters> params = AesSivParameters::Create(
153 /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink);
154 ASSERT_THAT(params, IsOk());
155
156 util::StatusOr<std::unique_ptr<Serialization>> serialized_params =
157 internal::MutableSerializationRegistry::GlobalInstance()
158 .SerializeParameters<internal::ProtoParametersSerialization>(*params);
159 ASSERT_THAT(serialized_params.status(),
160 StatusIs(absl::StatusCode::kNotFound));
161
162 ASSERT_THAT(DeterministicAeadConfig::Register(), IsOk());
163
164 util::StatusOr<std::unique_ptr<Parameters>> parsed_params2 =
165 internal::MutableSerializationRegistry::GlobalInstance().ParseParameters(
166 *proto_params_serialization);
167 ASSERT_THAT(parsed_params2, IsOk());
168
169 util::StatusOr<std::unique_ptr<Serialization>> serialized_params2 =
170 internal::MutableSerializationRegistry::GlobalInstance()
171 .SerializeParameters<internal::ProtoParametersSerialization>(*params);
172 ASSERT_THAT(serialized_params2, IsOk());
173 }
174
TEST_F(DeterministicAeadConfigTest,AesSivProtoKeySerializationRegistered)175 TEST_F(DeterministicAeadConfigTest, AesSivProtoKeySerializationRegistered) {
176 if (IsFipsModeEnabled()) {
177 GTEST_SKIP() << "Not supported in FIPS-only mode";
178 }
179
180 google::crypto::tink::AesSivKey key_proto;
181 key_proto.set_version(0);
182 key_proto.set_key_value(subtle::Random::GetRandomBytes(64));
183
184 util::StatusOr<internal::ProtoKeySerialization> proto_key_serialization =
185 internal::ProtoKeySerialization::Create(
186 "type.googleapis.com/google.crypto.tink.AesSivKey",
187 RestrictedData(key_proto.SerializeAsString(),
188 InsecureSecretKeyAccess::Get()),
189 KeyData::SYMMETRIC, OutputPrefixType::TINK, /*id_requirement=*/123);
190 ASSERT_THAT(proto_key_serialization, IsOk());
191
192 util::StatusOr<std::unique_ptr<Key>> parsed_key =
193 internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
194 *proto_key_serialization, InsecureSecretKeyAccess::Get());
195 ASSERT_THAT(parsed_key.status(), StatusIs(absl::StatusCode::kNotFound));
196
197 util::StatusOr<AesSivParameters> params = AesSivParameters::Create(
198 /*key_size_in_bytes=*/64, AesSivParameters::Variant::kTink);
199 ASSERT_THAT(params, IsOk());
200
201 util::StatusOr<AesSivKey> key =
202 AesSivKey::Create(*params,
203 RestrictedData(subtle::Random::GetRandomBytes(64),
204 InsecureSecretKeyAccess::Get()),
205 /*id_requirement=*/123, GetPartialKeyAccess());
206 ASSERT_THAT(key, IsOk());
207
208 util::StatusOr<std::unique_ptr<Serialization>> serialized_key =
209 internal::MutableSerializationRegistry::GlobalInstance()
210 .SerializeKey<internal::ProtoKeySerialization>(
211 *key, InsecureSecretKeyAccess::Get());
212 ASSERT_THAT(serialized_key.status(), StatusIs(absl::StatusCode::kNotFound));
213
214 ASSERT_THAT(DeterministicAeadConfig::Register(), IsOk());
215
216 util::StatusOr<std::unique_ptr<Key>> parsed_key2 =
217 internal::MutableSerializationRegistry::GlobalInstance().ParseKey(
218 *proto_key_serialization, InsecureSecretKeyAccess::Get());
219 ASSERT_THAT(parsed_key2, IsOk());
220
221 util::StatusOr<std::unique_ptr<Serialization>> serialized_key2 =
222 internal::MutableSerializationRegistry::GlobalInstance()
223 .SerializeKey<internal::ProtoKeySerialization>(
224 *key, InsecureSecretKeyAccess::Get());
225 ASSERT_THAT(serialized_key2, IsOk());
226 }
227
228 } // namespace
229 } // namespace tink
230 } // namespace crypto
231