1 // Copyright 2023 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 // https://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 #include "anonymous_tokens/cpp/crypto/rsa_ssa_pss_verifier.h"
16
17 #include <memory>
18 #include <string>
19 #include <utility>
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include "absl/status/status.h"
24 #include "absl/status/statusor.h"
25 #include "absl/strings/string_view.h"
26 #include "anonymous_tokens/cpp/crypto/anonymous_tokens_pb_openssl_converters.h"
27 #include "anonymous_tokens/cpp/crypto/constants.h"
28 #include "anonymous_tokens/cpp/crypto/crypto_utils.h"
29 #include "anonymous_tokens/cpp/testing/proto_utils.h"
30 #include "anonymous_tokens/cpp/testing/utils.h"
31 #include "anonymous_tokens/proto/anonymous_tokens.pb.h"
32 #include <openssl/rsa.h>
33
34
35 namespace anonymous_tokens {
36 namespace {
37
TEST(RsaSsaPssVerifier,SuccessfulVerification)38 TEST(RsaSsaPssVerifier, SuccessfulVerification) {
39 const IetfStandardRsaBlindSignatureTestVector test_vec =
40 GetIetfStandardRsaBlindSignatureTestVector();
41 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const auto test_keys,
42 GetIetfStandardRsaBlindSignatureTestKeys());
43 const EVP_MD *sig_hash = EVP_sha384(); // Owned by BoringSSL
44 const EVP_MD *mgf1_hash = EVP_sha384(); // Owned by BoringSSL
45 const int salt_length = kSaltLengthInBytes48;
46 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
47 const auto verifier,
48 RsaSsaPssVerifier::New(salt_length, sig_hash, mgf1_hash, test_keys.first,
49 /*use_rsa_public_exponent=*/true));
50 EXPECT_TRUE(verifier->Verify(test_vec.signature, test_vec.message).ok());
51 }
52
TEST(RsaSsaPssVerifier,InvalidSignature)53 TEST(RsaSsaPssVerifier, InvalidSignature) {
54 const IetfStandardRsaBlindSignatureTestVector test_vec =
55 GetIetfStandardRsaBlindSignatureTestVector();
56 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const auto test_keys,
57 GetIetfStandardRsaBlindSignatureTestKeys());
58 const EVP_MD *sig_hash = EVP_sha384(); // Owned by BoringSSL
59 const EVP_MD *mgf1_hash = EVP_sha384(); // Owned by BoringSSL
60 const int salt_length = kSaltLengthInBytes48;
61 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
62 const auto verifier,
63 RsaSsaPssVerifier::New(salt_length, sig_hash, mgf1_hash, test_keys.first,
64 /*use_rsa_public_exponent=*/true));
65 // corrupt signature
66 std::string wrong_sig = test_vec.signature;
67 wrong_sig.replace(10, 1, "x");
68
69 absl::Status verification_result =
70 verifier->Verify(wrong_sig, test_vec.message);
71 EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
72 EXPECT_THAT(verification_result.message(),
73 testing::HasSubstr("verification failed"));
74 }
75
TEST(RsaSsaPssVerifier,InvalidVerificationKey)76 TEST(RsaSsaPssVerifier, InvalidVerificationKey) {
77 const IetfStandardRsaBlindSignatureTestVector test_vec =
78 GetIetfStandardRsaBlindSignatureTestVector();
79 const EVP_MD *sig_hash = EVP_sha384(); // Owned by BoringSSL
80 const EVP_MD *mgf1_hash = EVP_sha384(); // Owned by BoringSSL
81 const int salt_length = kSaltLengthInBytes48;
82 // wrong key
83 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto new_keys_pair, GetStandardRsaKeyPair());
84 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
85 const auto verifier,
86 RsaSsaPssVerifier::New(salt_length, sig_hash, mgf1_hash,
87 new_keys_pair.first,
88 /*use_rsa_public_exponent=*/true));
89
90 absl::Status verification_result =
91 verifier->Verify(test_vec.signature, test_vec.message);
92 EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
93 EXPECT_THAT(verification_result.message(),
94 testing::HasSubstr("verification failed"));
95 }
96
TEST(RsaSsaPssVerifierTestWithPublicMetadata,EmptyMessageStandardVerificationSuccess)97 TEST(RsaSsaPssVerifierTestWithPublicMetadata,
98 EmptyMessageStandardVerificationSuccess) {
99 absl::string_view message = "";
100 const EVP_MD *sig_hash = EVP_sha384(); // Owned by BoringSSL
101 const EVP_MD *mgf1_hash = EVP_sha384(); // Owned by BoringSSL
102 const int salt_length = kSaltLengthInBytes48;
103 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const auto test_key,
104 GetStandardRsaKeyPair());
105 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
106 auto private_key, AnonymousTokensRSAPrivateKeyToRSA(test_key.second));
107 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
108 std::string encoded_message,
109 EncodeMessageForTests(message, test_key.first, sig_hash, mgf1_hash,
110 salt_length));
111 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
112 std::string potentially_insecure_signature,
113 TestSign(encoded_message, private_key.get()));
114 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
115 auto verifier,
116 RsaSsaPssVerifier::New(salt_length, sig_hash, mgf1_hash, test_key.first,
117 /*use_rsa_public_exponent=*/true));
118 EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
119 }
120
TEST(RsaSsaPssVerifierTestWithPublicMetadata,IetfRsaBlindSignaturesWithPublicMetadataTestVectorsSuccess)121 TEST(RsaSsaPssVerifierTestWithPublicMetadata,
122 IetfRsaBlindSignaturesWithPublicMetadataTestVectorsSuccess) {
123 auto test_vectors = GetIetfRsaBlindSignatureWithPublicMetadataTestVectors();
124 const EVP_MD *sig_hash = EVP_sha384(); // Owned by BoringSSL
125 const EVP_MD *mgf1_hash = EVP_sha384(); // Owned by BoringSSL
126 const int salt_length = kSaltLengthInBytes48;
127 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
128 const auto test_key,
129 GetIetfRsaBlindSignatureWithPublicMetadataTestKeys());
130 for (const auto &test_vector : test_vectors) {
131 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
132 auto verifier,
133 RsaSsaPssVerifier::New(salt_length, sig_hash, mgf1_hash, test_key.first,
134 /*use_rsa_public_exponent=*/true,
135 test_vector.public_metadata));
136 EXPECT_TRUE(verifier
137 ->Verify(test_vector.signature,
138 MaskMessageConcat(test_vector.message_mask,
139 test_vector.message))
140 .ok());
141 }
142 }
143
TEST(RsaSsaPssVerifierTestWithPublicMetadata,IetfRsaBlindSignaturesWithPublicMetadataNoPublicExponentSuccess)144 TEST(RsaSsaPssVerifierTestWithPublicMetadata,
145 IetfRsaBlindSignaturesWithPublicMetadataNoPublicExponentSuccess) {
146 auto test_vectors =
147 GetIetfPartiallyBlindRSASignatureNoPublicExponentTestVectors();
148 const EVP_MD *sig_hash = EVP_sha384(); // Owned by BoringSSL
149 const EVP_MD *mgf1_hash = EVP_sha384(); // Owned by BoringSSL
150 const int salt_length = kSaltLengthInBytes48;
151 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
152 const auto test_key,
153 GetIetfRsaBlindSignatureWithPublicMetadataTestKeys());
154 for (const auto &test_vector : test_vectors) {
155 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
156 auto verifier,
157 RsaSsaPssVerifier::New(salt_length, sig_hash, mgf1_hash, test_key.first,
158 /*use_rsa_public_exponent=*/false,
159 test_vector.public_metadata));
160 EXPECT_TRUE(
161 verifier->Verify(test_vector.signature, test_vector.message).ok());
162 }
163 }
164
165 using RsaSsaPssVerifierPublicMetadataTestParams =
166 std::tuple<absl::StatusOr<std::pair<RSAPublicKey, RSAPrivateKey>>,
167 /*use_rsa_public_exponent*/ bool>;
168
169 class RsaSsaPssVerifierTestWithPublicMetadata
170 : public ::testing::TestWithParam<
171 RsaSsaPssVerifierPublicMetadataTestParams> {
172 protected:
SetUp()173 void SetUp() override {
174 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(auto keys_pair, std::get<0>(GetParam()));
175 use_rsa_public_exponent_ = std::get<1>(GetParam());
176 public_key_ = std::move(keys_pair.first);
177 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
178 private_key_, AnonymousTokensRSAPrivateKeyToRSA(keys_pair.second));
179 // NOTE: using recommended RsaSsaPssParams
180 sig_hash_ = EVP_sha384();
181 mgf1_hash_ = EVP_sha384();
182 salt_length_ = kSaltLengthInBytes48;
183 }
184
185 RSAPublicKey public_key_;
186 bssl::UniquePtr<RSA> private_key_;
187 const EVP_MD *sig_hash_; // Owned by BoringSSL.
188 const EVP_MD *mgf1_hash_; // Owned by BoringSSL.
189 int salt_length_;
190 bool use_rsa_public_exponent_;
191 };
192
193 // This test only tests whether the implemented verfier 'verifies' properly
194 // under some public metadata. The outline of method calls in this test should
195 // not be assumed a secure signature scheme (and used in other places) as the
196 // security has not been proven/analyzed.
TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,VerifierWorksWithPublicMetadata)197 TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,
198 VerifierWorksWithPublicMetadata) {
199 absl::string_view message = "Hello World!";
200 absl::string_view public_metadata = "pubmd!";
201 std::string augmented_message =
202 EncodeMessagePublicMetadata(message, public_metadata);
203 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
204 std::string encoded_message,
205 EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
206 mgf1_hash_, salt_length_));
207 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
208 std::string potentially_insecure_signature,
209 TestSignWithPublicMetadata(encoded_message, public_metadata,
210 *private_key_, use_rsa_public_exponent_));
211 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
212 auto verifier,
213 RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
214 use_rsa_public_exponent_, public_metadata));
215 EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
216 }
217
TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,VerifierFailsToVerifyWithWrongPublicMetadata)218 TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,
219 VerifierFailsToVerifyWithWrongPublicMetadata) {
220 absl::string_view message = "Hello World!";
221 absl::string_view public_metadata = "pubmd!";
222 absl::string_view public_metadata_2 = "pubmd2";
223 std::string augmented_message =
224 EncodeMessagePublicMetadata(message, public_metadata);
225 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
226 std::string encoded_message,
227 EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
228 mgf1_hash_, salt_length_));
229 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
230 std::string potentially_insecure_signature,
231 TestSignWithPublicMetadata(encoded_message, public_metadata,
232 *private_key_, use_rsa_public_exponent_));
233 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
234 auto verifier,
235 RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
236 use_rsa_public_exponent_, public_metadata_2));
237 absl::Status verification_result =
238 verifier->Verify(potentially_insecure_signature, message);
239 EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
240 EXPECT_THAT(verification_result.message(),
241 testing::HasSubstr("verification failed"));
242 }
243
TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,VerifierFailsToVerifyWithEmptyPublicMetadata)244 TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,
245 VerifierFailsToVerifyWithEmptyPublicMetadata) {
246 absl::string_view message = "Hello World!";
247 absl::string_view public_metadata = "pubmd!";
248 absl::string_view empty_public_metadata = "";
249 std::string augmented_message =
250 EncodeMessagePublicMetadata(message, public_metadata);
251 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
252 std::string encoded_message,
253 EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
254 mgf1_hash_, salt_length_));
255 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
256 std::string potentially_insecure_signature,
257 TestSignWithPublicMetadata(encoded_message, public_metadata,
258 *private_key_, use_rsa_public_exponent_));
259 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
260 auto verifier,
261 RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
262 use_rsa_public_exponent_, empty_public_metadata));
263 absl::Status verification_result =
264 verifier->Verify(potentially_insecure_signature, message);
265 EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
266 EXPECT_THAT(verification_result.message(),
267 testing::HasSubstr("verification failed"));
268 }
269
TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,VerifierFailsToVerifyWithoutPublicMetadataSupport)270 TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,
271 VerifierFailsToVerifyWithoutPublicMetadataSupport) {
272 absl::string_view message = "Hello World!";
273 absl::string_view public_metadata = "pubmd!";
274 std::string augmented_message =
275 EncodeMessagePublicMetadata(message, public_metadata);
276 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
277 std::string encoded_message,
278 EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
279 mgf1_hash_, salt_length_));
280 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
281 std::string potentially_insecure_signature,
282 TestSignWithPublicMetadata(encoded_message, public_metadata,
283 *private_key_, use_rsa_public_exponent_));
284 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
285 auto verifier,
286 RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
287 use_rsa_public_exponent_));
288 absl::Status verification_result =
289 verifier->Verify(potentially_insecure_signature, message);
290 EXPECT_EQ(verification_result.code(), absl::StatusCode::kInvalidArgument);
291 EXPECT_THAT(verification_result.message(),
292 testing::HasSubstr("verification failed"));
293 }
294
TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,EmptyMessageEmptyPublicMetadataVerificationSuccess)295 TEST_P(RsaSsaPssVerifierTestWithPublicMetadata,
296 EmptyMessageEmptyPublicMetadataVerificationSuccess) {
297 absl::string_view message = "";
298 absl::string_view public_metadata = "";
299 std::string augmented_message =
300 EncodeMessagePublicMetadata(message, public_metadata);
301 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
302 std::string encoded_message,
303 EncodeMessageForTests(augmented_message, public_key_, sig_hash_,
304 mgf1_hash_, salt_length_));
305 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
306 std::string potentially_insecure_signature,
307 TestSignWithPublicMetadata(encoded_message, public_metadata,
308 *private_key_.get(),
309 use_rsa_public_exponent_));
310 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
311 auto verifier,
312 RsaSsaPssVerifier::New(salt_length_, sig_hash_, mgf1_hash_, public_key_,
313 use_rsa_public_exponent_, public_metadata));
314 EXPECT_TRUE(verifier->Verify(potentially_insecure_signature, message).ok());
315 }
316
317 INSTANTIATE_TEST_SUITE_P(
318 RsaSsaPssVerifierTestWithPublicMetadata,
319 RsaSsaPssVerifierTestWithPublicMetadata,
320 ::testing::Combine(
321 ::testing::Values(GetStrongRsaKeys2048(), GetAnotherStrongRsaKeys2048(),
322 GetStrongRsaKeys3072(), GetStrongRsaKeys4096()),
323 /*use_rsa_public_exponent*/ ::testing::Values(true, false)));
324
325 } // namespace
326 } // namespace anonymous_tokens
327
328