• 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_sign.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/str_cat.h"
27 #include "tink/config/tink_fips.h"
28 #include "tink/util/status.h"
29 #include "tink/util/statusor.h"
30 #include "tink/util/test_matchers.h"
31 
32 extern "C" {
33 #include "third_party/pqclean/crypto_sign/falcon-1024/api.h"
34 #include "third_party/pqclean/crypto_sign/falcon-512/api.h"
35 }
36 
37 namespace crypto {
38 namespace tink {
39 namespace subtle {
40 namespace {
41 
42 using ::crypto::tink::test::IsOk;
43 
44 struct FalconTestCase {
45   std::string test_name;
46   int32_t private_key_size;
47   int32_t signature_length;
48 };
49 
50 using FalconSignTest = testing::TestWithParam<FalconTestCase>;
51 
TEST_P(FalconSignTest,ValidSignatureLength)52 TEST_P(FalconSignTest, ValidSignatureLength) {
53   if (IsFipsModeEnabled()) {
54     GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
55   }
56 
57   const FalconTestCase& test_case = GetParam();
58 
59   // Generate falcon key pair.
60   util::StatusOr<FalconKeyPair> key_pair =
61       GenerateFalconKeyPair(test_case.private_key_size);
62   ASSERT_THAT(key_pair, IsOk());
63 
64   // Create a new signer.
65   util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
66       FalconSign::New(key_pair->GetPrivateKey());
67   ASSERT_THAT(signer, IsOk());
68 
69   // Sign a message.
70   std::string message = "message to be signed";
71   util::StatusOr<std::string> signature = ((*signer)->Sign(message));
72   ASSERT_THAT(signature, IsOk());
73 
74   // Check signature size.
75   EXPECT_NE(*signature, message);
76   EXPECT_LE((*signature).size(), test_case.signature_length);
77 }
78 
TEST_P(FalconSignTest,NonDeterminism)79 TEST_P(FalconSignTest, NonDeterminism) {
80   if (IsFipsModeEnabled()) {
81     GTEST_SKIP() << "Test assumes kOnlyUseFips is false.";
82   }
83 
84   const FalconTestCase& test_case = GetParam();
85 
86   // Generate falcon key pair.
87   util::StatusOr<FalconKeyPair> key_pair =
88       GenerateFalconKeyPair(test_case.private_key_size);
89   ASSERT_THAT(key_pair, IsOk());
90 
91   // Create two signers based on same private key.
92   util::StatusOr<std::unique_ptr<PublicKeySign>> signer =
93       FalconSign::New(key_pair->GetPrivateKey());
94   ASSERT_THAT(signer, IsOk());
95 
96   // Sign the same message twice, using the same private key.
97   std::string message = "message to be signed";
98   util::StatusOr<std::string> first_signature = ((*signer))->Sign(message);
99   ASSERT_THAT(first_signature, IsOk());
100 
101   util::StatusOr<std::string> second_signature = ((*signer))->Sign(message);
102   ASSERT_THAT(second_signature, IsOk());
103 
104   // Check signatures size.
105   EXPECT_NE(*first_signature, message);
106   EXPECT_LE((*first_signature).size(), test_case.signature_length);
107 
108   EXPECT_NE(*second_signature, message);
109   EXPECT_LE((*second_signature).size(), test_case.signature_length);
110 
111   // Check if signatures are equal.
112   EXPECT_NE(*first_signature, *second_signature);
113 }
114 
TEST_P(FalconSignTest,FipsMode)115 TEST_P(FalconSignTest, FipsMode) {
116   if (!IsFipsModeEnabled()) {
117     GTEST_SKIP() << "Test assumes kOnlyUseFips.";
118   }
119 
120   const FalconTestCase& test_case = GetParam();
121 
122   // Generate falcon key pair.
123   util::StatusOr<FalconKeyPair> key_pair =
124       GenerateFalconKeyPair(test_case.private_key_size);
125   ASSERT_THAT(key_pair, IsOk());
126 
127   // Create a new signer.
128   EXPECT_THAT(FalconSign::New(key_pair->GetPrivateKey()).status(),
129               test::StatusIs(absl::StatusCode::kInternal));
130 }
131 
132 INSTANTIATE_TEST_SUITE_P(
133     FalconSignTests, FalconSignTest,
134     testing::ValuesIn<FalconTestCase>({{"Falcon512", kFalcon512PrivateKeySize,
135                                         PQCLEAN_FALCON512_CRYPTO_BYTES},
136                                        {"Falcon1024", kFalcon1024PrivateKeySize,
137                                         PQCLEAN_FALCON1024_CRYPTO_BYTES}}),
__anon656296240202(const testing::TestParamInfo<FalconSignTest::ParamType>& info) 138     [](const testing::TestParamInfo<FalconSignTest::ParamType>& info) {
139       return info.param.test_name;
140     });
141 
142 }  // namespace
143 }  // namespace subtle
144 }  // namespace tink
145 }  // namespace crypto
146