1 // Copyright 2020 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/ecies_aead_hkdf_dem_helper.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "tink/aead/aes_gcm_key_manager.h"
27 #include "tink/daead/aes_siv_key_manager.h"
28 #include "tink/util/secret_data.h"
29 #include "tink/util/test_matchers.h"
30 #include "tink/util/test_util.h"
31
32 namespace crypto {
33 namespace tink {
34 namespace {
35
36 using ::crypto::tink::subtle::AeadOrDaead;
37 using ::crypto::tink::test::IsOk;
38 using ::crypto::tink::test::StatusIs;
39 using ::crypto::tink::util::StatusOr;
40 using ::testing::HasSubstr;
41
42 // Checks whether Decrypt(Encrypt(message)) == message with the given dem.
EncryptThenDecrypt(const AeadOrDaead & dem,absl::string_view message,absl::string_view associated_data)43 crypto::tink::util::Status EncryptThenDecrypt(
44 const AeadOrDaead& dem, absl::string_view message,
45 absl::string_view associated_data) {
46 StatusOr<std::string> encryption_or = dem.Encrypt(message, associated_data);
47 if (!encryption_or.status().ok()) return encryption_or.status();
48 StatusOr<std::string> decryption_or =
49 dem.Decrypt(encryption_or.value(), associated_data);
50 if (!decryption_or.status().ok()) return decryption_or.status();
51 if (decryption_or.value() != message) {
52 return crypto::tink::util::Status(absl::StatusCode::kInternal,
53 "Message/Decryption mismatch");
54 }
55 return util::OkStatus();
56 }
57
TEST(EciesAeadHkdfDemHelperTest,InvalidKey)58 TEST(EciesAeadHkdfDemHelperTest, InvalidKey) {
59 google::crypto::tink::KeyTemplate dem_key_template;
60 dem_key_template.set_type_url("some.type.url/that.is.not.supported");
61 auto result = EciesAeadHkdfDemHelper::New(dem_key_template);
62 EXPECT_THAT(EciesAeadHkdfDemHelper::New(dem_key_template).status(),
63 StatusIs(absl::StatusCode::kInvalidArgument,
64 HasSubstr("Unsupported DEM")));
65 }
66
TEST(EciesAeadHkdfDemHelperTest,DemHelperWithSomeAeadKeyType)67 TEST(EciesAeadHkdfDemHelperTest, DemHelperWithSomeAeadKeyType) {
68 google::crypto::tink::AesGcmKeyFormat key_format;
69 key_format.set_key_size(16);
70 std::unique_ptr<AesGcmKeyManager> key_manager(new AesGcmKeyManager());
71 std::string dem_key_type = key_manager->get_key_type();
72
73 google::crypto::tink::KeyTemplate dem_key_template;
74 dem_key_template.set_type_url(dem_key_type);
75 dem_key_template.set_value(key_format.SerializeAsString());
76
77 auto dem_helper_or = EciesAeadHkdfDemHelper::New(dem_key_template);
78 ASSERT_THAT(dem_helper_or, IsOk());
79 auto dem_helper = std::move(dem_helper_or.value());
80
81 util::SecretData key128 = util::SecretDataFromStringView(
82 test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f"));
83 StatusOr<std::unique_ptr<AeadOrDaead>> aead_or_daead_result_or =
84 dem_helper->GetAeadOrDaead(key128);
85 ASSERT_THAT(aead_or_daead_result_or, IsOk());
86
87 auto aead_or_daead = std::move(aead_or_daead_result_or.value());
88 EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"),
89 IsOk());
90 }
91
TEST(EciesAeadHkdfDemHelperTest,DemHelperWithSomeDeterministicAeadKeyType)92 TEST(EciesAeadHkdfDemHelperTest, DemHelperWithSomeDeterministicAeadKeyType) {
93 google::crypto::tink::AesSivKeyFormat key_format;
94 key_format.set_key_size(64);
95 std::unique_ptr<AesSivKeyManager> key_manager(new AesSivKeyManager());
96 std::string dem_key_type = key_manager->get_key_type();
97
98 google::crypto::tink::KeyTemplate dem_key_template;
99 dem_key_template.set_type_url(dem_key_type);
100 dem_key_template.set_value(key_format.SerializeAsString());
101
102 auto dem_helper_or = EciesAeadHkdfDemHelper::New(dem_key_template);
103 ASSERT_THAT(dem_helper_or, IsOk());
104 auto dem_helper = std::move(dem_helper_or.value());
105
106 util::SecretData key128 = util::SecretDataFromStringView(test::HexDecodeOrDie(
107 "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f00010203"
108 "0405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f"));
109 StatusOr<std::unique_ptr<AeadOrDaead>> aead_or_daead_result_or =
110 dem_helper->GetAeadOrDaead(key128);
111 ASSERT_THAT(aead_or_daead_result_or, IsOk());
112
113 auto aead_or_daead = std::move(aead_or_daead_result_or.value());
114 EXPECT_THAT(EncryptThenDecrypt(*aead_or_daead, "test_plaintext", "test_ad"),
115 IsOk());
116 }
117
118 } // namespace
119 } // namespace tink
120 } // namespace crypto
121