blob: 07403051e241d64f6df60ad8e90555520ed6a082 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h"
#include "base/base64.h"
#include "base/callback_helpers.h"
#include "net/http/structured_headers.h"
#include "services/network/trust_tokens/scoped_boringssl_bytes.h"
#include "services/network/trust_tokens/trust_token_client_data_canonicalization.h"
#include "services/network/trust_tokens/trust_token_parameterization.h"
#include "third_party/boringssl/src/include/openssl/base.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/boringssl/src/include/openssl/mem.h"
#include "third_party/boringssl/src/include/openssl/trust_token.h"
namespace network {
BoringsslTrustTokenRedemptionCryptographer::
BoringsslTrustTokenRedemptionCryptographer() = default;
BoringsslTrustTokenRedemptionCryptographer::
~BoringsslTrustTokenRedemptionCryptographer() = default;
bool BoringsslTrustTokenRedemptionCryptographer::Initialize(
mojom::TrustTokenProtocolVersion issuer_configured_version,
int issuer_configured_batch_size) {
if (!base::IsValueInRangeForNumericType<size_t>(issuer_configured_batch_size))
return false;
const TRUST_TOKEN_METHOD* method = nullptr;
switch (issuer_configured_version) {
case mojom::TrustTokenProtocolVersion::kTrustTokenV2Pmb:
method = TRUST_TOKEN_experiment_v2_pmb();
break;
case mojom::TrustTokenProtocolVersion::kTrustTokenV2Voprf:
method = TRUST_TOKEN_experiment_v2_voprf();
break;
}
ctx_ = bssl::UniquePtr<TRUST_TOKEN_CLIENT>(TRUST_TOKEN_CLIENT_new(
method, static_cast<size_t>(issuer_configured_batch_size)));
if (!ctx_)
return false;
return true;
}
base::Optional<std::string>
BoringsslTrustTokenRedemptionCryptographer::BeginRedemption(
TrustToken token,
base::StringPiece verification_key_to_bind,
const url::Origin& top_level_origin) {
if (!ctx_)
return base::nullopt;
// It's unclear if BoringSSL expects the exact same value in the client data
// and as the |time| argument to TRUST_TOKEN_CLIENT_begin_redemption; play
// it safe by using a single timestamp.
base::Time redemption_timestamp = base::Time::Now();
base::Optional<std::vector<uint8_t>> maybe_client_data =
CanonicalizeTrustTokenClientDataForRedemption(
redemption_timestamp, top_level_origin, verification_key_to_bind);
if (!maybe_client_data)
return base::nullopt;
ScopedBoringsslBytes raw_redemption_request;
bssl::UniquePtr<TRUST_TOKEN> boringssl_token(
TRUST_TOKEN_new(base::as_bytes(base::make_span(token.body())).data(),
token.body().size()));
if (!boringssl_token)
return base::nullopt;
if (!TRUST_TOKEN_CLIENT_begin_redemption(
ctx_.get(), raw_redemption_request.mutable_ptr(),
raw_redemption_request.mutable_len(), boringssl_token.get(),
maybe_client_data->data(), maybe_client_data->size(),
(redemption_timestamp - base::Time::UnixEpoch()).InSeconds())) {
return base::nullopt;
}
return base::Base64Encode(raw_redemption_request.as_span());
}
base::Optional<std::string>
BoringsslTrustTokenRedemptionCryptographer::ConfirmRedemption(
base::StringPiece response_header) {
if (!ctx_)
return base::nullopt;
std::string decoded_response;
if (!base::Base64Decode(response_header, &decoded_response))
return base::nullopt;
// In TrustTokenV2, the entire RR is stored in the body field, and the
// signature field is unused in finish_redemption.
ScopedBoringsslBytes rr;
ScopedBoringsslBytes unused;
if (!TRUST_TOKEN_CLIENT_finish_redemption(
ctx_.get(), rr.mutable_ptr(), rr.mutable_len(), unused.mutable_ptr(),
unused.mutable_len(),
base::as_bytes(base::make_span(decoded_response)).data(),
decoded_response.size())) {
return base::nullopt;
}
return std::string(reinterpret_cast<const char*>(rr.as_span().data()),
rr.as_span().size());
}
} // namespace network