| // 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 |