blob: 8f45dc93d90029192a9e3d1581aa912cd8c54a62 [file] [log] [blame]
// Copyright 2018 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 "content/browser/web_package/signed_exchange_prologue.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "content/browser/web_package/signed_exchange_utils.h"
namespace content {
namespace {
constexpr char kSignedExchangeMagic[] = "sxg1-b1";
constexpr size_t kMaximumSignatureHeaderFieldLength = 16 * 1024;
constexpr size_t kMaximumCBORHeaderLength = 512 * 1024;
} // namespace
constexpr size_t SignedExchangePrologue::kEncodedLengthInBytes;
size_t SignedExchangePrologue::kEncodedPrologueInBytes =
sizeof(kSignedExchangeMagic) +
SignedExchangePrologue::kEncodedLengthInBytes * 2;
// static
size_t SignedExchangePrologue::ParseEncodedLength(
base::span<const uint8_t> input) {
DCHECK_EQ(input.size(), SignedExchangePrologue::kEncodedLengthInBytes);
return static_cast<size_t>(input[0]) << 16 |
static_cast<size_t>(input[1]) << 8 | static_cast<size_t>(input[2]);
}
// static
base::Optional<SignedExchangePrologue> SignedExchangePrologue::Parse(
base::span<const uint8_t> input,
SignedExchangeDevToolsProxy* devtools_proxy) {
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("loading"),
"SignedExchangePrologue::Parse");
CHECK_EQ(input.size(), kEncodedPrologueInBytes);
const auto magic_string = input.subspan(0, sizeof(kSignedExchangeMagic));
const auto encoded_signature_header_field_length =
input.subspan(sizeof(kSignedExchangeMagic), kEncodedLengthInBytes);
const auto encoded_cbor_header_length =
input.subspan(sizeof(kSignedExchangeMagic) + kEncodedLengthInBytes,
kEncodedLengthInBytes);
if (memcmp(magic_string.data(), kSignedExchangeMagic,
sizeof(kSignedExchangeMagic)) != 0) {
signed_exchange_utils::ReportErrorAndTraceEvent(devtools_proxy,
"Wrong magic string");
return base::nullopt;
}
size_t signature_header_field_length =
ParseEncodedLength(encoded_signature_header_field_length);
size_t cbor_header_length = ParseEncodedLength(encoded_cbor_header_length);
if (signature_header_field_length > kMaximumSignatureHeaderFieldLength) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
base::StringPrintf("Signature header field too long: %zu",
signature_header_field_length));
return base::nullopt;
}
if (cbor_header_length > kMaximumCBORHeaderLength) {
signed_exchange_utils::ReportErrorAndTraceEvent(
devtools_proxy,
base::StringPrintf("CBOR header too long: %zu", cbor_header_length));
return base::nullopt;
}
return SignedExchangePrologue(signature_header_field_length,
cbor_header_length);
}
size_t SignedExchangePrologue::ComputeFollowingSectionsLength() const {
return signature_header_field_length_ + cbor_header_length_;
}
} // namespace content