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/experimental/pqcrypto/kem/cecpq2_hybrid_config.h"
18
19 #include <list>
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/config/tink_fips.h"
27 #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_private_key_manager.h"
28 #include "tink/experimental/pqcrypto/kem/cecpq2_aead_hkdf_public_key_manager.h"
29 #include "tink/experimental/pqcrypto/kem/cecpq2_hybrid_key_templates.h"
30 #include "tink/hybrid_decrypt.h"
31 #include "tink/hybrid_encrypt.h"
32 #include "tink/keyset_handle.h"
33 #include "tink/registry.h"
34 #include "tink/util/status.h"
35 #include "tink/util/test_matchers.h"
36 #include "tink/util/test_util.h"
37
38 namespace crypto {
39 namespace tink {
40 namespace {
41
42 using ::crypto::tink::test::DummyHybridDecrypt;
43 using ::crypto::tink::test::DummyHybridEncrypt;
44 using ::crypto::tink::test::IsOk;
45 using ::crypto::tink::test::StatusIs;
46
47 class Cecpq2HybridConfigTest : public ::testing::Test {
48 protected:
SetUp()49 void SetUp() override { Registry::Reset(); }
50 };
51
TEST_F(Cecpq2HybridConfigTest,Basic)52 TEST_F(Cecpq2HybridConfigTest, Basic) {
53 if (IsFipsModeEnabled()) {
54 GTEST_SKIP() << "Not supported in FIPS-only mode";
55 }
56
57 EXPECT_THAT(Registry::get_key_manager<HybridDecrypt>(
58 Cecpq2AeadHkdfPrivateKeyManager().get_key_type())
59 .status(),
60 StatusIs(absl::StatusCode::kNotFound));
61 EXPECT_THAT(Registry::get_key_manager<HybridEncrypt>(
62 Cecpq2AeadHkdfPublicKeyManager().get_key_type())
63 .status(),
64 StatusIs(absl::StatusCode::kNotFound));
65 EXPECT_THAT(Cecpq2HybridConfigRegister(), IsOk());
66 EXPECT_THAT(Registry::get_key_manager<HybridDecrypt>(
67 Cecpq2AeadHkdfPrivateKeyManager().get_key_type())
68 .status(),
69 IsOk());
70 EXPECT_THAT(Registry::get_key_manager<HybridEncrypt>(
71 Cecpq2AeadHkdfPublicKeyManager().get_key_type())
72 .status(),
73 IsOk());
74 }
75
76 // Tests that the HybridEncrypt wrapper has been properly registered and we
77 // can wrap primitives
TEST_F(Cecpq2HybridConfigTest,EncryptWrapperRegistered)78 TEST_F(Cecpq2HybridConfigTest, EncryptWrapperRegistered) {
79 if (IsFipsModeEnabled()) {
80 GTEST_SKIP() << "Not supported in FIPS-only mode";
81 }
82
83 ASSERT_TRUE(Cecpq2HybridConfigRegister().ok());
84
85 google::crypto::tink::KeysetInfo::KeyInfo key_info;
86 key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED);
87 key_info.set_key_id(1234);
88 key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK);
89 auto primitive_set = absl::make_unique<PrimitiveSet<HybridEncrypt>>();
90 ASSERT_THAT(
91 primitive_set->set_primary(
92 primitive_set
93 ->AddPrimitive(absl::make_unique<DummyHybridEncrypt>("dummy"),
94 key_info)
95 .value()),
96 IsOk());
97
98 auto wrapped = Registry::Wrap(std::move(primitive_set));
99
100 ASSERT_THAT(wrapped, IsOk());
101 auto encryption_result = wrapped.value()->Encrypt("secret", "");
102 ASSERT_THAT(encryption_result, IsOk());
103
104 std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value();
105 EXPECT_EQ(
106 encryption_result.value(),
107 absl::StrCat(prefix,
108 DummyHybridEncrypt("dummy").Encrypt("secret", "").value()));
109 }
110
111 // Tests that the HybridDecrypt wrapper has been properly registered and we
112 // can wrap primitives
TEST_F(Cecpq2HybridConfigTest,DecryptWrapperRegistered)113 TEST_F(Cecpq2HybridConfigTest, DecryptWrapperRegistered) {
114 if (IsFipsModeEnabled()) {
115 GTEST_SKIP() << "Not supported in FIPS-only mode";
116 }
117
118 ASSERT_TRUE(Cecpq2HybridConfigRegister().ok());
119
120 google::crypto::tink::KeysetInfo::KeyInfo key_info;
121 key_info.set_status(google::crypto::tink::KeyStatusType::ENABLED);
122 key_info.set_key_id(1234);
123 key_info.set_output_prefix_type(google::crypto::tink::OutputPrefixType::TINK);
124 auto primitive_set = absl::make_unique<PrimitiveSet<HybridDecrypt>>();
125 ASSERT_THAT(
126 primitive_set->set_primary(
127 primitive_set
128 ->AddPrimitive(absl::make_unique<DummyHybridDecrypt>("dummy"),
129 key_info)
130 .value()),
131 IsOk());
132
133 auto wrapped = Registry::Wrap(std::move(primitive_set));
134
135 ASSERT_THAT(wrapped, IsOk());
136
137 std::string prefix = CryptoFormat::GetOutputPrefix(key_info).value();
138 std::string encryption =
139 DummyHybridEncrypt("dummy").Encrypt("secret", "").value();
140
141 ASSERT_EQ(
142 wrapped.value()->Decrypt(absl::StrCat(prefix, encryption), "").value(),
143 "secret");
144 }
145
146 } // namespace
147 } // namespace tink
148 } // namespace crypto
149