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/privacy_pass/rsa_bssa_public_metadata_client.h"
16
17 #include <sys/types.h>
18
19 #include <memory>
20
21 #include <gmock/gmock.h>
22 #include <gtest/gtest.h>
23 #include "absl/status/statusor.h"
24 #include "anonymous_tokens/cpp/crypto/crypto_utils.h"
25 #include "anonymous_tokens/cpp/privacy_pass/token_encodings.h"
26 #include "anonymous_tokens/cpp/testing/utils.h"
27 #include <openssl/digest.h>
28
29
30 namespace anonymous_tokens {
31 namespace {
32
33 class PrivacyPassRsaBssaClientTest : public testing::Test {
34 protected:
SetUp()35 void SetUp() override {
36 // Seed the random string generator.
37 generator_.seed(GTEST_FLAG_GET(random_seed));
38
39 // Create RSA public and private key structs.
40 auto [test_rsa_public_key, test_rsa_private_key] =
41 GetStrongTestRsaKeyPair2048();
42 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
43 rsa_public_key_,
44 CreatePublicKeyRSA(test_rsa_public_key.n, test_rsa_public_key.e));
45 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
46 rsa_private_key_,
47 CreatePrivateKeyRSA(test_rsa_private_key.n, test_rsa_private_key.e,
48 test_rsa_private_key.d, test_rsa_private_key.p,
49 test_rsa_private_key.q, test_rsa_private_key.dp,
50 test_rsa_private_key.dq, test_rsa_private_key.crt));
51 // Compute RSA BSSA Public Key Token ID.
52 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
53 std::string public_key_der,
54 RsaSsaPssPublicKeyToDerEncoding(rsa_public_key_.get()));
55 const EVP_MD* sha256 = EVP_sha256();
56 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(token_key_id_,
57 ComputeHash(public_key_der, *sha256));
58
59 // Create a client using the rsa_public_key_.
60 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
61 client_,
62 PrivacyPassRsaBssaPublicMetadataClient::Create(*rsa_public_key_.get()));
63
64 // Challenge for the purposes of this test is a random 80 bytes string.
65 challenge_encoding_ = GetRandomString(/*string_length=*/80);
66 // Nonce is a random string of 32 bytes.
67 nonce_ = GetRandomString(/*string_length=*/32);
68 // Random extensions / public metadata for the purposes of this test.
69 extensions_ = {{CreateTestExtension(1), CreateTestExtension(2)}};
70 }
71
72 // Generates a random string of size string_length.
GetRandomString(int string_length)73 std::string GetRandomString(int string_length) {
74 std::string rand(string_length, 0);
75 for (int i = 0; i < string_length; ++i) {
76 rand[i] = static_cast<uint8_t>((distr_u8_)(generator_));
77 }
78 return rand;
79 }
80
81 // Creates test extension by setting the type to extension_type and the value
82 // to a random string of size 'extension_type'.
CreateTestExtension(uint16_t extension_type)83 Extension CreateTestExtension(uint16_t extension_type) {
84 return {
85 /*extension_type=*/extension_type,
86 /*extension_value=*/GetRandomString(/*string_length=*/extension_type)};
87 }
88
89 bssl::UniquePtr<RSA> rsa_public_key_;
90 bssl::UniquePtr<RSA> rsa_private_key_;
91 std::string token_key_id_;
92
93 std::unique_ptr<PrivacyPassRsaBssaPublicMetadataClient> client_;
94 Extensions extensions_;
95 std::string challenge_encoding_;
96 std::string nonce_;
97
98 std::mt19937_64 generator_;
99 std::uniform_int_distribution<int> distr_u8_ =
100 std::uniform_int_distribution<int>{0, 255};
101 };
102
TEST_F(PrivacyPassRsaBssaClientTest,WrongKeySize)103 TEST_F(PrivacyPassRsaBssaClientTest, WrongKeySize) {
104 auto [test_rsa_public_key, _] = GetStrongTestRsaKeyPair3072();
105 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
106 bssl::UniquePtr<RSA> wrong_rsa_public_key,
107 CreatePublicKeyRSA(test_rsa_public_key.n, test_rsa_public_key.e));
108
109 // Passing wrong key.
110 absl::StatusOr<std::unique_ptr<PrivacyPassRsaBssaPublicMetadataClient>>
111 client = PrivacyPassRsaBssaPublicMetadataClient::Create(
112 *wrong_rsa_public_key.get());
113
114 EXPECT_FALSE(client.status().ok());
115 EXPECT_EQ(client.status().code(), absl::StatusCode::kInvalidArgument);
116 EXPECT_THAT(client.status().message(),
117 ::testing::HasSubstr("Token type DA7A must use RSA key with the "
118 "modulus of size 256 bytes"));
119 }
120
TEST_F(PrivacyPassRsaBssaClientTest,WrongSizeOfTokenKeyID)121 TEST_F(PrivacyPassRsaBssaClientTest, WrongSizeOfTokenKeyID) {
122 // Token key ID of invalid size 0.
123 absl::StatusOr<ExtendedTokenRequest> token_req = client_->CreateTokenRequest(
124 /*challenge=*/"", /*nonce=*/"", /*token_key_id=*/"", /*extensions=*/{});
125
126 EXPECT_FALSE(token_req.status().ok());
127 EXPECT_EQ(token_req.status().code(), absl::StatusCode::kInvalidArgument);
128 EXPECT_THAT(token_req.status().message(),
129 ::testing::HasSubstr("token_key_id must be of size 32 bytes"));
130 }
131
TEST_F(PrivacyPassRsaBssaClientTest,CreateRequestTwice)132 TEST_F(PrivacyPassRsaBssaClientTest, CreateRequestTwice) {
133 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
134 ExtendedTokenRequest _,
135 client_->CreateTokenRequest(/*challenge=*/"", /*nonce=*/"", token_key_id_,
136 /*extensions=*/{}));
137 // 2nd request.
138 absl::StatusOr<ExtendedTokenRequest> token_req_2 =
139 client_->CreateTokenRequest(
140 /*challenge=*/"", /*nonce=*/"", token_key_id_, /*extensions=*/{});
141
142 EXPECT_FALSE(token_req_2.status().ok());
143 EXPECT_EQ(token_req_2.status().code(), absl::StatusCode::kFailedPrecondition);
144 EXPECT_THAT(
145 token_req_2.status().message(),
146 ::testing::HasSubstr("CreateTokenRequest has already been called"));
147 }
148
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeTokenWihtoutCreatingRequest)149 TEST_F(PrivacyPassRsaBssaClientTest, FinalizeTokenWihtoutCreatingRequest) {
150 const std::string dummy_signature = GetRandomString(/*string_length=*/256);
151 absl::StatusOr<Token> token = client_->FinalizeToken(dummy_signature);
152
153 EXPECT_FALSE(token.status().ok());
154 EXPECT_EQ(token.status().code(), absl::StatusCode::kFailedPrecondition);
155 EXPECT_THAT(token.status().message(),
156 ::testing::HasSubstr(
157 "CreateRequest must be called before FinalizeToken"));
158 }
159
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeTokenWithEmptySignature)160 TEST_F(PrivacyPassRsaBssaClientTest, FinalizeTokenWithEmptySignature) {
161 // Create token request.
162 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
163 ExtendedTokenRequest token_req,
164 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
165 extensions_));
166 // Finalize the token with empty signature.
167 absl::StatusOr<Token> token = client_->FinalizeToken("");
168
169 EXPECT_FALSE(token.status().ok());
170 EXPECT_EQ(token.status().code(), absl::StatusCode::kInternal);
171 EXPECT_THAT(token.status().message(),
172 ::testing::HasSubstr("Expected blind signature size = 256"));
173 }
174
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeWrongToken)175 TEST_F(PrivacyPassRsaBssaClientTest, FinalizeWrongToken) {
176 // Create token request.
177 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
178 ExtendedTokenRequest token_req,
179 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
180 extensions_));
181 const std::string dummy_signature = GetRandomString(256);
182 // Finalize token with wrong signature.
183 absl::StatusOr<Token> token = client_->FinalizeToken(dummy_signature);
184
185 EXPECT_FALSE(token.status().ok());
186 EXPECT_EQ(token.status().code(), absl::StatusCode::kInvalidArgument);
187 EXPECT_THAT(token.status().message(),
188 ::testing::HasSubstr("PSS padding verification failed"));
189 }
190
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeTokenWhereCreateRequestHasNoExtensions)191 TEST_F(PrivacyPassRsaBssaClientTest,
192 FinalizeTokenWhereCreateRequestHasNoExtensions) {
193 // Create token request without extensions.
194 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
195 ExtendedTokenRequest token_req,
196 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
197 /*extensions=*/{}));
198 // Compute token with populated extensions.
199 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
200 EncodeExtensions(extensions_));
201 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
202 const std::string signature,
203 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
204 /*public_metadata=*/encoded_extensions,
205 *rsa_private_key_.get(),
206 /*use_rsa_public_exponent=*/true));
207 // Finalize the token.
208 absl::StatusOr<Token> token = client_->FinalizeToken(signature);
209
210 EXPECT_FALSE(token.status().ok());
211 EXPECT_EQ(token.status().code(), absl::StatusCode::kInvalidArgument);
212 EXPECT_THAT(token.status().message(),
213 ::testing::HasSubstr("PSS padding verification failed"));
214 }
215
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeTokenCreatedWithEmptyExtensions)216 TEST_F(PrivacyPassRsaBssaClientTest, FinalizeTokenCreatedWithEmptyExtensions) {
217 // Create token request.
218 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
219 ExtendedTokenRequest token_req,
220 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
221 extensions_));
222 // Compute token without encoded_extensions.
223 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
224 const std::string signature,
225 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
226 /*public_metadata=*/"",
227 *rsa_private_key_.get(),
228 /*use_rsa_public_exponent=*/true));
229 // Finalize the token.
230 absl::StatusOr<Token> token = client_->FinalizeToken(signature);
231
232 EXPECT_FALSE(token.status().ok());
233 EXPECT_EQ(token.status().code(), absl::StatusCode::kInvalidArgument);
234 EXPECT_THAT(token.status().message(),
235 ::testing::HasSubstr("PSS padding verification failed"));
236 }
237
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeTokenTwice)238 TEST_F(PrivacyPassRsaBssaClientTest, FinalizeTokenTwice) {
239 // Create token request.
240 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
241 ExtendedTokenRequest token_req,
242 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
243 extensions_));
244 // Compute correct token, given the ExtendedTokenRequest.
245 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
246 EncodeExtensions(token_req.extensions));
247 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
248 const std::string signature,
249 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
250 /*public_metadata=*/encoded_extensions,
251 *rsa_private_key_.get(),
252 /*use_rsa_public_exponent=*/false));
253 // Finalize the token.
254 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Token _,
255 client_->FinalizeToken(signature));
256 // Finalize the token again.
257 absl::StatusOr<Token> token_2 = client_->FinalizeToken(signature);
258
259 EXPECT_FALSE(token_2.status().ok());
260 EXPECT_EQ(token_2.status().code(), absl::StatusCode::kFailedPrecondition);
261 EXPECT_THAT(token_2.status().message(),
262 ::testing::HasSubstr(
263 "RsaBlinder is in wrong state to unblind signature"));
264 }
265
TEST_F(PrivacyPassRsaBssaClientTest,FinalizeTokenWithWrongClient)266 TEST_F(PrivacyPassRsaBssaClientTest, FinalizeTokenWithWrongClient) {
267 // Create token request.
268 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
269 ExtendedTokenRequest token_req_1,
270 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
271 extensions_));
272 // Create a request with client_2.
273 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
274 std::unique_ptr<PrivacyPassRsaBssaPublicMetadataClient> client_2,
275 PrivacyPassRsaBssaPublicMetadataClient::Create(*rsa_public_key_.get()));
276 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
277 ExtendedTokenRequest _,
278 client_2->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
279 extensions_));
280 // Compute correct signature for client_, given token_req_1.
281 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
282 EncodeExtensions(token_req_1.extensions));
283 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
284 const std::string signature,
285 TestSignWithPublicMetadata(token_req_1.request.blinded_token_request,
286 /*public_metadata=*/encoded_extensions,
287 *rsa_private_key_.get(),
288 /*use_rsa_public_exponent=*/false));
289 // Finalize the token with wrong client_2.
290 absl::StatusOr<Token> token = client_2->FinalizeToken(signature);
291
292 EXPECT_FALSE(token.status().ok());
293 EXPECT_EQ(token.status().code(), absl::StatusCode::kInvalidArgument);
294 EXPECT_THAT(token.status().message(),
295 ::testing::HasSubstr("PSS padding verification failed"));
296 }
297
TEST_F(PrivacyPassRsaBssaClientTest,VerifyWithWrongExtensions)298 TEST_F(PrivacyPassRsaBssaClientTest, VerifyWithWrongExtensions) {
299 // Create token request.
300 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
301 ExtendedTokenRequest token_req,
302 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
303 extensions_));
304 // Compute correct token, given the ExtendedTokenRequest.
305 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
306 EncodeExtensions(token_req.extensions));
307 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
308 const std::string signature,
309 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
310 /*public_metadata=*/encoded_extensions,
311 *rsa_private_key_.get(),
312 /*use_rsa_public_exponent=*/false));
313 // Finalize the token.
314 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Token token,
315 client_->FinalizeToken(signature));
316 // Run public key verification using wrong extensions.
317 const Extensions wrong_extensions = {
318 {CreateTestExtension(2), CreateTestExtension(3)}};
319 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string wrong_encoded_extensions,
320 EncodeExtensions(wrong_extensions));
321 absl::Status verification = PrivacyPassRsaBssaPublicMetadataClient::Verify(
322 token, wrong_encoded_extensions, *rsa_public_key_.get());
323
324 EXPECT_FALSE(verification.ok());
325 EXPECT_EQ(verification.code(), absl::StatusCode::kInvalidArgument);
326 EXPECT_THAT(verification.message(),
327 ::testing::HasSubstr("PSS padding verification failed"));
328 }
329
TEST_F(PrivacyPassRsaBssaClientTest,VerifyWithEmptyExtensions)330 TEST_F(PrivacyPassRsaBssaClientTest, VerifyWithEmptyExtensions) {
331 // Create token request.
332 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
333 ExtendedTokenRequest token_req,
334 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
335 extensions_));
336 // Compute correct token, given the ExtendedTokenRequest.
337 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
338 EncodeExtensions(token_req.extensions));
339 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
340 const std::string signature,
341 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
342 /*public_metadata=*/encoded_extensions,
343 *rsa_private_key_.get(),
344 /*use_rsa_public_exponent=*/false));
345 // Finalize the token.
346 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Token token,
347 client_->FinalizeToken(signature));
348 // Run public key verification using empty extensions.
349 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string empty_encoded_extensions,
350 EncodeExtensions(/*extensions=*/{}));
351 absl::Status verification = PrivacyPassRsaBssaPublicMetadataClient::Verify(
352 token, empty_encoded_extensions, *rsa_public_key_.get());
353
354 EXPECT_FALSE(verification.ok());
355 EXPECT_EQ(verification.code(), absl::StatusCode::kInvalidArgument);
356 EXPECT_THAT(verification.message(),
357 ::testing::HasSubstr("PSS padding verification failed"));
358 }
359
TEST_F(PrivacyPassRsaBssaClientTest,VerifyWithWrongPublicKey)360 TEST_F(PrivacyPassRsaBssaClientTest, VerifyWithWrongPublicKey) {
361 // Create token request.
362 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
363 ExtendedTokenRequest token_req,
364 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
365 extensions_));
366 // Compute correct token, given the ExtendedTokenRequest.
367 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
368 EncodeExtensions(token_req.extensions));
369 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
370 const std::string signature,
371 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
372 /*public_metadata=*/encoded_extensions,
373 *rsa_private_key_.get(),
374 /*use_rsa_public_exponent=*/false));
375 // Finalize the token.
376 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Token token,
377 client_->FinalizeToken(signature));
378 // Run public key verification using a new key.
379 auto [test_rsa_public_key, _] = GetAnotherStrongTestRsaKeyPair2048();
380 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
381 bssl::UniquePtr<RSA> wrong_rsa_public_key,
382 CreatePublicKeyRSA(test_rsa_public_key.n, test_rsa_public_key.e));
383 absl::Status verification = PrivacyPassRsaBssaPublicMetadataClient::Verify(
384 token, encoded_extensions, *wrong_rsa_public_key.get());
385
386 EXPECT_FALSE(verification.ok());
387 EXPECT_EQ(verification.code(), absl::StatusCode::kInvalidArgument);
388 EXPECT_THAT(verification.message(),
389 ::testing::HasSubstr("PSS padding verification failed"));
390 }
391
TEST_F(PrivacyPassRsaBssaClientTest,TokenCreationAndVerificationSuccess)392 TEST_F(PrivacyPassRsaBssaClientTest, TokenCreationAndVerificationSuccess) {
393 // Create token request.
394 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
395 ExtendedTokenRequest token_req,
396 client_->CreateTokenRequest(challenge_encoding_, nonce_, token_key_id_,
397 extensions_));
398 // Compute correct token, given the ExtendedTokenRequest.
399 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
400 EncodeExtensions(token_req.extensions));
401 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
402 const std::string signature,
403 TestSignWithPublicMetadata(token_req.request.blinded_token_request,
404 /*public_metadata=*/encoded_extensions,
405 *rsa_private_key_.get(),
406 /*use_rsa_public_exponent=*/false));
407 // Finalize the token.
408 ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Token token,
409 client_->FinalizeToken(signature));
410 // Run public key verification successfully.
411 EXPECT_TRUE(PrivacyPassRsaBssaPublicMetadataClient::Verify(
412 token, encoded_extensions, *rsa_public_key_.get())
413 .ok());
414 }
415
416 } // namespace
417 } // namespace anonymous_tokens
418