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