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