1 // Copyright 2020 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "services/network/trust_tokens/trust_token_request_canonicalizer.h"
6
7 #include <memory>
8
9 #include "components/cbor/values.h"
10 #include "components/cbor/writer.h"
11 #include "net/url_request/url_request.h"
12 #include "services/network/public/mojom/trust_tokens.mojom-shared.h"
13 #include "services/network/trust_tokens/test/trust_token_test_util.h"
14 #include "services/network/trust_tokens/trust_token_http_headers.h"
15 #include "services/network/trust_tokens/trust_token_request_canonicalizer.h"
16 #include "services/network/trust_tokens/trust_token_request_signing_helper.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace network {
20
21 // Adopt the Trust Tokens fixture to create URLRequests without boilerplate
22 using TrustTokenRequestCanonicalizerTest = TrustTokenRequestHelperTest;
23
24 // Check that an empty request with an empty public key (and no headers to sign)
25 // serializes correctly. Expected CBOR maps:
26 //
27 // SignRequestData::kHeadersOnly:
28 // { "public_key": b"key" }
29 //
30 // SignRequestData::kInclude:
31 // { "url": "", "public_key": b"key" }
TEST_F(TrustTokenRequestCanonicalizerTest,Empty)32 TEST_F(TrustTokenRequestCanonicalizerTest, Empty) {
33 TrustTokenRequestCanonicalizer canonicalizer;
34
35 cbor::Value::MapValue expected_cbor;
36 expected_cbor[cbor::Value(
37 TrustTokenRequestSigningHelper::kCanonicalizedRequestDataPublicKeyKey)] =
38 cbor::Value("key", cbor::Value::Type::BYTE_STRING);
39
40 std::unique_ptr<net::URLRequest> request = MakeURLRequest("");
41 EXPECT_EQ(canonicalizer.Canonicalize(
42 request.get(), /*public_key=*/"key",
43 mojom::TrustTokenSignRequestData::kHeadersOnly),
44 cbor::Writer::Write(cbor::Value(expected_cbor)));
45
46 expected_cbor[cbor::Value(
47 TrustTokenRequestSigningHelper::kCanonicalizedRequestDataUrlKey)] =
48 cbor::Value("");
49 EXPECT_EQ(
50 canonicalizer.Canonicalize(request.get(), /*public_key=*/"key",
51 mojom::TrustTokenSignRequestData::kInclude),
52 cbor::Writer::Write(cbor::Value(expected_cbor)));
53 }
54
55 // Canonicalize a request with a nonempty public key and a nonempty URL.
56 //
57 // SignRequestData::kHeadersOnly:
58 // { "public_key": b"key" }
59 //
60 // SignRequestData::kInclude:
61 // { "url": "https://issuer.com/", "public_key": b"key" }
TEST_F(TrustTokenRequestCanonicalizerTest,Simple)62 TEST_F(TrustTokenRequestCanonicalizerTest, Simple) {
63 TrustTokenRequestCanonicalizer canonicalizer;
64
65 cbor::Value::MapValue expected_cbor;
66 expected_cbor[cbor::Value(
67 TrustTokenRequestSigningHelper::kCanonicalizedRequestDataPublicKeyKey)] =
68 cbor::Value("key", cbor::Value::Type::BYTE_STRING);
69
70 std::unique_ptr<net::URLRequest> request =
71 MakeURLRequest("https://issuer.com/");
72 EXPECT_EQ(canonicalizer.Canonicalize(
73 request.get(), /*public_key=*/"key",
74 mojom::TrustTokenSignRequestData::kHeadersOnly),
75 cbor::Writer::Write(cbor::Value(expected_cbor)));
76
77 expected_cbor[cbor::Value(
78 TrustTokenRequestSigningHelper::kCanonicalizedRequestDataUrlKey)] =
79 cbor::Value("https://issuer.com/");
80 EXPECT_EQ(
81 canonicalizer.Canonicalize(request.get(), /*public_key=*/"key",
82 mojom::TrustTokenSignRequestData::kInclude),
83 cbor::Writer::Write(cbor::Value(expected_cbor)));
84 }
85
86 // Canonicalize a request with a nonempty public key, some signed headers, and a
87 // nonempty URL.
88 //
89 // Expected CBOR maps:
90 //
91 // SignRequestData::kHeadersOnly:
92 // { "public_key": b"key", "first_header": "first_header_value",
93 // "second_header": "second_header_value" }
94 //
95 // SignRequestData::kInclude:
96 // { "url": "https://issuer.com/", "public_key": b"key",
97 // "first_header": "first_header_value", "second_header":
98 // "second_header_value" }
TEST_F(TrustTokenRequestCanonicalizerTest,WithSignedHeaders)99 TEST_F(TrustTokenRequestCanonicalizerTest, WithSignedHeaders) {
100 TrustTokenRequestCanonicalizer canonicalizer;
101
102 cbor::Value::MapValue expected_cbor;
103 expected_cbor[cbor::Value(
104 TrustTokenRequestSigningHelper::kCanonicalizedRequestDataPublicKeyKey)] =
105 cbor::Value("key", cbor::Value::Type::BYTE_STRING);
106
107 std::unique_ptr<net::URLRequest> request =
108 MakeURLRequest("https://issuer.com/");
109
110 // Capitalization should be normalized.
111 request->SetExtraRequestHeaderByName("First_HeadER", "first_header_value",
112 /*overwrite=*/true);
113
114 request->SetExtraRequestHeaderByName("second_header", "second_header_value",
115 /*overwrite=*/true);
116 request->SetExtraRequestHeaderByName(kTrustTokensRequestHeaderSignedHeaders,
117 " first_header , second_header ",
118 /*overwrite=*/true);
119
120 expected_cbor[cbor::Value("first_header")] =
121 cbor::Value("first_header_value");
122 expected_cbor[cbor::Value("second_header")] =
123 cbor::Value("second_header_value");
124
125 EXPECT_EQ(canonicalizer.Canonicalize(
126 request.get(), /*public_key=*/"key",
127 mojom::TrustTokenSignRequestData::kHeadersOnly),
128 cbor::Writer::Write(cbor::Value(expected_cbor)));
129
130 expected_cbor[cbor::Value(
131 TrustTokenRequestSigningHelper::kCanonicalizedRequestDataUrlKey)] =
132 cbor::Value("https://issuer.com/");
133 EXPECT_EQ(
134 canonicalizer.Canonicalize(request.get(), /*public_key=*/"key",
135 mojom::TrustTokenSignRequestData::kInclude),
136 cbor::Writer::Write(cbor::Value(expected_cbor)));
137 }
138
139 // Canonicalizing a request with a malformed Signed-Headers header should fail.
TEST_F(TrustTokenRequestCanonicalizerTest,RejectsMalformedSignedHeaders)140 TEST_F(TrustTokenRequestCanonicalizerTest, RejectsMalformedSignedHeaders) {
141 TrustTokenRequestCanonicalizer canonicalizer;
142
143 std::unique_ptr<net::URLRequest> request =
144 MakeURLRequest("https://issuer.com/");
145
146 // Set the Signed-Headers header to something that is *not* the serialization
147 // of a Structured Headers token. (Tokens can't start with quotes.)
148 request->SetExtraRequestHeaderByName(kTrustTokensRequestHeaderSignedHeaders,
149 "\"", /*overwrite=*/true);
150
151 EXPECT_FALSE(canonicalizer.Canonicalize(
152 request.get(), /*public_key=*/"key",
153 mojom::TrustTokenSignRequestData::kHeadersOnly));
154 }
155
156 // Canonicalizing a request with an empty key should fail.
TEST_F(TrustTokenRequestCanonicalizerTest,RejectsEmptyKey)157 TEST_F(TrustTokenRequestCanonicalizerTest, RejectsEmptyKey) {
158 TrustTokenRequestCanonicalizer canonicalizer;
159
160 std::unique_ptr<net::URLRequest> request =
161 MakeURLRequest("https://issuer.com/");
162
163 EXPECT_FALSE(canonicalizer.Canonicalize(
164 request.get(), /*public_key=*/"",
165 mojom::TrustTokenSignRequestData::kHeadersOnly));
166 }
167 } // namespace network
168