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/signature/falcon_sign_key_manager.h"
18
19 #include <memory>
20 #include <string>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/container/flat_hash_set.h"
25 #include "absl/strings/str_cat.h"
26 #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h"
27 #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h"
28 #include "tink/experimental/pqcrypto/signature/subtle/falcon_verify.h"
29 #include "tink/public_key_verify.h"
30 #include "tink/util/secret_data.h"
31 #include "tink/util/status.h"
32 #include "tink/util/statusor.h"
33 #include "tink/util/test_matchers.h"
34
35 namespace crypto {
36 namespace tink {
37 namespace {
38
39 using ::crypto::tink::test::IsOk;
40 using ::crypto::tink::util::StatusOr;
41 using ::google::crypto::tink::FalconKeyFormat;
42 using ::google::crypto::tink::FalconPrivateKey;
43 using ::google::crypto::tink::FalconPublicKey;
44 using ::google::crypto::tink::KeyData;
45 using ::testing::Eq;
46 using ::testing::Not;
47 using ::testing::SizeIs;
48
49 struct FalconTestCase {
50 std::string test_name;
51 int32_t private_key_size;
52 int32_t public_key_size;
53 };
54
55 using FalconSignKeyManagerTest = testing::TestWithParam<FalconTestCase>;
56
57 // Helper function that returns a valid falcon key format.
CreateValidKeyFormat(int32_t private_key_size)58 StatusOr<FalconKeyFormat> CreateValidKeyFormat(int32_t private_key_size) {
59 FalconKeyFormat key_format;
60 key_format.set_key_size(private_key_size);
61
62 return key_format;
63 }
64
TEST(FalconSignKeyManagerTest,Basic)65 TEST(FalconSignKeyManagerTest, Basic) {
66 EXPECT_THAT(FalconSignKeyManager().get_version(), Eq(0));
67 EXPECT_THAT(FalconSignKeyManager().key_material_type(),
68 Eq(KeyData::ASYMMETRIC_PRIVATE));
69 EXPECT_THAT(FalconSignKeyManager().get_key_type(),
70 Eq("type.googleapis.com/google.crypto.tink.FalconPrivateKey"));
71 }
72
TEST_P(FalconSignKeyManagerTest,ValidKeyFormat)73 TEST_P(FalconSignKeyManagerTest, ValidKeyFormat) {
74 const FalconTestCase& test_case = GetParam();
75
76 StatusOr<FalconKeyFormat> key_format =
77 CreateValidKeyFormat(test_case.private_key_size);
78 ASSERT_THAT(key_format, IsOk());
79
80 EXPECT_THAT(FalconSignKeyManager().ValidateKeyFormat(*key_format), IsOk());
81 }
82
TEST(FalconSignKeyManagerTest,InvalidKeyFormat)83 TEST(FalconSignKeyManagerTest, InvalidKeyFormat) {
84 StatusOr<FalconKeyFormat> key_format = CreateValidKeyFormat(0);
85 ASSERT_THAT(key_format, IsOk());
86
87 EXPECT_THAT(FalconSignKeyManager().ValidateKeyFormat(*key_format),
88 Not(IsOk()));
89 }
90
TEST_P(FalconSignKeyManagerTest,CreateKeyValid)91 TEST_P(FalconSignKeyManagerTest, CreateKeyValid) {
92 const FalconTestCase& test_case = GetParam();
93
94 StatusOr<FalconKeyFormat> key_format =
95 CreateValidKeyFormat(test_case.private_key_size);
96 ASSERT_THAT(key_format, IsOk());
97
98 StatusOr<FalconPrivateKey> private_key =
99 FalconSignKeyManager().CreateKey(*key_format);
100 ASSERT_THAT(private_key, IsOk());
101
102 EXPECT_THAT(FalconSignKeyManager().ValidateKey(*private_key), IsOk());
103 EXPECT_THAT(private_key->version(), Eq(0));
104 EXPECT_THAT(private_key->public_key().version(), Eq(private_key->version()));
105 EXPECT_THAT(private_key->key_value(), SizeIs(test_case.private_key_size));
106 }
107
TEST_P(FalconSignKeyManagerTest,PrivateKeyWrongVersion)108 TEST_P(FalconSignKeyManagerTest, PrivateKeyWrongVersion) {
109 const FalconTestCase& test_case = GetParam();
110
111 StatusOr<FalconKeyFormat> key_format =
112 CreateValidKeyFormat(test_case.private_key_size);
113 ASSERT_THAT(key_format, IsOk());
114
115 StatusOr<FalconPrivateKey> private_key =
116 FalconSignKeyManager().CreateKey(*key_format);
117 ASSERT_THAT(private_key, IsOk());
118
119 private_key->set_version(1);
120 EXPECT_THAT(FalconSignKeyManager().ValidateKey(*private_key), Not(IsOk()));
121 }
122
TEST_P(FalconSignKeyManagerTest,CreateKeyAlwaysNew)123 TEST_P(FalconSignKeyManagerTest, CreateKeyAlwaysNew) {
124 const FalconTestCase& test_case = GetParam();
125
126 StatusOr<FalconKeyFormat> key_format =
127 CreateValidKeyFormat(test_case.private_key_size);
128 ASSERT_THAT(key_format, IsOk());
129
130 absl::flat_hash_set<std::string> keys;
131 int num_tests = 5;
132 for (int i = 0; i < num_tests; ++i) {
133 StatusOr<FalconPrivateKey> private_key =
134 FalconSignKeyManager().CreateKey(*key_format);
135 ASSERT_THAT(private_key, IsOk());
136 keys.insert(private_key->key_value());
137 }
138 EXPECT_THAT(keys, SizeIs(num_tests));
139 }
140
TEST_P(FalconSignKeyManagerTest,GetPublicKey)141 TEST_P(FalconSignKeyManagerTest, GetPublicKey) {
142 const FalconTestCase& test_case = GetParam();
143
144 StatusOr<FalconKeyFormat> key_format =
145 CreateValidKeyFormat(test_case.private_key_size);
146 ASSERT_THAT(key_format, IsOk());
147
148 StatusOr<FalconPrivateKey> private_key =
149 FalconSignKeyManager().CreateKey(*key_format);
150 ASSERT_THAT(private_key, IsOk());
151
152 StatusOr<FalconPublicKey> public_key =
153 FalconSignKeyManager().GetPublicKey(*private_key);
154 ASSERT_THAT(public_key, IsOk());
155
156 EXPECT_THAT(public_key->version(), Eq(private_key->public_key().version()));
157 EXPECT_THAT(public_key->key_value(),
158 Eq(private_key->public_key().key_value()));
159 }
160
TEST_P(FalconSignKeyManagerTest,CreateValid)161 TEST_P(FalconSignKeyManagerTest, CreateValid) {
162 const FalconTestCase& test_case = GetParam();
163
164 StatusOr<FalconKeyFormat> key_format =
165 CreateValidKeyFormat(test_case.private_key_size);
166 ASSERT_THAT(key_format, IsOk());
167
168 util::StatusOr<FalconPrivateKey> private_key =
169 FalconSignKeyManager().CreateKey(*key_format);
170 ASSERT_THAT(private_key, IsOk());
171
172 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
173 FalconSignKeyManager().GetPrimitive<PublicKeySign>(*private_key);
174 ASSERT_THAT(signer, IsOk());
175
176 StatusOr<subtle::FalconPublicKeyPqclean> falcon_public_key_pqclean =
177 subtle::FalconPublicKeyPqclean::NewPublicKey(
178 private_key->public_key().key_value());
179 ASSERT_THAT(falcon_public_key_pqclean, IsOk());
180
181 util::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier =
182 subtle::FalconVerify::New(*falcon_public_key_pqclean);
183 ASSERT_THAT(verifier, IsOk());
184
185 std::string message = "Some message";
186 util::StatusOr<std::string> signature = (*signer)->Sign(message);
187 ASSERT_THAT(signature, IsOk());
188 EXPECT_THAT((*verifier)->Verify(*signature, message), IsOk());
189 }
190
TEST_P(FalconSignKeyManagerTest,CreateBadPublicKey)191 TEST_P(FalconSignKeyManagerTest, CreateBadPublicKey) {
192 const FalconTestCase& test_case = GetParam();
193
194 StatusOr<FalconKeyFormat> key_format =
195 CreateValidKeyFormat(test_case.private_key_size);
196 ASSERT_THAT(key_format, IsOk());
197
198 util::StatusOr<FalconPrivateKey> private_key =
199 FalconSignKeyManager().CreateKey(*key_format);
200 ASSERT_THAT(private_key, IsOk());
201
202 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
203 FalconSignKeyManager().GetPrimitive<PublicKeySign>(*private_key);
204 ASSERT_THAT(signer, IsOk());
205
206 std::string bad_public_key_data(test_case.public_key_size, '@');
207
208 StatusOr<subtle::FalconPublicKeyPqclean> falcon_public_key_pqclean =
209 subtle::FalconPublicKeyPqclean::NewPublicKey(bad_public_key_data);
210 ASSERT_THAT(falcon_public_key_pqclean, IsOk());
211 util::StatusOr<std::unique_ptr<PublicKeyVerify>> direct_verifier =
212 subtle::FalconVerify::New(*falcon_public_key_pqclean);
213 ASSERT_THAT(direct_verifier, IsOk());
214
215 std::string message = "Some message";
216 util::StatusOr<std::string> signature = (*signer)->Sign(message);
217 ASSERT_THAT(signature, IsOk());
218 EXPECT_THAT((*direct_verifier)->Verify(*signature, message), Not(IsOk()));
219 }
220
221 INSTANTIATE_TEST_SUITE_P(
222 FalconSignKeyManagerTests, FalconSignKeyManagerTest,
223 testing::ValuesIn<FalconTestCase>(
224 {{"Falcon512", subtle::kFalcon512PrivateKeySize,
225 subtle::kFalcon512PublicKeySize},
226 {"Falcon1024", subtle::kFalcon1024PrivateKeySize,
227 subtle::kFalcon1024PublicKeySize}}),
228 [](const testing::TestParamInfo<FalconSignKeyManagerTest::ParamType>&
__anon53b76b260202(const testing::TestParamInfo<FalconSignKeyManagerTest::ParamType>& info) 229 info) { return info.param.test_name; });
230
231 } // namespace
232
233 } // namespace tink
234 } // namespace crypto
235