1 // Copyright 2018 Google Inc.
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/subtle/rsa_ssa_pss_sign_boringssl.h"
18
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include "absl/status/status.h"
22 #include "absl/strings/escaping.h"
23 #include "openssl/bn.h"
24 #include "openssl/rsa.h"
25 #include "tink/internal/fips_utils.h"
26 #include "tink/internal/rsa_util.h"
27 #include "tink/internal/ssl_unique_ptr.h"
28 #include "tink/subtle/rsa_ssa_pss_verify_boringssl.h"
29 #include "tink/util/test_matchers.h"
30
31 namespace crypto {
32 namespace tink {
33 namespace subtle {
34 namespace {
35
36 using ::crypto::tink::test::IsOk;
37 using ::crypto::tink::test::StatusIs;
38 using ::testing::IsEmpty;
39 using ::testing::Not;
40
41 class RsaPssSignBoringsslTest : public ::testing::Test {
42 public:
RsaPssSignBoringsslTest()43 RsaPssSignBoringsslTest() : rsa_f4_(BN_new()) {
44 EXPECT_TRUE(BN_set_word(rsa_f4_.get(), RSA_F4));
45 EXPECT_THAT(
46 internal::NewRsaKeyPair(/*modulus_size_in_bits=*/2048, rsa_f4_.get(),
47 &private_key_, &public_key_),
48 IsOk());
49 }
50
51 protected:
52 internal::SslUniquePtr<BIGNUM> rsa_f4_;
53 internal::RsaPrivateKey private_key_;
54 internal::RsaPublicKey public_key_;
55 };
56
TEST_F(RsaPssSignBoringsslTest,EncodesPss)57 TEST_F(RsaPssSignBoringsslTest, EncodesPss) {
58 if (internal::IsFipsModeEnabled()) {
59 GTEST_SKIP() << "Test not run in FIPS-only mode";
60 }
61
62 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
63 /*mgf1_hash=*/HashType::SHA256,
64 /*salt_length=*/32};
65
66 auto signer_or = RsaSsaPssSignBoringSsl::New(private_key_, params);
67 ASSERT_THAT(signer_or, IsOk());
68
69 auto signature_or = signer_or.value()->Sign("testdata");
70 ASSERT_THAT(signature_or, IsOk());
71 EXPECT_THAT(signature_or.value(), Not(IsEmpty()));
72
73 auto verifier_or = RsaSsaPssVerifyBoringSsl::New(public_key_, params);
74 ASSERT_THAT(verifier_or, IsOk());
75 EXPECT_THAT(verifier_or.value()->Verify(signature_or.value(), "testdata"),
76 IsOk());
77 }
78
TEST_F(RsaPssSignBoringsslTest,EncodesPssWithSeparateHashes)79 TEST_F(RsaPssSignBoringsslTest, EncodesPssWithSeparateHashes) {
80 if (internal::IsFipsModeEnabled()) {
81 GTEST_SKIP() << "Test not run in FIPS-only mode";
82 }
83
84 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
85 /*mgf1_hash=*/HashType::SHA1,
86 /*salt_length=*/32};
87
88 auto signer_or = RsaSsaPssSignBoringSsl::New(private_key_, params);
89 ASSERT_THAT(signer_or, IsOk());
90
91 auto signature_or = signer_or.value()->Sign("testdata");
92 ASSERT_THAT(signature_or, IsOk());
93 EXPECT_THAT(signature_or.value(), Not(IsEmpty()));
94
95 auto verifier_or = RsaSsaPssVerifyBoringSsl::New(public_key_, params);
96 ASSERT_THAT(verifier_or, IsOk());
97 EXPECT_THAT(verifier_or.value()->Verify(signature_or.value(), "testdata"),
98 IsOk());
99 }
100
TEST_F(RsaPssSignBoringsslTest,RejectsInvalidPaddingHash)101 TEST_F(RsaPssSignBoringsslTest, RejectsInvalidPaddingHash) {
102 if (internal::IsFipsModeEnabled()) {
103 GTEST_SKIP() << "Test not run in FIPS-only mode";
104 }
105
106 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
107 /*mgf1_hash=*/HashType::UNKNOWN_HASH,
108 /*salt_length=*/0};
109 ASSERT_THAT(RsaSsaPssSignBoringSsl::New(private_key_, params).status(),
110 StatusIs(absl::StatusCode::kUnimplemented));
111 }
112
TEST_F(RsaPssSignBoringsslTest,RejectsUnsafePaddingHash)113 TEST_F(RsaPssSignBoringsslTest, RejectsUnsafePaddingHash) {
114 if (internal::IsFipsModeEnabled()) {
115 GTEST_SKIP() << "Test not run in FIPS-only mode";
116 }
117
118 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA1,
119 /*mgf1_hash=*/HashType::SHA1,
120 /*salt_length=*/0};
121 ASSERT_THAT(RsaSsaPssSignBoringSsl::New(private_key_, params).status(),
122 StatusIs(absl::StatusCode::kInvalidArgument));
123 }
124
TEST_F(RsaPssSignBoringsslTest,RejectsInvalidCrtParams)125 TEST_F(RsaPssSignBoringsslTest, RejectsInvalidCrtParams) {
126 if (internal::IsFipsModeEnabled()) {
127 GTEST_SKIP() << "Test not run in FIPS-only mode";
128 }
129
130 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
131 /*mgf1_hash=*/HashType::SHA256,
132 /*salt_length=*/32};
133 ASSERT_THAT(private_key_.crt, Not(IsEmpty()));
134 ASSERT_THAT(private_key_.dq, Not(IsEmpty()));
135 ASSERT_THAT(private_key_.dp, Not(IsEmpty()));
136
137 // Flip a few bits in the CRT parameters; check that creation fails.
138 {
139 internal::RsaPrivateKey key = private_key_;
140 key.crt[0] ^= 0x80;
141 auto signer_or = RsaSsaPssSignBoringSsl::New(key, params);
142 EXPECT_THAT(signer_or.status(),
143 StatusIs(absl::StatusCode::kInvalidArgument));
144 }
145 {
146 internal::RsaPrivateKey key = private_key_;
147 key.dq[0] ^= 0x08;
148 auto signer_or = RsaSsaPssSignBoringSsl::New(key, params);
149 EXPECT_THAT(signer_or.status(),
150 StatusIs(absl::StatusCode::kInvalidArgument));
151 }
152 {
153 internal::RsaPrivateKey key = private_key_;
154 key.dp[0] ^= 0x04;
155 auto signer_or = RsaSsaPssSignBoringSsl::New(key, params);
156 EXPECT_THAT(signer_or.status(),
157 StatusIs(absl::StatusCode::kInvalidArgument));
158 }
159 }
160
161 // FIPS-only mode test
TEST_F(RsaPssSignBoringsslTest,TestFipsFailWithoutBoringCrypto)162 TEST_F(RsaPssSignBoringsslTest, TestFipsFailWithoutBoringCrypto) {
163 if (!internal::IsFipsModeEnabled() || internal::IsFipsEnabledInSsl()) {
164 GTEST_SKIP()
165 << "Test assumes kOnlyUseFips but BoringCrypto is unavailable.";
166 }
167
168 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
169 /*mgf1_hash=*/HashType::SHA256,
170 /*salt_length=*/32};
171 EXPECT_THAT(RsaSsaPssSignBoringSsl::New(private_key_, params).status(),
172 StatusIs(absl::StatusCode::kInternal));
173 }
174
TEST_F(RsaPssSignBoringsslTest,TestRestrictedFipsModuli)175 TEST_F(RsaPssSignBoringsslTest, TestRestrictedFipsModuli) {
176 if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) {
177 GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto.";
178 }
179 internal::RsaPrivateKey private_key;
180 internal::RsaPublicKey public_key;
181
182 EXPECT_THAT(internal::NewRsaKeyPair(/*modulus_size_in_bits=*/4096,
183 rsa_f4_.get(), &private_key, &public_key),
184 IsOk());
185
186 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
187 /*mgf1_hash=*/HashType::SHA256,
188 /*salt_length=*/32};
189 EXPECT_THAT(RsaSsaPssSignBoringSsl::New(private_key, params).status(),
190 StatusIs(absl::StatusCode::kInternal));
191 }
192
TEST_F(RsaPssSignBoringsslTest,TestAllowedFipsModuli)193 TEST_F(RsaPssSignBoringsslTest, TestAllowedFipsModuli) {
194 if (!internal::IsFipsModeEnabled() || !internal::IsFipsEnabledInSsl()) {
195 GTEST_SKIP() << "Test assumes kOnlyUseFips and BoringCrypto.";
196 }
197 internal::RsaPrivateKey private_key;
198 internal::RsaPublicKey public_key;
199
200 EXPECT_THAT(internal::NewRsaKeyPair(/*modulus_size_in_bits=*/3072,
201 rsa_f4_.get(), &private_key, &public_key),
202 IsOk());
203
204 internal::RsaSsaPssParams params{/*sig_hash=*/HashType::SHA256,
205 /*mgf1_hash=*/HashType::SHA256,
206 /*salt_length=*/32};
207 EXPECT_THAT(RsaSsaPssSignBoringSsl::New(private_key, params).status(),
208 IsOk());
209 }
210
211 } // namespace
212 } // namespace subtle
213 } // namespace tink
214 } // namespace crypto
215