forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Trigger Attestation] Add attribution attestation mediator
AttributionAttestationMediator handles a single trigger attestation operation (https://github.com/WICG/attribution-reporting-api/blob/main/trigger_attestation.md): it generates a blinded unsigned message using an underlying cryptographic library, asks a token issuer to sign the blinded message, verifies and unblinds the blind token using the cryptographic library and then returns a token for redemption. The attribution request helper (https://chromium-review.googlesource.com/c/chromium/src/+/4097288) hooked in a url_loader will own a attribution mediator instance. The class can be viewed in context in this Trigger Attestation prototype CL: https://chromium-review.googlesource.com/c/chromium/src/+/4048207 Bug: 1396434 Change-Id: Ieb75bc6f476f1e858db17bb953f50edef7ce07c0 Change-Id: Ieb75bc6f476f1e858db17bb953f50edef7ce07c0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4089468 Reviewed-by: Charlie Harrison <csharrison@chromium.org> Reviewed-by: Kenichi Ishibashi <bashi@chromium.org> Commit-Queue: Anthony Garant <anthonygarant@chromium.org> Cr-Commit-Position: refs/heads/main@{#1091935}
- Loading branch information
Showing
11 changed files
with
820 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
# Copyright 2023 The Chromium Authors | ||
# Use of this source code is governed by a BSD-style license that can be | ||
# found in the LICENSE file. | ||
|
||
source_set("attribution") { | ||
visibility = [ | ||
":*", | ||
"//services/network:network_service", | ||
"//services/network:test_support", | ||
"//services/network:tests", | ||
] | ||
defines = [ "IS_NETWORK_SERVICE_IMPL" ] | ||
sources = [ | ||
"attribution_attestation_mediator.cc", | ||
"attribution_attestation_mediator.h", | ||
] | ||
deps = [ | ||
"//base", | ||
"//net", | ||
"//services/network/public/cpp", | ||
"//services/network/public/mojom", | ||
"//services/network/trust_tokens", | ||
"//url", | ||
] | ||
} | ||
|
||
source_set("tests") { | ||
testonly = true | ||
|
||
defines = [ "IS_NETWORK_SERVICE_IMPL" ] | ||
|
||
sources = [ | ||
"attribution_attestation_mediator_unittest.cc", | ||
"attribution_test_utils.cc", | ||
"attribution_test_utils.h", | ||
] | ||
|
||
deps = [ | ||
":attribution", | ||
"//base", | ||
"//base/test:test_support", | ||
"//services/network/public/mojom", | ||
"//services/network/trust_tokens", | ||
"//testing/gtest", | ||
"//url", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mixins: "//content/browser/attribution_reporting/COMMON_METADATA" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
anthonygarant@chromium.org | ||
csharrison@chromium.org | ||
|
||
file://content/browser/attribution_reporting/OWNERS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
# Attribution | ||
|
||
`//services/network/attribution` contains logic supporting the [Attribution | ||
Reporting API](https://github.com/WICG/attribution-reporting-api) in the network | ||
service. Specific use cases are detailed below. | ||
|
||
## Attribution Attestation | ||
|
||
The directory contains logic that orchestrates [Trigger | ||
Attestation](https://github.com/WICG/attribution-reporting-api/blob/main/trigger_attestation.md). | ||
Hooked in the url_loader when applicable, it adds and parse specific headers | ||
which allow reporting origins to submit a token attesting to the veracity of | ||
a trigger registration. |
175 changes: 175 additions & 0 deletions
175
services/network/attribution/attribution_attestation_mediator.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,175 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "services/network/attribution/attribution_attestation_mediator.h" | ||
|
||
#include <utility> | ||
|
||
#include "base/bind.h" | ||
#include "base/check.h" | ||
#include "base/task/thread_pool.h" | ||
#include "net/http/http_request_headers.h" | ||
#include "net/http/http_response_headers.h" | ||
#include "services/network/public/cpp/trust_token_http_headers.h" | ||
#include "services/network/trust_tokens/suitable_trust_token_origin.h" | ||
#include "services/network/trust_tokens/trust_token_key_commitment_getter.h" | ||
#include "services/network/trust_tokens/types.h" | ||
#include "url/origin.h" | ||
|
||
namespace network { | ||
|
||
using Cryptographer = AttributionAttestationMediator::Cryptographer; | ||
|
||
struct AttributionAttestationMediator::CryptographerAndBlindMessage { | ||
std::unique_ptr<Cryptographer> cryptographer; | ||
absl::optional<std::string> blind_message; | ||
}; | ||
|
||
struct AttributionAttestationMediator::CryptographerAndToken { | ||
std::unique_ptr<Cryptographer> cryptographer; | ||
absl::optional<std::string> token; | ||
}; | ||
|
||
AttributionAttestationMediator::AttributionAttestationMediator( | ||
const TrustTokenKeyCommitmentGetter* key_commitment_getter, | ||
std::unique_ptr<Cryptographer> cryptographer) | ||
: key_commitment_getter_(std::move(key_commitment_getter)), | ||
cryptographer_(std::move(cryptographer)) { | ||
DCHECK(key_commitment_getter_); | ||
DCHECK(cryptographer_); | ||
} | ||
|
||
AttributionAttestationMediator::~AttributionAttestationMediator() = default; | ||
|
||
void AttributionAttestationMediator::GetHeadersForAttestation( | ||
const GURL& url, | ||
const std::string& message, | ||
base::OnceCallback<void(net::HttpRequestHeaders)> done) { | ||
DCHECK(!message_); | ||
message_ = message; | ||
|
||
absl::optional<SuitableTrustTokenOrigin> issuer = | ||
SuitableTrustTokenOrigin::Create(url); | ||
if (!issuer.has_value()) { | ||
std::move(done).Run(net::HttpRequestHeaders()); | ||
return; | ||
} | ||
|
||
key_commitment_getter_->Get( | ||
issuer.value(), | ||
base::BindOnce(&AttributionAttestationMediator::OnGotKeyCommitment, | ||
weak_ptr_factory_.GetWeakPtr(), std::move(done))); | ||
} | ||
|
||
void AttributionAttestationMediator::OnGotKeyCommitment( | ||
base::OnceCallback<void(net::HttpRequestHeaders)> done, | ||
mojom::TrustTokenKeyCommitmentResultPtr commitment_result) { | ||
if (!commitment_result) { | ||
std::move(done).Run(net::HttpRequestHeaders()); | ||
return; | ||
} | ||
|
||
if (!cryptographer_->Initialize(commitment_result->protocol_version)) { | ||
std::move(done).Run(net::HttpRequestHeaders()); | ||
return; | ||
} | ||
|
||
for (const mojom::TrustTokenVerificationKeyPtr& key : | ||
commitment_result->keys) { | ||
if (!cryptographer_->AddKey(key->body)) { | ||
std::move(done).Run(net::HttpRequestHeaders()); | ||
return; | ||
} | ||
} | ||
|
||
base::ThreadPool::PostTaskAndReplyWithResult( | ||
FROM_HERE, | ||
base::BindOnce( | ||
[](std::unique_ptr<Cryptographer> cryptographer, | ||
std::string message) { | ||
absl::optional<std::string> blind_message = | ||
cryptographer->BeginIssuance(message); | ||
return AttributionAttestationMediator::CryptographerAndBlindMessage{ | ||
std::move(cryptographer), std::move(blind_message)}; | ||
}, | ||
std::move(cryptographer_), message_.value()), | ||
base::BindOnce(&AttributionAttestationMediator::OnDoneBeginIssuance, | ||
weak_ptr_factory_.GetWeakPtr(), | ||
commitment_result->protocol_version, std::move(done))); | ||
} | ||
|
||
void AttributionAttestationMediator::OnDoneBeginIssuance( | ||
mojom::TrustTokenProtocolVersion protocol_version, | ||
base::OnceCallback<void(net::HttpRequestHeaders)> done, | ||
AttributionAttestationMediator::CryptographerAndBlindMessage | ||
cryptographer_and_blind_message) { | ||
cryptographer_ = std::move(cryptographer_and_blind_message.cryptographer); | ||
|
||
if (!cryptographer_and_blind_message.blind_message.has_value()) { | ||
std::move(done).Run(net::HttpRequestHeaders()); | ||
return; | ||
} | ||
|
||
net::HttpRequestHeaders request_headers; | ||
request_headers.SetHeader( | ||
kTriggerAttestationHeader, | ||
std::move(cryptographer_and_blind_message.blind_message.value())); | ||
request_headers.SetHeader( | ||
kTrustTokensSecTrustTokenVersionHeader, | ||
internal::ProtocolVersionToString(protocol_version)); | ||
std::move(done).Run(std::move(request_headers)); | ||
} | ||
|
||
void AttributionAttestationMediator::ProcessAttestationToGetToken( | ||
net::HttpResponseHeaders& response_headers, | ||
base::OnceCallback<void(absl::optional<std::string>)> done) { | ||
DCHECK(message_.has_value()); | ||
|
||
std::string header_value; | ||
|
||
// EnumerateHeader(|iter|=nullptr) asks for the first instance of the header, | ||
// if any. At most one `kTriggerAttestationHeader` is expected as only one | ||
// token can attest to a trigger. Subsequent instances of the header are | ||
// ignored. | ||
if (!response_headers.EnumerateHeader( | ||
/*iter=*/nullptr, kTriggerAttestationHeader, &header_value)) { | ||
std::move(done).Run(absl::nullopt); | ||
return; | ||
} | ||
response_headers.RemoveHeader(kTriggerAttestationHeader); | ||
|
||
base::ThreadPool::PostTaskAndReplyWithResult( | ||
FROM_HERE, | ||
base::BindOnce( | ||
[](std::unique_ptr<Cryptographer> cryptographer, | ||
std::string blind_token) { | ||
absl::optional<std::string> token = | ||
cryptographer->ConfirmIssuanceAndBeginRedemption(blind_token); | ||
|
||
return AttributionAttestationMediator::CryptographerAndToken{ | ||
std::move(cryptographer), std::move(token)}; | ||
}, | ||
std::move(cryptographer_), std::move(header_value)), | ||
base::BindOnce( | ||
&AttributionAttestationMediator::OnDoneProcessingIssuanceResponse, | ||
weak_ptr_factory_.GetWeakPtr(), std::move(done))); | ||
} | ||
|
||
void AttributionAttestationMediator::OnDoneProcessingIssuanceResponse( | ||
base::OnceCallback<void(absl::optional<std::string>)> done, | ||
AttributionAttestationMediator::CryptographerAndToken | ||
cryptographer_and_token) { | ||
cryptographer_ = std::move(cryptographer_and_token.cryptographer); | ||
|
||
if (!cryptographer_and_token.token.has_value()) { | ||
// The response was rejected by the underlying cryptographic library as | ||
// malformed or otherwise invalid. | ||
std::move(done).Run(absl::nullopt); | ||
return; | ||
} | ||
|
||
std::move(done).Run(std::move(cryptographer_and_token.token.value())); | ||
} | ||
|
||
} // namespace network |
Oops, something went wrong.