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