xref: /aosp_15_r20/external/tink/cc/hybrid/internal/hpke_decrypt_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 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_decrypt.h"
18 
19 #include <memory>
20 #include <string>
21 #include <vector>
22 
23 #include "gtest/gtest.h"
24 #include "absl/status/status.h"
25 #include "absl/strings/str_cat.h"
26 #include "tink/hybrid/internal/hpke_encrypt.h"
27 #include "tink/hybrid/internal/hpke_test_util.h"
28 #include "tink/util/statusor.h"
29 #include "tink/util/test_matchers.h"
30 #include "proto/hpke.pb.h"
31 
32 namespace crypto {
33 namespace tink {
34 namespace {
35 
36 using ::crypto::tink::internal::CreateHpkeParams;
37 using ::crypto::tink::internal::CreateHpkePrivateKey;
38 using ::crypto::tink::internal::CreateHpkePublicKey;
39 using ::crypto::tink::internal::CreateHpkeTestParams;
40 using ::crypto::tink::internal::DefaultHpkeTestParams;
41 using ::crypto::tink::internal::HpkeTestParams;
42 using ::crypto::tink::test::IsOk;
43 using ::crypto::tink::test::IsOkAndHolds;
44 using ::crypto::tink::test::StatusIs;
45 using ::google::crypto::tink::HpkeAead;
46 using ::google::crypto::tink::HpkeKdf;
47 using ::google::crypto::tink::HpkeKem;
48 using ::google::crypto::tink::HpkeParams;
49 using ::google::crypto::tink::HpkePrivateKey;
50 using ::google::crypto::tink::HpkePublicKey;
51 using ::testing::Values;
52 
Encrypt(HpkeParams params,absl::string_view recipient_public_key,absl::string_view plaintext,absl::string_view context_info)53 util::StatusOr<std::string> Encrypt(HpkeParams params,
54                                     absl::string_view recipient_public_key,
55                                     absl::string_view plaintext,
56                                     absl::string_view context_info) {
57   HpkePublicKey recipient_key =
58       CreateHpkePublicKey(params, std::string(recipient_public_key));
59   util::StatusOr<std::unique_ptr<HybridEncrypt>> hpke_encrypt =
60       HpkeEncrypt::New(recipient_key);
61   if (!hpke_encrypt.ok()) {
62     return hpke_encrypt.status();
63   }
64   return (*hpke_encrypt)->Encrypt(plaintext, context_info);
65 }
66 
67 class HpkeDecryptTest : public testing::TestWithParam<HpkeParams> {};
68 
69 INSTANTIATE_TEST_SUITE_P(
70     HpkeDecryptionTestSuite, HpkeDecryptTest,
71     Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
72                             HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM),
73            CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
74                             HpkeKdf::HKDF_SHA256,
75                             HpkeAead::CHACHA20_POLY1305)));
76 
TEST_P(HpkeDecryptTest,SetupRecipientContextAndDecrypt)77 TEST_P(HpkeDecryptTest, SetupRecipientContextAndDecrypt) {
78   HpkeParams hpke_params = GetParam();
79   util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
80   ASSERT_THAT(params, IsOk());
81   HpkePrivateKey recipient_key =
82       CreateHpkePrivateKey(hpke_params, params->recipient_private_key);
83   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
84       HpkeDecrypt::New(recipient_key);
85   ASSERT_THAT(hpke_decrypt, IsOk());
86 
87   std::vector<std::string> inputs = {"", params->plaintext};
88   std::vector<std::string> context_infos = {"", params->application_info};
89   for (const std::string& input : inputs) {
90     for (const std::string& context_info : context_infos) {
91       SCOPED_TRACE(absl::StrCat("input: '", input, "', context_info: '",
92                                 context_info, "'"));
93       util::StatusOr<std::string> ciphertext = Encrypt(
94           hpke_params, params->recipient_public_key, input, context_info);
95       ASSERT_THAT(ciphertext, IsOk());
96       util::StatusOr<std::string> plaintext =
97           (*hpke_decrypt)->Decrypt(*ciphertext, context_info);
98       EXPECT_THAT(plaintext, IsOkAndHolds(input));
99     }
100   }
101 }
102 
103 class HpkeDecryptWithBadParamTest : public testing::TestWithParam<HpkeParams> {
104 };
105 
106 INSTANTIATE_TEST_SUITE_P(
107     HpkeDecryptionWithBadParamTestSuite, HpkeDecryptWithBadParamTest,
108     Values(CreateHpkeParams(HpkeKem::KEM_UNKNOWN,
109                             HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM),
110            CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
111                             HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM),
112            CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
113                             HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN)));
114 
TEST_P(HpkeDecryptWithBadParamTest,BadParamsFails)115 TEST_P(HpkeDecryptWithBadParamTest, BadParamsFails) {
116   HpkeParams bad_params = GetParam();
117   HpkeTestParams params = DefaultHpkeTestParams();
118   HpkePrivateKey recipient_key =
119       CreateHpkePrivateKey(bad_params, params.recipient_private_key);
120   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
121       HpkeDecrypt::New(recipient_key);
122   ASSERT_THAT(hpke_decrypt, IsOk());
123 
124   util::StatusOr<std::string> decryption =
125       (*hpke_decrypt)->Decrypt(params.ciphertext, params.application_info);
126 
127   EXPECT_THAT(decryption.status(),
128               StatusIs(absl::StatusCode::kInvalidArgument));
129 }
130 
TEST(HpkeDecryptWithShortCiphertextTest,ShortCiphertextFails)131 TEST(HpkeDecryptWithShortCiphertextTest, ShortCiphertextFails) {
132   HpkeParams hpke_params =
133       CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
134                        HpkeAead::AES_128_GCM);
135   HpkeTestParams params = DefaultHpkeTestParams();
136   HpkePrivateKey recipient_key =
137       CreateHpkePrivateKey(hpke_params, params.recipient_private_key);
138   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
139       HpkeDecrypt::New(recipient_key);
140   ASSERT_THAT(hpke_decrypt, IsOk());
141 
142   util::StatusOr<std::string> plaintext =
143       (*hpke_decrypt)->Decrypt("short ciphertext", "associated data");
144 
145   EXPECT_THAT(plaintext.status(), StatusIs(absl::StatusCode::kInvalidArgument));
146 }
147 
TEST(HpkeDecryptWithBadCiphertextTest,BadCiphertextFails)148 TEST(HpkeDecryptWithBadCiphertextTest, BadCiphertextFails) {
149   HpkeParams hpke_params =
150       CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
151                        HpkeAead::AES_128_GCM);
152   HpkeTestParams params = DefaultHpkeTestParams();
153   HpkePrivateKey recipient_key =
154       CreateHpkePrivateKey(hpke_params, params.recipient_private_key);
155   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
156       HpkeDecrypt::New(recipient_key);
157   ASSERT_THAT(hpke_decrypt, IsOk());
158   util::StatusOr<std::string> ciphertext =
159       Encrypt(hpke_params, params.recipient_public_key, params.plaintext,
160               params.application_info);
161   ASSERT_THAT(ciphertext, IsOk());
162 
163   util::StatusOr<std::string> plaintext =
164       (*hpke_decrypt)
165           ->Decrypt(absl::StrCat(*ciphertext, "modified ciphertext"),
166                     params.application_info);
167 
168   EXPECT_THAT(plaintext.status(), StatusIs(absl::StatusCode::kUnknown));
169 }
170 
TEST(HpkeDecryptWithBadAssociatedDataTest,BadAssociatedDataFails)171 TEST(HpkeDecryptWithBadAssociatedDataTest, BadAssociatedDataFails) {
172   HpkeParams hpke_params =
173       CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
174                        HpkeAead::AES_128_GCM);
175   HpkeTestParams params = DefaultHpkeTestParams();
176   HpkePrivateKey recipient_key =
177       CreateHpkePrivateKey(hpke_params, params.recipient_private_key);
178   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
179       HpkeDecrypt::New(recipient_key);
180   ASSERT_THAT(hpke_decrypt, IsOk());
181   util::StatusOr<std::string> ciphertext =
182       Encrypt(hpke_params, params.recipient_public_key, params.plaintext,
183               params.application_info);
184   ASSERT_THAT(ciphertext, IsOk());
185 
186   util::StatusOr<std::string> plaintext =
187       (*hpke_decrypt)
188           ->Decrypt(*ciphertext,
189                     absl::StrCat(params.application_info, "modified aad"));
190 
191   EXPECT_THAT(plaintext.status(), StatusIs(absl::StatusCode::kUnknown));
192 }
193 
TEST(HpkeDecryptWithMissingPublicKeyTest,MissingPublicKeyFails)194 TEST(HpkeDecryptWithMissingPublicKeyTest, MissingPublicKeyFails) {
195   HpkeParams hpke_params =
196       CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
197                        HpkeAead::AES_128_GCM);
198   HpkeTestParams params = DefaultHpkeTestParams();
199   HpkePrivateKey recipient_key =
200       CreateHpkePrivateKey(hpke_params, params.recipient_private_key);
201   recipient_key.clear_public_key();
202 
203   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
204       HpkeDecrypt::New(recipient_key);
205 
206   EXPECT_THAT(hpke_decrypt.status(),
207               StatusIs(absl::StatusCode::kInvalidArgument));
208 }
209 
TEST(HpkeDecryptWithMissingHpkeParamsTest,MissingHpkeParamsFails)210 TEST(HpkeDecryptWithMissingHpkeParamsTest, MissingHpkeParamsFails) {
211   HpkeParams hpke_params =
212       CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
213                        HpkeAead::AES_128_GCM);
214   HpkeTestParams params = DefaultHpkeTestParams();
215   HpkePrivateKey recipient_key =
216       CreateHpkePrivateKey(hpke_params, params.recipient_private_key);
217   recipient_key.mutable_public_key()->clear_params();
218 
219   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
220       HpkeDecrypt::New(recipient_key);
221 
222   EXPECT_THAT(hpke_decrypt.status(),
223               StatusIs(absl::StatusCode::kInvalidArgument));
224 }
225 
TEST(HpkeDecryptWithZeroLengthPrivateKeyTest,ZeroLengthPrivateKeyFails)226 TEST(HpkeDecryptWithZeroLengthPrivateKeyTest, ZeroLengthPrivateKeyFails) {
227   HpkeParams hpke_params =
228       CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
229                        HpkeAead::AES_128_GCM);
230   HpkeTestParams params = DefaultHpkeTestParams();
231   HpkePrivateKey recipient_key =
232       CreateHpkePrivateKey(hpke_params, /*raw_key_bytes=*/"");
233 
234   util::StatusOr<std::unique_ptr<HybridDecrypt>> hpke_decrypt =
235       HpkeDecrypt::New(recipient_key);
236 
237   EXPECT_THAT(hpke_decrypt.status(),
238               StatusIs(absl::StatusCode::kInvalidArgument));
239 }
240 
241 }  // namespace
242 }  // namespace tink
243 }  // namespace crypto
244