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/subtle/falcon_verify.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 "absl/strings/escaping.h"
27 #include "absl/strings/str_cat.h"
28 #include "tink/config/tink_fips.h"
29 #include "tink/experimental/pqcrypto/signature/subtle/falcon_sign.h"
30 #include "tink/experimental/pqcrypto/signature/subtle/falcon_subtle_utils.h"
31 #include "tink/public_key_sign.h"
32 #include "tink/public_key_verify.h"
33 #include "tink/util/status.h"
34 #include "tink/util/statusor.h"
35 #include "tink/util/test_matchers.h"
36
37 extern "C" {
38 #include "third_party/pqclean/crypto_sign/falcon-1024/api.h"
39 #include "third_party/pqclean/crypto_sign/falcon-512/api.h"
40 }
41
42 namespace crypto {
43 namespace tink {
44 namespace subtle {
45 namespace {
46
47 using ::crypto::tink::test::IsOk;
48 using ::crypto::tink::test::StatusIs;
49 using crypto::tink::util::Status;
50
51 struct FalconTestCase {
52 std::string test_name;
53 int32_t private_key_size;
54 int32_t signature_length;
55 };
56
57 using FalconVerifyTest = testing::TestWithParam<FalconTestCase>;
58
TEST_P(FalconVerifyTest,BasicSignVerify)59 TEST_P(FalconVerifyTest, BasicSignVerify) {
60 if (IsFipsModeEnabled()) {
61 GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
62 }
63
64 const FalconTestCase& test_case = GetParam();
65
66 // Generate falcon key pair.
67 util::StatusOr<FalconKeyPair> key_pair =
68 GenerateFalconKeyPair(test_case.private_key_size);
69 ASSERT_THAT(key_pair, IsOk());
70
71 // Create a new signer.
72 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
73 FalconSign::New(key_pair->GetPrivateKey());
74 ASSERT_THAT(signer, IsOk());
75
76 // Sign a message.
77 std::string message = "message to be signed";
78 util::StatusOr<std::string> signature = (*signer)->Sign(message);
79 ASSERT_THAT(signature, IsOk());
80
81 // Create a new verifier.
82 absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier =
83 FalconVerify::New(key_pair->GetPublicKey());
84 ASSERT_THAT(verifier, IsOk());
85
86 // Verify signature.
87 Status status = (*verifier)->Verify(*signature, message);
88 EXPECT_THAT(status, IsOk());
89 }
90
TEST_P(FalconVerifyTest,FailsWithWrongSignature)91 TEST_P(FalconVerifyTest, FailsWithWrongSignature) {
92 if (IsFipsModeEnabled()) {
93 GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
94 }
95
96 const FalconTestCase& test_case = GetParam();
97
98 // Generate falcon key pair.
99 util::StatusOr<FalconKeyPair> key_pair =
100 GenerateFalconKeyPair(test_case.private_key_size);
101 ASSERT_THAT(key_pair, IsOk());
102
103 // Create a new signer.
104 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
105 FalconSign::New(key_pair->GetPrivateKey());
106 ASSERT_THAT(signer, IsOk());
107
108 // Sign a message.
109 std::string message = "message to be signed";
110 util::StatusOr<std::string> signature = (*signer)->Sign(message);
111 ASSERT_THAT(signature, IsOk());
112
113 // Create a new verifier.
114 absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier =
115 FalconVerify::New(key_pair->GetPublicKey());
116 ASSERT_THAT(verifier, IsOk());
117
118 // Verify signature.
119 Status status =
120 (*verifier)->Verify(*signature + "some trailing data", message);
121 EXPECT_FALSE(status.ok());
122 }
123
TEST_P(FalconVerifyTest,FailsWithWrongMessage)124 TEST_P(FalconVerifyTest, FailsWithWrongMessage) {
125 if (IsFipsModeEnabled()) {
126 GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
127 }
128
129 const FalconTestCase& test_case = GetParam();
130
131 // Generate falcon key pair.
132 util::StatusOr<FalconKeyPair> key_pair =
133 GenerateFalconKeyPair(test_case.private_key_size);
134 ASSERT_THAT(key_pair, IsOk());
135
136 // Create a new signer.
137 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
138 FalconSign::New(key_pair->GetPrivateKey());
139 ASSERT_THAT(signer, IsOk());
140
141 // Sign a message.
142 std::string message = "message to be signed";
143 util::StatusOr<std::string> signature = (*signer)->Sign(message);
144 ASSERT_THAT(signature, IsOk());
145
146 // Create a new verifier.
147 absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier =
148 FalconVerify::New(key_pair->GetPublicKey());
149 ASSERT_THAT(verifier, IsOk());
150
151 // Verify signature.
152 Status status = (*verifier)->Verify(*signature, "some bad message");
153 EXPECT_FALSE(status.ok());
154 }
155
TEST_P(FalconVerifyTest,FailsWithBytesFlipped)156 TEST_P(FalconVerifyTest, FailsWithBytesFlipped) {
157 if (IsFipsModeEnabled()) {
158 GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
159 }
160
161 const FalconTestCase& test_case = GetParam();
162
163 // Generate falcon key pair.
164 util::StatusOr<FalconKeyPair> key_pair =
165 GenerateFalconKeyPair(test_case.private_key_size);
166 ASSERT_THAT(key_pair, IsOk());
167
168 // Create a new signer.
169 util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
170 FalconSign::New(key_pair->GetPrivateKey());
171 ASSERT_THAT(signer, IsOk());
172
173 // Sign a message.
174 std::string message = "message to be signed";
175 util::StatusOr<std::string> signature = (*signer)->Sign(message);
176 ASSERT_THAT(signature, IsOk());
177
178 // Create a new verifier.
179 absl::StatusOr<std::unique_ptr<PublicKeyVerify>> verifier =
180 FalconVerify::New(key_pair->GetPublicKey());
181 ASSERT_THAT(verifier, IsOk());
182
183 // Invalidate one signature byte.
184 (*signature)[0] ^= 1;
185
186 // Verify signature.
187 Status status = (*verifier)->Verify(*signature, message);
188 EXPECT_FALSE(status.ok());
189 }
190
TEST_P(FalconVerifyTest,FipsMode)191 TEST_P(FalconVerifyTest, FipsMode) {
192 if (!IsFipsModeEnabled()) {
193 GTEST_SKIP() << "Test assumes kOnlyUseFips.";
194 }
195
196 const FalconTestCase& test_case = GetParam();
197
198 // Generate falcon key pair.
199 util::StatusOr<FalconKeyPair> key_pair =
200 GenerateFalconKeyPair(test_case.private_key_size);
201 ASSERT_THAT(key_pair, IsOk());
202
203 // Create a new signer.
204 EXPECT_THAT(FalconVerify::New(key_pair->GetPublicKey()).status(),
205 StatusIs(absl::StatusCode::kInternal));
206 }
207
208 INSTANTIATE_TEST_SUITE_P(
209 FalconVerifyTests, FalconVerifyTest,
210 testing::ValuesIn<FalconTestCase>({{"Falcon512", kFalcon512PrivateKeySize,
211 PQCLEAN_FALCON512_CRYPTO_BYTES},
212 {"Falcon1024", kFalcon1024PrivateKeySize,
213 PQCLEAN_FALCON1024_CRYPTO_BYTES}}),
__anon445dd2c80202(const testing::TestParamInfo<FalconVerifyTest::ParamType>& info) 214 [](const testing::TestParamInfo<FalconVerifyTest::ParamType>& info) {
215 return info.param.test_name;
216 });
217
218 } // namespace
219 } // namespace subtle
220 } // namespace tink
221 } // namespace crypto
222