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/token_encodings.h"
16 
17 #include <cstdint>
18 #include <string>
19 #include <utility>
20 #include <vector>
21 
22 #include <gmock/gmock.h>
23 #include <gtest/gtest.h>
24 #include "absl/status/status.h"
25 #include "absl/status/statusor.h"
26 #include "absl/strings/escaping.h"
27 #include "absl/time/clock.h"
28 #include "absl/time/time.h"
29 #include "absl/types/span.h"
30 #include "anonymous_tokens/cpp/testing/utils.h"
31 
32 namespace anonymous_tokens {
33 namespace {
34 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,EmptyAuthenticatorInputTest)35 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
36      EmptyAuthenticatorInputTest) {
37   Token token;
38   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string authenticator_input,
39                                    AuthenticatorInput(token));
40 
41   std::string expected_authenticator_input_encoding;
42   ASSERT_TRUE(
43       absl::HexStringToBytes("DA7A", &expected_authenticator_input_encoding));
44 
45   EXPECT_EQ(authenticator_input, expected_authenticator_input_encoding);
46 }
47 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,AuthenticatorInputTest)48 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, AuthenticatorInputTest) {
49   std::string token_key_id;
50   ASSERT_TRUE(absl::HexStringToBytes(
51       "ca572f8982a9ca248a3056186322d93ca147266121ddeb5632c07f1f71cd2708",
52       &token_key_id));
53   std::string nonce;
54   ASSERT_TRUE(absl::HexStringToBytes(
55       "5f5e46604255ac6a8ae0820f5b20c236118d97d917509ccbc96b5a82ae40ebeb",
56       &nonce));
57   std::string context;
58   ASSERT_TRUE(absl::HexStringToBytes(
59       "11e15c91a7c2ad02abd66645802373db1d823bea80f08d452541fb2b62b5898b",
60       &context));
61   Token token = {/*token_type=*/0XDA7A, std::move(token_key_id),
62                  std::move(nonce), std::move(context)};
63 
64   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string authenticator_input,
65                                    AuthenticatorInput(token));
66 
67   std::string expected_authenticator_input_encoding;
68   ASSERT_TRUE(absl::HexStringToBytes(
69       "DA7A5f5e46604255ac6a8ae0820f5b20c236118d97d917509ccbc96b5a82ae40ebeb11e1"
70       "5c91a7c2ad02abd66645802373db1d823bea80f08d452541fb2b62b5898bca572f8982a9"
71       "ca248a3056186322d93ca147266121ddeb5632c07f1f71cd2708",
72       &expected_authenticator_input_encoding));
73   EXPECT_EQ(authenticator_input, expected_authenticator_input_encoding);
74 }
75 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,EmptyMarshalTokenTest)76 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, EmptyMarshalTokenTest) {
77   Token token;
78   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_token,
79                                    MarshalToken(token));
80   std::string expected_token_encoding;
81   ASSERT_TRUE(absl::HexStringToBytes("DA7A", &expected_token_encoding));
82 
83   EXPECT_EQ(encoded_token, expected_token_encoding);
84 }
85 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,MarshalTokenTest)86 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, MarshalTokenTest) {
87   std::string token_key_id;
88   ASSERT_TRUE(absl::HexStringToBytes(
89       "ca572f8982a9ca248a3056186322d93ca147266121ddeb5632c07f1f71cd2708",
90       &token_key_id));
91   std::string nonce;
92   ASSERT_TRUE(absl::HexStringToBytes(
93       "5f5e46604255ac6a8ae0820f5b20c236118d97d917509ccbc96b5a82ae40ebeb",
94       &nonce));
95   std::string context;
96   ASSERT_TRUE(absl::HexStringToBytes(
97       "11e15c91a7c2ad02abd66645802373db1d823bea80f08d452541fb2b62b5898b",
98       &context));
99   std::string authenticator;
100   ASSERT_TRUE(absl::HexStringToBytes(
101       "4ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560568620"
102       "0d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129"
103       "b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881f5e156"
104       "68e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d59402a8"
105       "7e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f5c27d0"
106       "1ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac1f8f61"
107       "1029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000ae10548"
108       "3941652e",
109       &authenticator));
110   Token token = {/*token_type=*/0XDA7A, std::move(token_key_id),
111                  std::move(nonce), std::move(context),
112                  std::move(authenticator)};
113 
114   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_token,
115                                    MarshalToken(token));
116 
117   std::string expected_token_encoding;
118   ASSERT_TRUE(absl::HexStringToBytes(
119       "DA7A5f5e46604255ac6a8ae0820f5b20c236118d97d917509ccbc96b5a82ae40ebeb11e1"
120       "5c91a7c2ad02abd66645802373db1d823bea80f08d452541fb2b62b5898bca572f8982a9"
121       "ca248a3056186322d93ca147266121ddeb5632c07f1f71cd27084ed3f2a25ec528543d9a"
122       "83c850d12b3036b518fafec080df3efcd9693b944d05605686200d6500f249475737ea92"
123       "46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad61c08a9fe416"
124       "29a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d7edd63be98fc"
125       "c7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f36cc45b0f7aa"
126       "c0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f5c27d01ad42119953c5987b05c"
127       "9ae2ca04b12838e641b4b1aac21e36f18573f603735fac1f8f611029e4cb76c8a5cc6f2c"
128       "4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000ae105483941652e",
129       &expected_token_encoding));
130   EXPECT_EQ(encoded_token, expected_token_encoding);
131 
132   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Token token2,
133                                    UnmarshalToken(encoded_token));
134   EXPECT_EQ(token.token_type, token2.token_type);
135   EXPECT_EQ(token.token_key_id, token2.token_key_id);
136   EXPECT_EQ(token.context, token2.context);
137   EXPECT_EQ(token.nonce, token2.nonce);
138   EXPECT_EQ(token.authenticator, token2.authenticator);
139 }
140 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnmarshalTooShort)141 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, UnmarshalTooShort) {
142   std::string short_token;
143   ASSERT_TRUE(absl::HexStringToBytes("DA7A5f5e466042", &short_token));
144   EXPECT_FALSE(UnmarshalToken(short_token).ok());
145 }
146 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnmarshalTooLong)147 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, UnmarshalTooLong) {
148   std::string long_token;
149   ASSERT_TRUE(absl::HexStringToBytes(
150       "DA7A5f5e46604255ac6a8ae0820f5b20c236118d97d917509ccbc96b5a82ae40ebeb11e1"
151       "5c91a7c2ad02abd66645802373db1d823bea80f08d452541fb2b62b5898bca572f8982a9"
152       "ca248a3056186322d93ca147266121ddeb5632c07f1f71cd27084ed3f2a25ec528543d9a"
153       "83c850d12b3036b518fafec080df3efcd9693b944d05605686200d6500f249475737ea92"
154       "46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad61c08a9fe416"
155       "29a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d7edd63be98fc"
156       "c7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f36cc45b0f7aa"
157       "c0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f5c27d01ad42119953c5987b05c"
158       "9ae2ca04b12838e641b4b1aac21e36f18573f603735fac1f8f611029e4cb76c8a5cc6f2c"
159       "4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000ae105483941652e9ae2ca04",
160       &long_token));
161   EXPECT_FALSE(UnmarshalToken(long_token).ok());
162 }
163 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnmarshalWrongType)164 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, UnmarshalWrongType) {
165   std::string token;
166   ASSERT_TRUE(absl::HexStringToBytes(
167       "DA7B5f5e46604255ac6a8ae0820f5b20c236118d97d917509ccbc96b5a82ae40ebeb11e1"
168       "5c91a7c2ad02abd66645802373db1d823bea80f08d452541fb2b62b5898bca572f8982a9"
169       "ca248a3056186322d93ca147266121ddeb5632c07f1f71cd27084ed3f2a25ec528543d9a"
170       "83c850d12b3036b518fafec080df3efcd9693b944d05605686200d6500f249475737ea92"
171       "46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad61c08a9fe416"
172       "29a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d7edd63be98fc"
173       "c7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f36cc45b0f7aa"
174       "c0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f5c27d01ad42119953c5987b05c"
175       "9ae2ca04b12838e641b4b1aac21e36f18573f603735fac1f8f611029e4cb76c8a5cc6f2c"
176       "4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000ae105483941652e",
177       &token));
178   EXPECT_FALSE(UnmarshalToken(token).ok());
179 }
180 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,EmptyExtensionTest)181 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, EmptyExtensionTest) {
182   Extension extension;
183   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_extension,
184                                    EncodeExtension(extension));
185 
186   std::string expected_extension_encoding;
187   ASSERT_TRUE(absl::HexStringToBytes("00010000", &expected_extension_encoding));
188   EXPECT_EQ(encoded_extension, expected_extension_encoding);
189 }
190 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ExtensionValueSizeOfMoreThanTwoBytes)191 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
192      ExtensionValueSizeOfMoreThanTwoBytes) {
193   // Input string of size more than 2 bytes.
194   std::string large_test_value = std::string(65536, 'a');
195   // Random hex number to populate the uint16_t extension_type.
196   Extension extension = {/*extension_type=*/0x5E6D,
197                          /*extension_value=*/large_test_value};
198   absl::StatusOr<std::string> encoded_extension = EncodeExtension(extension);
199 
200   EXPECT_EQ(encoded_extension.status().code(),
201             absl::StatusCode::kInvalidArgument);
202   EXPECT_THAT(encoded_extension.status().message(),
203               ::testing::HasSubstr("Failed to generate extension encoding"));
204 }
205 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ExtensionEncodingSuccess)206 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, ExtensionEncodingSuccess) {
207   std::string extension_value;
208   ASSERT_TRUE(absl::HexStringToBytes(
209       "46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad61c08a9fe416"
210       "29a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d7edd63be98fc"
211       "c7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f36cc45b0f7a"
212       "a",
213       &extension_value));
214   Extension extension = {
215       // Random hex number to populate the uint16_t extension_type.
216       /*extension_type=*/0x5E6D,
217       // Random hex string to populate extension_value.
218       std::move(extension_value)};
219   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_extension,
220                                    EncodeExtension(extension));
221   // The first 2 bytes of the expected_extension_encoding store the
222   // extension_type. The next two bytes store the number of bytes needed for the
223   // extension_value. These 4 bytes are then prefixed to the extension_value.
224   std::string expected_extension_encoding;
225   ASSERT_TRUE(absl::HexStringToBytes(
226       "5e6d006c46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad61c0"
227       "8a9fe41629a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d7edd"
228       "63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f36cc"
229       "45b0f7aa",
230       &expected_extension_encoding));
231   EXPECT_EQ(encoded_extension, expected_extension_encoding);
232 }
233 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,EmptyExtensionsTest)234 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, EmptyExtensionsTest) {
235   Extensions extensions;
236   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_extensions,
237                                    EncodeExtensions(extensions));
238 
239   std::string expected_extensions_encoding;
240   ASSERT_TRUE(absl::HexStringToBytes("0000", &expected_extensions_encoding));
241   EXPECT_EQ(encoded_extensions, expected_extensions_encoding);
242 }
243 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ExtensionsListSizeOfMoreThanTwoBytes)244 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
245      ExtensionsListSizeOfMoreThanTwoBytes) {
246   std::string large_test_value = std::string(65532, 'a');
247   Extensions extensions;
248   extensions.extensions.push_back(
249       {// Random hex number to populate the uint16_t extension_type.
250        /*extension_type=*/0x5E6D,
251        /*extension_value=*/large_test_value});
252   absl::StatusOr<std::string> encoded_extensions = EncodeExtensions(extensions);
253   // The string encoding of this extensions struct will take at least 65536
254   // bytes. This length is not be storable in 2 bytes.
255   EXPECT_EQ(encoded_extensions.status().code(),
256             absl::StatusCode::kInvalidArgument);
257   EXPECT_THAT(
258       encoded_extensions.status().message(),
259       ::testing::HasSubstr("Failed to generate encoded extensions list"));
260 }
261 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,SingleExtensionInExtensionsSuccess)262 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
263      SingleExtensionInExtensionsSuccess) {
264   std::string extension_value;
265   ASSERT_TRUE(absl::HexStringToBytes(
266       "46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad61c08a9fe416"
267       "29a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d7edd63be98fc"
268       "c7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f36cc45b0f7a"
269       "a",
270       &extension_value));
271   Extensions extensions;
272   extensions.extensions.push_back(Extension{
273       // Random hex number to populate the uint16_t extension_type.
274       /*extension_type=*/0x5E6D,
275       // Random hex string to populate extension_value.
276       std::move(extension_value)});
277   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_extensions,
278                                    EncodeExtensions(extensions));
279   // The first 2 bytes of the expected_extensions_encoding store the length of
280   // the rest of the string. The rest of the string is the concatenation
281   // of individually encoded extensions.
282   std::string expected_extensions_encoding;
283   ASSERT_TRUE(absl::HexStringToBytes(
284       "00705e6d006c46a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129b88c92ad"
285       "61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881f5e15668e0701d"
286       "7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d59402a87e08514f"
287       "36cc45b0f7aa",
288       &expected_extensions_encoding));
289   EXPECT_EQ(encoded_extensions, expected_extensions_encoding);
290 }
291 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,MultipleExtensionsEncodingSuccess)292 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
293      MultipleExtensionsEncodingSuccess) {
294   std::string extension_value_1;
295   ASSERT_TRUE(absl::HexStringToBytes("01", &extension_value_1));
296   std::string extension_value_2;
297   ASSERT_TRUE(absl::HexStringToBytes("0202", &extension_value_2));
298   Extensions extensions;
299   extensions.extensions.push_back(
300       Extension{/*extension_type=*/0x0001, std::move(extension_value_1)});
301   extensions.extensions.push_back(
302       Extension{/*extension_type=*/0x0002, std::move(extension_value_2)});
303   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions,
304                                    EncodeExtensions(extensions));
305   // The first 2 bytes of the expected_extensions_encoding store the length of
306   // the rest of the string. The rest of the string is the concatenation
307   // of individually encoded extensions.
308   std::string expected_extensions_encoding;
309   ASSERT_TRUE(absl::HexStringToBytes("000b0001000101000200020202",
310                                      &expected_extensions_encoding));
311   EXPECT_EQ(encoded_extensions, expected_extensions_encoding);
312   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extensions extensions2,
313                                    DecodeExtensions(encoded_extensions));
314   EXPECT_EQ(extensions2.extensions.size(), extensions.extensions.size());
315   for (size_t i = 0; i < extensions.extensions.size(); ++i) {
316     EXPECT_EQ(extensions2.extensions[i].extension_type,
317               extensions.extensions[i].extension_type);
318     EXPECT_EQ(extensions2.extensions[i].extension_value,
319               extensions.extensions[i].extension_value);
320   }
321 }
322 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ExpirationTimestampRoundTrip)323 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
324      ExpirationTimestampRoundTrip) {
325   ExpirationTimestamp et{.timestamp_precision = 3600, .timestamp = 1688583600};
326   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, et.AsExtension());
327   EXPECT_EQ(ext.extension_type, 0x0001);
328   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const ExpirationTimestamp et2,
329                                    ExpirationTimestamp::FromExtension(ext));
330   EXPECT_EQ(et.timestamp_precision, et2.timestamp_precision);
331   EXPECT_EQ(et.timestamp, et2.timestamp);
332 }
333 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ExpirationTimestampWrongType)334 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
335      ExpirationTimestampWrongType) {
336   const Extension ext = {.extension_type = 0x0002, .extension_value = ""};
337   EXPECT_FALSE(ExpirationTimestamp::FromExtension(ext).ok());
338 }
339 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,DecodeExtensions)340 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, DecodeExtensions) {
341   std::string encoded_extensions;
342   ASSERT_TRUE(absl::HexStringToBytes(
343       "0014000100100000000000000E100000000064A5BDB0", &encoded_extensions));
344   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extensions extensions,
345                                    DecodeExtensions(encoded_extensions));
346   EXPECT_EQ(extensions.extensions.size(), 1u);
347   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
348       const ExpirationTimestamp et,
349       ExpirationTimestamp::FromExtension(extensions.extensions[0]));
350   EXPECT_EQ(et.timestamp_precision, 3600u);
351   EXPECT_EQ(et.timestamp, 1688583600u);
352   Extensions extensions2;
353   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext2, et.AsExtension());
354   extensions2.extensions.push_back(ext2);
355   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const std::string encoded_extensions2,
356                                    EncodeExtensions(extensions2));
357   EXPECT_EQ(absl::BytesToHexString(encoded_extensions2),
358             absl::BytesToHexString(encoded_extensions));
359 }
360 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,DecodeTooShort)361 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, DecodeTooShort) {
362   std::string encoded_extensions;
363   ASSERT_TRUE(absl::HexStringToBytes("00140001001000", &encoded_extensions));
364   const absl::StatusOr<Extensions> extensions =
365       DecodeExtensions(encoded_extensions);
366   EXPECT_FALSE(extensions.ok()) << extensions.status();
367 }
368 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,DecodeTooLong)369 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, DecodeTooLong) {
370   std::string encoded_extensions;
371   ASSERT_TRUE(absl::HexStringToBytes(
372       "0014000100100000000000000E100000000064A5BDB0123456",
373       &encoded_extensions));
374   const absl::StatusOr<Extensions> extensions =
375       DecodeExtensions(encoded_extensions);
376   EXPECT_FALSE(extensions.ok());
377 }
378 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,GeoHintRoundTrip)379 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, GeoHintRoundTrip) {
380   GeoHint gh{.geo_hint = "US,US-AL,ALABASTER"};
381   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, gh.AsExtension());
382   EXPECT_EQ(ext.extension_type, 0x0002);
383   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const GeoHint gh2,
384                                    GeoHint::FromExtension(ext));
385   EXPECT_EQ(gh.geo_hint, gh2.geo_hint);
386   EXPECT_EQ(gh2.country_code, "US");
387   EXPECT_EQ(gh2.region, "US-AL");
388   EXPECT_EQ(gh2.city, "ALABASTER");
389 }
390 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,GeoHintNoPostal)391 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, GeoHintNoPostal) {
392   GeoHint gh{.geo_hint = "US,US-AL,ALABASTER,FOO"};
393   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, gh.AsExtension());
394   EXPECT_FALSE(GeoHint::FromExtension(ext).ok());
395 }
396 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,GeoHintNoLowercase)397 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, GeoHintNoLowercase) {
398   GeoHint gh{.geo_hint = "US,US-AL,Alabaster"};
399   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, gh.AsExtension());
400   EXPECT_FALSE(GeoHint::FromExtension(ext).ok());
401 }
402 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,GeoHintTooShort)403 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, GeoHintTooShort) {
404   GeoHint gh{.geo_hint = "US,US-AL"};
405   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, gh.AsExtension());
406   EXPECT_FALSE(GeoHint::FromExtension(ext).ok());
407 }
408 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,GeoHintEmptyOk)409 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, GeoHintEmptyOk) {
410   GeoHint gh{.geo_hint = "US,,"};
411   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, gh.AsExtension());
412   EXPECT_TRUE(GeoHint::FromExtension(ext).ok());
413 }
414 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ServiceTypeRoundTrip)415 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, ServiceTypeRoundTrip) {
416   ServiceType st{.service_type_id = 0x01};
417   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, st.AsExtension());
418   EXPECT_EQ(ext.extension_type, 0xF001);
419   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const ServiceType st2,
420                                    ServiceType::FromExtension(ext));
421   EXPECT_EQ(st.service_type_id, st2.service_type_id);
422   EXPECT_EQ(st2.service_type, "chromeipblinding");
423 }
424 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,WrongExtId)425 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, WrongExtId) {
426   ServiceType st{.service_type_id = 0x01};
427   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, st.AsExtension());
428   ext.extension_type = 0xF002;
429   EXPECT_FALSE(ServiceType::FromExtension(ext).ok());
430 }
431 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,WrongServiceTypeId)432 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, WrongServiceTypeId) {
433   ServiceType st{.service_type_id = 0x02};
434   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, st.AsExtension());
435   EXPECT_EQ(ext.extension_type, 0xF001);
436   EXPECT_FALSE(ServiceType::FromExtension(ext).ok());
437 }
438 
TEST(AnonymousTokensDebugMode,RoundTrip)439 TEST(AnonymousTokensDebugMode, RoundTrip) {
440   DebugMode dm{.mode = DebugMode::kProd};
441   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, dm.AsExtension());
442   EXPECT_EQ(ext.extension_type, 0xF002);
443   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const DebugMode dm2,
444                                    DebugMode::FromExtension(ext));
445   EXPECT_EQ(dm.mode, dm2.mode);
446 }
447 
TEST(AnonymousTokensDebugMode,WrongExtId)448 TEST(AnonymousTokensDebugMode, WrongExtId) {
449   DebugMode dm{.mode = DebugMode::kProd};
450   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, dm.AsExtension());
451   ext.extension_type = 0xF003;
452   EXPECT_FALSE(ServiceType::FromExtension(ext).ok());
453 }
454 
TEST(AnonymousTokensDebugMode,InvalidMode)455 TEST(AnonymousTokensDebugMode, InvalidMode) {
456   DebugMode dm{.mode = DebugMode::kProd};
457   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, dm.AsExtension());
458   EXPECT_EQ(ext.extension_type, 0xF002);
459   ext.extension_value = std::string("~");
460   EXPECT_FALSE(DebugMode::FromExtension(ext).ok());
461 }
462 
TEST(AnonymousTokensProxyLayer,RoundTripProxyA)463 TEST(AnonymousTokensProxyLayer, RoundTripProxyA) {
464   ProxyLayer pl{.layer = ProxyLayer::kProxyA};
465   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, pl.AsExtension());
466   EXPECT_EQ(ext.extension_type, 0xF003);
467   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const ProxyLayer pl2,
468                                    ProxyLayer::FromExtension(ext));
469   EXPECT_EQ(pl.layer, pl2.layer);
470 }
471 
TEST(AnonymousTokensProxyLayer,RoundTripProxyB)472 TEST(AnonymousTokensProxyLayer, RoundTripProxyB) {
473   ProxyLayer pl{.layer = ProxyLayer::kProxyB};
474   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const Extension ext, pl.AsExtension());
475   EXPECT_EQ(ext.extension_type, 0xF003);
476   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(const ProxyLayer pl2,
477                                    ProxyLayer::FromExtension(ext));
478   EXPECT_EQ(pl.layer, pl2.layer);
479 }
480 
TEST(AnonymousTokensProxyLayer,WrongExtId)481 TEST(AnonymousTokensProxyLayer, WrongExtId) {
482   ProxyLayer pl{.layer = ProxyLayer::kProxyA};
483   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, pl.AsExtension());
484   ext.extension_type = 0xF004;
485   EXPECT_FALSE(ProxyLayer::FromExtension(ext).ok());
486 }
487 
TEST(AnonymousTokensProxyLayer,InvalidLayer)488 TEST(AnonymousTokensProxyLayer, InvalidLayer) {
489   ProxyLayer pl{.layer = ProxyLayer::kProxyA};
490   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, pl.AsExtension());
491   EXPECT_EQ(ext.extension_type, 0xF003);
492   ext.extension_value = std::string("~");
493   EXPECT_FALSE(ProxyLayer::FromExtension(ext).ok());
494 }
495 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,EmptyMarshalTokenChallengeTest)496 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
497      EmptyMarshalTokenChallengeTest) {
498   TokenChallenge token_challenge;
499   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_token,
500                                    MarshalTokenChallenge(token_challenge));
501 
502   std::string expected_token_encoding;
503   ASSERT_TRUE(absl::HexStringToBytes("DA7A0000", &expected_token_encoding));
504 
505   EXPECT_EQ(encoded_token, expected_token_encoding);
506 }
507 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,MarshalTokenChallengeTest)508 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest, MarshalTokenChallengeTest) {
509   TokenChallenge token_challenge;
510   token_challenge.issuer_name = "issuer.google.com";
511   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_token,
512                                    MarshalTokenChallenge(token_challenge));
513 
514   std::string expected_token_encoding;
515   ASSERT_TRUE(absl::HexStringToBytes(
516       "da7a00116973737565722e676f6f676c652e636f6d", &expected_token_encoding));
517 
518   EXPECT_EQ(encoded_token, expected_token_encoding);
519 }
520 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnMarshalTokenRequestWrongTokenType)521 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
522      UnMarshalTokenRequestWrongTokenType) {
523   std::string token_request_encoding;
524   ASSERT_TRUE(absl::HexStringToBytes(
525       "1234124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
526       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
527       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
528       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
529       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
530       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
531       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
532       "e105483941652e",
533       &token_request_encoding));
534   absl::StatusOr<TokenRequest> token_request =
535       UnmarshalTokenRequest(token_request_encoding);
536 
537   EXPECT_EQ(token_request.status().code(), absl::StatusCode::kInvalidArgument);
538   EXPECT_THAT(token_request.status().message(),
539               ::testing::HasSubstr("unsupported token type"));
540 }
541 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnMarshalTokenRequestBlindedRequestTooShort)542 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
543      UnMarshalTokenRequestBlindedRequestTooShort) {
544   std::string token_request_encoding;
545   ASSERT_TRUE(absl::HexStringToBytes(
546       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
547       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
548       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
549       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
550       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
551       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
552       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000"
553       "a",
554       &token_request_encoding));
555   absl::StatusOr<TokenRequest> token_request =
556       UnmarshalTokenRequest(token_request_encoding);
557 
558   EXPECT_EQ(token_request.status().code(), absl::StatusCode::kInvalidArgument);
559   EXPECT_THAT(token_request.status().message(),
560               ::testing::HasSubstr("failed to read blinded_token_request"));
561 }
562 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnMarshalTokenRequestBlindedRequestTooLong)563 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
564      UnMarshalTokenRequestBlindedRequestTooLong) {
565   std::string token_request_encoding;
566   ASSERT_TRUE(absl::HexStringToBytes(
567       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
568       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
569       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
570       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
571       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
572       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
573       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
574       "e105483941652ea5cc6f2c4143474e458c8d2ca8e9aa",
575       &token_request_encoding));
576   absl::StatusOr<TokenRequest> token_request =
577       UnmarshalTokenRequest(token_request_encoding);
578 
579   EXPECT_EQ(token_request.status().code(), absl::StatusCode::kInvalidArgument);
580   EXPECT_THAT(token_request.status().message(),
581               ::testing::HasSubstr("token request had extra bytes"));
582 }
583 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,MarshalAndUnmarshalTokenRequest)584 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
585      MarshalAndUnmarshalTokenRequest) {
586   std::string blinded_token_request;
587   ASSERT_TRUE(absl::HexStringToBytes(
588       "4ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560568620"
589       "0d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129"
590       "b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881f5e156"
591       "68e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d59402a8"
592       "7e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f5c27d0"
593       "1ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac1f8f61"
594       "1029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000ae10548"
595       "3941652e",
596       &blinded_token_request));
597   TokenRequest token_request{
598       .token_type = 0xDA7A,
599       .truncated_token_key_id = 0x12,
600       .blinded_token_request = std::move(blinded_token_request)};
601   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(std::string encoded_token_request,
602                                    MarshalTokenRequest(token_request));
603 
604   std::string expected_token_request_encoding;
605   ASSERT_TRUE(absl::HexStringToBytes(
606       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
607       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
608       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
609       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
610       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
611       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
612       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
613       "e105483941652e",
614       &expected_token_request_encoding));
615 
616   EXPECT_EQ(encoded_token_request, expected_token_request_encoding);
617 
618   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
619       TokenRequest decoded_token_request,
620       UnmarshalTokenRequest(encoded_token_request));
621 
622   EXPECT_EQ(decoded_token_request.token_type, token_request.token_type);
623   EXPECT_EQ(decoded_token_request.truncated_token_key_id,
624             token_request.truncated_token_key_id);
625   EXPECT_EQ(decoded_token_request.blinded_token_request,
626             token_request.blinded_token_request);
627 }
628 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnmarshalExtendedTokenRequestTooShort)629 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
630      UnmarshalExtendedTokenRequestTooShort) {
631   std::string extended_token_request_encoding_1;
632   ASSERT_TRUE(absl::HexStringToBytes(
633       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
634       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
635       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
636       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
637       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
638       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
639       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
640       "e10548394165",
641       &extended_token_request_encoding_1));
642   std::string extended_token_request_encoding_2;
643   ASSERT_TRUE(absl::HexStringToBytes(
644       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
645       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
646       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
647       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
648       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
649       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
650       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
651       "e105483941652e",
652       &extended_token_request_encoding_2));
653 
654   absl::StatusOr<ExtendedTokenRequest> decoded_extended_token_request_1 =
655       UnmarshalExtendedTokenRequest(extended_token_request_encoding_1);
656   absl::StatusOr<ExtendedTokenRequest> decoded_extended_token_request_2 =
657       UnmarshalExtendedTokenRequest(extended_token_request_encoding_2);
658 
659   EXPECT_EQ(decoded_extended_token_request_1.status().code(),
660             absl::StatusCode::kInvalidArgument);
661   EXPECT_THAT(decoded_extended_token_request_1.status().message(),
662               ::testing::HasSubstr("failed to read encoded_token_request"));
663   EXPECT_EQ(decoded_extended_token_request_2.status().code(),
664             absl::StatusCode::kInvalidArgument);
665   EXPECT_THAT(decoded_extended_token_request_2.status().message(),
666               ::testing::HasSubstr("failed to read extensions."));
667 }
668 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,UnmarshalExtendedTokenRequestTooLong)669 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
670      UnmarshalExtendedTokenRequestTooLong) {
671   std::string extended_token_request_encoding;
672   ASSERT_TRUE(absl::HexStringToBytes(
673       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
674       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
675       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
676       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
677       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
678       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
679       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
680       "e105483941652e000b0001000101000200020202DA",
681       &extended_token_request_encoding));
682 
683   absl::StatusOr<ExtendedTokenRequest> decoded_extended_token_request =
684       UnmarshalExtendedTokenRequest(extended_token_request_encoding);
685 
686   EXPECT_EQ(decoded_extended_token_request.status().code(),
687             absl::StatusCode::kInvalidArgument);
688   EXPECT_THAT(decoded_extended_token_request.status().message(),
689               ::testing::HasSubstr("no data after extensions is allowed"));
690 }
691 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,MarshalAndUnmarshalExtendedTokenRequest)692 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
693      MarshalAndUnmarshalExtendedTokenRequest) {
694   std::string blinded_token_request;
695   ASSERT_TRUE(absl::HexStringToBytes(
696       "4ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560568620"
697       "0d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bbae7129"
698       "b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881f5e156"
699       "68e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d59402a8"
700       "7e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f5c27d0"
701       "1ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac1f8f61"
702       "1029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000ae10548"
703       "3941652e",
704       &blinded_token_request));
705   TokenRequest token_request{
706       .token_type = 0xDA7A,
707       .truncated_token_key_id = 0x12,
708       .blinded_token_request = std::move(blinded_token_request)};
709   std::string extension_value_1;
710   ASSERT_TRUE(absl::HexStringToBytes("01", &extension_value_1));
711   std::string extension_value_2;
712   ASSERT_TRUE(absl::HexStringToBytes("0202", &extension_value_2));
713   Extensions extensions;
714   extensions.extensions.push_back(
715       Extension{/*extension_type=*/0x0001, std::move(extension_value_1)});
716   extensions.extensions.push_back(
717       Extension{/*extension_type=*/0x0002, std::move(extension_value_2)});
718   ExtendedTokenRequest extended_token_request{token_request, extensions};
719 
720   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
721       std::string encoded_extended_token_request,
722       MarshalExtendedTokenRequest(extended_token_request));
723 
724   std::string expected_extended_token_request_encoding;
725   ASSERT_TRUE(absl::HexStringToBytes(
726       "DA7A124ed3f2a25ec528543d9a83c850d12b3036b518fafec080df3efcd9693b944d0560"
727       "5686200d6500f249475737ea9246a70c3c2a1ff280663e46c792a8ae0d9a6877d1b427bb"
728       "ae7129b88c92ad61c08a9fe41629a642263e4857e428a706ba87659361fed38087c0e881"
729       "f5e15668e0701d7edd63be98fcc7415819d466c61341de03d7e2a24181d7b9321b0826d5"
730       "9402a87e08514f36cc45b0f7aac0e9a6578ddb0534c8ebe528c693b6efb54e76a5a8056f"
731       "5c27d01ad42119953c5987b05c9ae2ca04b12838e641b4b1aac21e36f18573f603735fac"
732       "1f8f611029e4cb76c8a5cc6f2c4143474e458c8d2ca8e9a71f01d90e0d2d784874ff000a"
733       "e105483941652e000b0001000101000200020202",
734       &expected_extended_token_request_encoding));
735 
736   EXPECT_EQ(encoded_extended_token_request,
737             expected_extended_token_request_encoding);
738 
739   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(
740       ExtendedTokenRequest decoded_extended_token_request,
741       UnmarshalExtendedTokenRequest(encoded_extended_token_request));
742 
743   EXPECT_EQ(decoded_extended_token_request.request.token_type,
744             token_request.token_type);
745   EXPECT_EQ(decoded_extended_token_request.request.truncated_token_key_id,
746             token_request.truncated_token_key_id);
747   EXPECT_EQ(decoded_extended_token_request.request.blinded_token_request,
748             token_request.blinded_token_request);
749   EXPECT_EQ(decoded_extended_token_request.extensions.extensions.size(),
750             extensions.extensions.size());
751   for (size_t i = 0; i < extensions.extensions.size(); ++i) {
752     EXPECT_EQ(
753         decoded_extended_token_request.extensions.extensions[i].extension_type,
754         extensions.extensions[i].extension_type);
755     EXPECT_EQ(
756         decoded_extended_token_request.extensions.extensions[i].extension_value,
757         extensions.extensions[i].extension_value);
758   }
759 }
760 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ValidateExtensionsValuesTest)761 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
762      ValidateExtensionsValuesTest) {
763   Extensions extensions;
764   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
765 
766   ExpirationTimestamp et;
767   absl::Time one_day_away = absl::Now() + absl::Hours(24);
768   et.timestamp = absl::ToUnixSeconds(one_day_away);
769   et.timestamp -= et.timestamp % 900;
770   et.timestamp_precision = 900;
771   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, et.AsExtension());
772   extensions.extensions.push_back(ext);
773   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
774 
775   GeoHint gh;
776   gh.geo_hint = "US,US-AL,ALABASTER";
777   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(ext, gh.AsExtension());
778   extensions.extensions.push_back(ext);
779   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
780 
781   ServiceType svc;
782   svc.service_type_id = ServiceType::kChromeIpBlinding;
783   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(ext, svc.AsExtension());
784   extensions.extensions.push_back(ext);
785   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
786 
787   DebugMode debug;
788   debug.mode = DebugMode::kDebug;
789   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(ext, debug.AsExtension());
790   extensions.extensions.push_back(ext);
791   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
792 
793   ProxyLayer proxy_layer;
794   proxy_layer.layer = ProxyLayer::kProxyA;
795   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(ext, proxy_layer.AsExtension());
796   extensions.extensions.push_back(ext);
797   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
798 }
799 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,NotRoundedExpirationExtensionValidationTest)800 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
801      NotRoundedExpirationExtensionValidationTest) {
802   Extensions extensions;
803   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
804 
805   ExpirationTimestamp et;
806   absl::Time one_day_away = absl::Now() + absl::Hours(24);
807   et.timestamp = absl::ToUnixSeconds(one_day_away);
808   et.timestamp -= et.timestamp % 900;
809   et.timestamp += 17;
810   et.timestamp_precision = 900;
811   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, et.AsExtension());
812   extensions.extensions.push_back(ext);
813   EXPECT_EQ(ValidateExtensionsValues(extensions, absl::Now()).code(),
814             absl::StatusCode::kInvalidArgument);
815 }
816 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,BadPrecisionExpirationExtensionValidationTest)817 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
818      BadPrecisionExpirationExtensionValidationTest) {
819   Extensions extensions;
820   EXPECT_TRUE(ValidateExtensionsValues(extensions, absl::Now()).ok());
821 
822   ExpirationTimestamp et;
823   absl::Time one_day_away = absl::Now() + absl::Hours(24);
824   et.timestamp = absl::ToUnixSeconds(one_day_away);
825   et.timestamp -= et.timestamp % 2;
826   et.timestamp_precision = 2;
827   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, et.AsExtension());
828   extensions.extensions.push_back(ext);
829   EXPECT_EQ(ValidateExtensionsValues(extensions, absl::Now()).code(),
830             absl::StatusCode::kInvalidArgument);
831 }
832 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,MissingCountryGeoHintExtensionValidationTest)833 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
834      MissingCountryGeoHintExtensionValidationTest) {
835   Extensions extensions;
836   GeoHint gh;
837   gh.geo_hint = "US-AL,ALABASTER";
838   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, gh.AsExtension());
839   extensions.extensions.push_back(ext);
840   EXPECT_EQ(ValidateExtensionsValues(extensions, absl::Now()).code(),
841             absl::StatusCode::kInvalidArgument);
842 }
843 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,CountryLowercaseGeoHintExtensionValidationTest)844 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
845      CountryLowercaseGeoHintExtensionValidationTest) {
846   Extensions extensions;
847   GeoHint gh;
848   gh.geo_hint = "us,US-AL,ALABASTER";
849   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, gh.AsExtension());
850   extensions.extensions.push_back(ext);
851   EXPECT_EQ(ValidateExtensionsValues(extensions, absl::Now()).code(),
852             absl::StatusCode::kInvalidArgument);
853 }
854 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,NotCountryCodeGeoHintExtensionValidationTest)855 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
856      NotCountryCodeGeoHintExtensionValidationTest) {
857   Extensions extensions;
858   GeoHint gh;
859   gh.geo_hint = "USA,US-AL,ALABASTER";
860   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, gh.AsExtension());
861   extensions.extensions.push_back(ext);
862   EXPECT_EQ(ValidateExtensionsValues(extensions, absl::Now()).code(),
863             absl::StatusCode::kInvalidArgument);
864 }
865 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,RegionLowercaseGeoHintExtensionValidationTest)866 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
867      RegionLowercaseGeoHintExtensionValidationTest) {
868   Extensions extensions;
869   GeoHint gh;
870   gh.geo_hint = "US,US-al,ALABASTER";
871   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, gh.AsExtension());
872   extensions.extensions.push_back(ext);
873   EXPECT_EQ(ValidateExtensionsValues(extensions, absl::Now()).code(),
874             absl::StatusCode::kInvalidArgument);
875 }
876 
TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,ValidateExtensionsOrderAndValuesTest)877 TEST(AnonymousTokensPrivacyPassTokenEncodingsTest,
878      ValidateExtensionsOrderAndValuesTest) {
879   Extensions extensions;
880   std::vector<uint16_t> expected_types;
881   EXPECT_TRUE(ValidateExtensionsOrderAndValues(
882                   extensions, absl::MakeSpan(expected_types), absl::Now())
883                   .ok());
884 
885   ExpirationTimestamp et;
886   absl::Time one_day_away = absl::Now() + absl::Hours(24);
887   et.timestamp = absl::ToUnixSeconds(one_day_away);
888   et.timestamp -= et.timestamp % 900;
889   et.timestamp_precision = 900;
890   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(Extension ext, et.AsExtension());
891   extensions.extensions.push_back(ext);
892   expected_types.push_back(0x0001);
893   EXPECT_TRUE(ValidateExtensionsOrderAndValues(
894                   extensions, absl::MakeSpan(expected_types), absl::Now())
895                   .ok());
896 
897   expected_types.push_back(0x0002);
898   EXPECT_FALSE(ValidateExtensionsOrderAndValues(
899                    extensions, absl::MakeSpan(expected_types), absl::Now())
900                    .ok());
901 
902   GeoHint gh;
903   gh.geo_hint = "US,US-AL,ALABASTER";
904   ANON_TOKENS_ASSERT_OK_AND_ASSIGN(ext, gh.AsExtension());
905   extensions.extensions.push_back(ext);
906   EXPECT_TRUE(ValidateExtensionsOrderAndValues(
907                   extensions, absl::MakeSpan(expected_types), absl::Now())
908                   .ok());
909 
910   expected_types.clear();
911   EXPECT_FALSE(ValidateExtensionsOrderAndValues(
912                    extensions, absl::MakeSpan(expected_types), absl::Now())
913                    .ok());
914 
915   expected_types.push_back(0x0002);
916   expected_types.push_back(0x0001);
917   EXPECT_FALSE(ValidateExtensionsOrderAndValues(
918                    extensions, absl::MakeSpan(expected_types), absl::Now())
919                    .ok());
920 }
921 
922 }  // namespace
923 }  // namespace anonymous_tokens
924