• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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