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_encrypt.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_test_util.h"
27 #include "tink/hybrid/internal/hpke_util.h"
28 #include "tink/util/test_matchers.h"
29 #include "proto/hpke.pb.h"
30
31 namespace crypto {
32 namespace tink {
33 namespace {
34
35 using ::crypto::tink::internal::CreateHpkeParams;
36 using ::crypto::tink::internal::CreateHpkePublicKey;
37 using ::crypto::tink::internal::CreateHpkeTestParams;
38 using ::crypto::tink::internal::DefaultHpkeTestParams;
39 using ::crypto::tink::internal::HpkeTestParams;
40 using ::crypto::tink::test::IsOk;
41 using ::crypto::tink::test::IsOkAndHolds;
42 using ::crypto::tink::test::StatusIs;
43 using ::google::crypto::tink::HpkeAead;
44 using ::google::crypto::tink::HpkeKdf;
45 using ::google::crypto::tink::HpkeKem;
46 using ::google::crypto::tink::HpkeParams;
47 using ::google::crypto::tink::HpkePublicKey;
48 using ::testing::SizeIs;
49 using ::testing::Values;
50
51 constexpr int kTagLength = 16; // Tag length (in bytes) for GCM and Poly1305.
52
53 class HpkeEncryptTest : public testing::TestWithParam<HpkeParams> {};
54
55 INSTANTIATE_TEST_SUITE_P(
56 HpkeEncryptionTestSuite, HpkeEncryptTest,
57 Values(CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
58 HpkeKdf::HKDF_SHA256, HpkeAead::AES_128_GCM),
59 CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
60 HpkeKdf::HKDF_SHA256, HpkeAead::CHACHA20_POLY1305),
61 CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
62 HpkeKdf::HKDF_SHA256, HpkeAead::AES_256_GCM)));
63
TEST_P(HpkeEncryptTest,SetupSenderContextAndEncrypt)64 TEST_P(HpkeEncryptTest, SetupSenderContextAndEncrypt) {
65 HpkeParams hpke_params = GetParam();
66 util::StatusOr<uint32_t> encapsulated_key_length =
67 internal::HpkeEncapsulatedKeyLength(hpke_params.kem());
68 ASSERT_THAT(encapsulated_key_length, IsOk());
69
70 util::StatusOr<HpkeTestParams> params = CreateHpkeTestParams(hpke_params);
71 ASSERT_THAT(params, IsOk());
72 HpkePublicKey recipient_key =
73 CreateHpkePublicKey(hpke_params, params->recipient_public_key);
74 util::StatusOr<std::unique_ptr<HybridEncrypt>> hpke_encrypt =
75 HpkeEncrypt::New(recipient_key);
76 ASSERT_THAT(hpke_encrypt, IsOk());
77
78 std::vector<std::string> plaintexts = {"", params->plaintext};
79 std::vector<std::string> context_infos = {"", params->application_info};
80 for (const std::string& plaintext : plaintexts) {
81 for (const std::string& context_info : context_infos) {
82 SCOPED_TRACE(absl::StrCat("plaintext: '", plaintext, "', context_info: '",
83 context_info, "'"));
84 int expected_ciphertext_length =
85 *encapsulated_key_length + plaintext.size() + kTagLength;
86 util::StatusOr<std::string> encryption_result =
87 (*hpke_encrypt)->Encrypt(plaintext, context_info);
88 EXPECT_THAT(encryption_result,
89 IsOkAndHolds(SizeIs(expected_ciphertext_length)));
90 }
91 }
92 }
93
94 class HpkeEncryptWithBadParamTest : public testing::TestWithParam<HpkeParams> {
95 };
96
97 INSTANTIATE_TEST_SUITE_P(
98 HpkeEncryptionWithBadParamTestSuite, HpkeEncryptWithBadParamTest,
99 Values(CreateHpkeParams(HpkeKem::KEM_UNKNOWN, HpkeKdf::HKDF_SHA256,
100 HpkeAead::AES_128_GCM),
101 CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
102 HpkeKdf::KDF_UNKNOWN, HpkeAead::AES_128_GCM),
103 CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256,
104 HpkeKdf::HKDF_SHA256, HpkeAead::AEAD_UNKNOWN)));
105
TEST_P(HpkeEncryptWithBadParamTest,BadParamFails)106 TEST_P(HpkeEncryptWithBadParamTest, BadParamFails) {
107 HpkeParams hpke_params = GetParam();
108 HpkeTestParams params = DefaultHpkeTestParams();
109 HpkePublicKey recipient_key =
110 CreateHpkePublicKey(hpke_params, params.recipient_public_key);
111 util::StatusOr<std::unique_ptr<HybridEncrypt>> hpke_encrypt =
112 HpkeEncrypt::New(recipient_key);
113 ASSERT_THAT(hpke_encrypt, IsOk());
114
115 util::StatusOr<std::string> encryption_result =
116 (*hpke_encrypt)->Encrypt(params.plaintext, params.application_info);
117
118 EXPECT_THAT(encryption_result.status(),
119 StatusIs(absl::StatusCode::kInvalidArgument));
120 }
121
TEST(HpkeEncryptWithZeroLengthPublicKey,ZeroLengthPublicKeyFails)122 TEST(HpkeEncryptWithZeroLengthPublicKey, ZeroLengthPublicKeyFails) {
123 HpkeParams hpke_params =
124 CreateHpkeParams(HpkeKem::DHKEM_X25519_HKDF_SHA256, HpkeKdf::HKDF_SHA256,
125 HpkeAead::AES_128_GCM);
126 HpkeTestParams params = DefaultHpkeTestParams();
127 HpkePublicKey recipient_key =
128 CreateHpkePublicKey(hpke_params, /*raw_key_bytes=*/"");
129
130 util::StatusOr<std::unique_ptr<HybridEncrypt>> hpke_encrypt =
131 HpkeEncrypt::New(recipient_key);
132
133 EXPECT_THAT(hpke_encrypt.status(),
134 StatusIs(absl::StatusCode::kInvalidArgument));
135 }
136
137 } // namespace
138 } // namespace tink
139 } // namespace crypto
140