xref: /aosp_15_r20/external/tink/cc/hybrid/internal/hpke_context_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2022 Google LLC
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/hybrid/internal/hpke_context.h"
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "tink/hybrid/internal/hpke_test_util.h"
26 #include "tink/hybrid/internal/hpke_util.h"
27 #include "tink/util/secret_data.h"
28 #include "tink/util/statusor.h"
29 #include "tink/util/test_matchers.h"
30 
31 namespace crypto {
32 namespace tink {
33 namespace internal {
34 namespace {
35 
36 using ::crypto::tink::internal::CreateHpkeTestParams;
37 using ::crypto::tink::internal::DefaultHpkeTestParams;
38 using ::crypto::tink::internal::HpkeTestParams;
39 using ::crypto::tink::test::IsOk;
40 using ::crypto::tink::test::StatusIs;
41 using ::testing::Eq;
42 using ::testing::TestWithParam;
43 using ::testing::Values;
44 
45 class HpkeContextTest : public TestWithParam<HpkeParams> {};
46 
47 INSTANTIATE_TEST_SUITE_P(
48     HpkeContextTestSuite, HpkeContextTest,
49     Values(HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256,
50                       HpkeAead::kAes128Gcm},
51            HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256,
52                       HpkeAead::kChaCha20Poly1305}));
53 
TEST_P(HpkeContextTest,SealAndOpen)54 TEST_P(HpkeContextTest, SealAndOpen) {
55   HpkeParams hpke_params = GetParam();
56   util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
57   ASSERT_THAT(params, IsOk());
58 
59   util::StatusOr<std::unique_ptr<HpkeContext>> sender_hpke_context =
60       HpkeContext::SetupSender(hpke_params, params->recipient_public_key,
61                                params->application_info);
62   ASSERT_THAT(sender_hpke_context, IsOk());
63 
64   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
65       HpkeContext::SetupRecipient(
66           hpke_params,
67           util::SecretDataFromStringView(params->recipient_private_key),
68           (*sender_hpke_context)->EncapsulatedKey(), params->application_info);
69   ASSERT_THAT(recipient_hpke_context, IsOk());
70 
71   std::vector<std::string> inputs = {"", params->plaintext};
72   std::vector<std::string> context_infos = {"", params->application_info};
73   for (const std::string& input : inputs) {
74     for (const std::string& context_info : context_infos) {
75       SCOPED_TRACE(absl::StrCat("plaintext: '", input, "', context_info: '",
76                                 context_info, "'"));
77       util::StatusOr<std::string> ciphertext =
78           (*sender_hpke_context)->Seal(input, context_info);
79       ASSERT_THAT(ciphertext, IsOk());
80 
81       util::StatusOr<std::string> plaintext =
82           (*recipient_hpke_context)->Open(*ciphertext, context_info);
83       ASSERT_THAT(plaintext, IsOk());
84 
85       EXPECT_THAT(*plaintext, Eq(input));
86     }
87   }
88 }
89 
TEST_P(HpkeContextTest,Export)90 TEST_P(HpkeContextTest, Export) {
91   HpkeParams hpke_params = GetParam();
92   util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
93   ASSERT_THAT(params, IsOk());
94 
95   util::StatusOr<std::unique_ptr<HpkeContext>> sender_hpke_context =
96       HpkeContext::SetupSender(hpke_params, params->recipient_public_key,
97                                params->application_info);
98   ASSERT_THAT(sender_hpke_context, IsOk());
99 
100   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
101       HpkeContext::SetupRecipient(
102           hpke_params,
103           util::SecretDataFromStringView(params->recipient_private_key),
104           (*sender_hpke_context)->EncapsulatedKey(), params->application_info);
105   ASSERT_THAT(recipient_hpke_context, IsOk());
106 
107   std::vector<std::string> exporter_contexts = {"", "c", "context"};
108   std::vector<int> secret_lengths = {0, 8, 16, 32, 64};
109   for (const std::string& exporter_context : exporter_contexts) {
110     for (int secret_length : secret_lengths) {
111       SCOPED_TRACE(absl::StrCat("exporter_context: '", exporter_context,
112                                 "', secret_length: '", secret_length, "'"));
113       util::StatusOr<util::SecretData> sender_secret =
114           (*sender_hpke_context)->Export(exporter_context, secret_length);
115       ASSERT_THAT(sender_secret, IsOk());
116 
117       util::StatusOr<util::SecretData> recipient_secret =
118           (*recipient_hpke_context)->Export(exporter_context, secret_length);
119       ASSERT_THAT(recipient_secret, IsOk());
120 
121       EXPECT_THAT(*sender_secret, Eq(*recipient_secret));
122     }
123   }
124 }
125 
TEST_P(HpkeContextTest,OpenTruncatedCiphertextFails)126 TEST_P(HpkeContextTest, OpenTruncatedCiphertextFails) {
127   HpkeParams hpke_params = GetParam();
128   util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
129   ASSERT_THAT(params, IsOk());
130 
131   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
132       HpkeContext::SetupRecipient(
133           hpke_params,
134           util::SecretDataFromStringView(params->recipient_private_key),
135           params->encapsulated_key, params->application_info);
136   ASSERT_THAT(recipient_hpke_context, IsOk());
137 
138   util::StatusOr<std::string> plaintext =
139       (*recipient_hpke_context)
140           ->Open(params->ciphertext, params->associated_data);
141   ASSERT_THAT(plaintext, IsOk());
142 
143   const std::string truncated_ciphertext =
144       params->ciphertext.substr(params->ciphertext.length() - 1);
145   util::StatusOr<std::string> bad_plaintext =
146       (*recipient_hpke_context)
147           ->Open(truncated_ciphertext, params->associated_data);
148   EXPECT_THAT(bad_plaintext.status(), StatusIs(absl::StatusCode::kUnknown));
149 }
150 
TEST_P(HpkeContextTest,OpenModifiedCiphertextFails)151 TEST_P(HpkeContextTest, OpenModifiedCiphertextFails) {
152   HpkeParams hpke_params = GetParam();
153   util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
154   ASSERT_THAT(params, IsOk());
155 
156   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
157       HpkeContext::SetupRecipient(
158           hpke_params,
159           util::SecretDataFromStringView(params->recipient_private_key),
160           params->encapsulated_key, params->application_info);
161   ASSERT_THAT(recipient_hpke_context, IsOk());
162 
163   util::StatusOr<std::string> plaintext =
164       (*recipient_hpke_context)
165           ->Open(params->ciphertext, params->associated_data);
166   ASSERT_THAT(plaintext, IsOk());
167 
168   const std::string modified_ciphertext =
169       absl::StrCat(params->ciphertext, "modification");
170   util::StatusOr<std::string> bad_plaintext =
171       (*recipient_hpke_context)
172           ->Open(modified_ciphertext, params->associated_data);
173   EXPECT_THAT(bad_plaintext.status(), StatusIs(absl::StatusCode::kUnknown));
174 }
175 
TEST_P(HpkeContextTest,OpenModifiedAssociatedDataFails)176 TEST_P(HpkeContextTest, OpenModifiedAssociatedDataFails) {
177   HpkeParams hpke_params = GetParam();
178   util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
179   ASSERT_THAT(params, IsOk());
180 
181   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
182       HpkeContext::SetupRecipient(
183           hpke_params,
184           util::SecretDataFromStringView(params->recipient_private_key),
185           params->encapsulated_key, params->application_info);
186   ASSERT_THAT(recipient_hpke_context, IsOk());
187 
188   util::StatusOr<std::string> plaintext =
189       (*recipient_hpke_context)
190           ->Open(params->ciphertext, params->associated_data);
191   ASSERT_THAT(plaintext, IsOk());
192 
193   const std::string modified_associated_data =
194       absl::StrCat(params->associated_data, "modification");
195   util::StatusOr<std::string> bad_plaintext =
196       (*recipient_hpke_context)
197           ->Open(params->ciphertext, modified_associated_data);
198   EXPECT_THAT(bad_plaintext.status(), StatusIs(absl::StatusCode::kUnknown));
199 }
200 
201 class HpkeContextWithBadHpkeParamTest : public TestWithParam<HpkeParams> {};
202 
203 INSTANTIATE_TEST_SUITE_P(
204     HpkeContextWithBadHpkeParamTestTestSuite, HpkeContextWithBadHpkeParamTest,
205     Values(HpkeParams{HpkeKem::kUnknownKem, HpkeKdf::kHkdfSha256,
206                       HpkeAead::kAes128Gcm},
207            HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kUnknownKdf,
208                       HpkeAead::kAes256Gcm},
209            HpkeParams{HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256,
210                       HpkeAead::kUnknownAead}));
211 
TEST_P(HpkeContextWithBadHpkeParamTest,SenderBadHpkeParamFails)212 TEST_P(HpkeContextWithBadHpkeParamTest, SenderBadHpkeParamFails) {
213   HpkeParams hpke_params = GetParam();
214   HpkeTestParams params = DefaultHpkeTestParams();
215 
216   util::StatusOr<std::unique_ptr<HpkeContext>> sender_hpke_context =
217       HpkeContext::SetupSender(hpke_params, params.recipient_public_key,
218                                params.application_info);
219   EXPECT_THAT(sender_hpke_context.status(),
220               StatusIs(absl::StatusCode::kInvalidArgument));
221 }
222 
TEST_P(HpkeContextWithBadHpkeParamTest,RecipientBadHpkeParamFails)223 TEST_P(HpkeContextWithBadHpkeParamTest, RecipientBadHpkeParamFails) {
224   HpkeParams hpke_params = GetParam();
225   HpkeTestParams params = DefaultHpkeTestParams();
226 
227   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
228       HpkeContext::SetupRecipient(
229           hpke_params,
230           util::SecretDataFromStringView(params.recipient_private_key),
231           params.encapsulated_key, params.application_info);
232   EXPECT_THAT(recipient_hpke_context.status(),
233               StatusIs(absl::StatusCode::kInvalidArgument));
234 }
235 
TEST(HpkeContextZeroLengthKeyTest,ZeroLengthPublicKeyFails)236 TEST(HpkeContextZeroLengthKeyTest, ZeroLengthPublicKeyFails) {
237   HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256,
238                             HpkeAead::kAes256Gcm};
239   HpkeTestParams params = DefaultHpkeTestParams();
240 
241   util::StatusOr<std::unique_ptr<HpkeContext>> sender_hpke_context =
242       HpkeContext::SetupSender(hpke_params, /*recipient_public_key=*/"",
243                                params.application_info);
244   EXPECT_THAT(sender_hpke_context.status(),
245               StatusIs(absl::StatusCode::kInvalidArgument));
246 }
247 
TEST(HpkeContextZeroLengthKeyTest,ZeroLengthPrivateKeyFails)248 TEST(HpkeContextZeroLengthKeyTest, ZeroLengthPrivateKeyFails) {
249   HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256,
250                             HpkeAead::kAes256Gcm};
251   HpkeTestParams params = DefaultHpkeTestParams();
252 
253   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
254       HpkeContext::SetupRecipient(
255           hpke_params,
256           /*recipient_private_key=*/util::SecretDataFromStringView(""),
257           params.encapsulated_key, params.application_info);
258   EXPECT_THAT(recipient_hpke_context.status(),
259               StatusIs(absl::StatusCode::kInvalidArgument));
260 }
261 
TEST(HpkeContextZeroLengthKeyTest,ZeroLengthEncapsulatedKeyFails)262 TEST(HpkeContextZeroLengthKeyTest, ZeroLengthEncapsulatedKeyFails) {
263   HpkeParams hpke_params = {HpkeKem::kX25519HkdfSha256, HpkeKdf::kHkdfSha256,
264                             HpkeAead::kAes256Gcm};
265   HpkeTestParams params = DefaultHpkeTestParams();
266 
267   util::StatusOr<std::unique_ptr<HpkeContext>> recipient_hpke_context =
268       HpkeContext::SetupRecipient(
269           hpke_params,
270           util::SecretDataFromStringView(params.recipient_private_key),
271           /*encapsulated_key=*/"", params.application_info);
272   EXPECT_THAT(recipient_hpke_context.status(),
273               StatusIs(absl::StatusCode::kInvalidArgument));
274 }
275 
TEST(ConcatenatePayloadTest,ConcatenatePayloadSucceeds)276 TEST(ConcatenatePayloadTest, ConcatenatePayloadSucceeds) {
277   HpkeTestParams params = DefaultHpkeTestParams();
278   EXPECT_THAT(ConcatenatePayload(params.encapsulated_key, params.ciphertext),
279               Eq(absl::StrCat(params.encapsulated_key, params.ciphertext)));
280 }
281 
TEST(SplitPayloadTest,SplitPayloadSucceeds)282 TEST(SplitPayloadTest, SplitPayloadSucceeds) {
283   HpkeTestParams params = DefaultHpkeTestParams();
284   const std::string payload =
285       absl::StrCat(params.encapsulated_key, params.ciphertext);
286   util::StatusOr<HpkePayloadView> hpke_payload =
287       SplitPayload(HpkeKem::kX25519HkdfSha256, payload);
288   ASSERT_THAT(hpke_payload, IsOk());
289   EXPECT_THAT(hpke_payload->encapsulated_key, Eq(params.encapsulated_key));
290   EXPECT_THAT(hpke_payload->ciphertext, Eq(params.ciphertext));
291 }
292 
TEST(SplitPayloadTest,InvalidKemFails)293 TEST(SplitPayloadTest, InvalidKemFails) {
294   HpkeTestParams params = DefaultHpkeTestParams();
295   util::StatusOr<HpkePayloadView> payload =
296       SplitPayload(HpkeKem::kUnknownKem,
297                    absl::StrCat(params.encapsulated_key, params.ciphertext));
298   EXPECT_THAT(payload.status(), StatusIs(absl::StatusCode::kInvalidArgument));
299 }
300 
301 }  // namespace
302 }  // namespace internal
303 }  // namespace tink
304 }  // namespace crypto
305