• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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