![electron-roller[bot]](/assets/img/avatar_default.png)
* chore: bump chromium in DEPS to 133.0.6858.0 * chore: bump chromium in DEPS to 133.0.6860.0 * chore: update patches v8/revert_fastapi_remove_dynamic_overload_resolution.patch had some additions due to https://chromium-review.googlesource.com/c/v8/v8/+/6023139 * 6044060: Reland "Moves shared GN templates into //build/config/apple." https://chromium-review.googlesource.com/c/chromium/src/+/6044060 * Revert "6023139: [fastapi] Add support for attribute setters" https://chromium-review.googlesource.com/c/v8/v8/+/6023139 * Update printing.patch The removed include is present in the original source file now, just slightly before where it was being added. 6015430: Reduce platform-like buildflags in sandbox code Refs: https://chromium-review.googlesource.com/c/chromium/src/+/6015430 * 6039836: Migrate Command::IsMediaKey to be a member of ui::Accelerator https://chromium-review.googlesource.com/c/chromium/src/+/6039836 * 6038659: [CodeHealth] Clean up the feature ZstdContentEncoding https://chromium-review.googlesource.com/c/chromium/src/+/6038659 * chore: bump chromium in DEPS to 133.0.6862.0 * chore: update patches * 72747: crypto: switch to C++ https://boringssl-review.googlesource.com/c/boringssl/+/72747 * fixup! 72747: crypto: switch to C++ https://boringssl-review.googlesource.com/c/boringssl/+/72747 * chore: gen libc++ filenames * 6042601: [shared storage] Implement with_lock option for methods from response headers https://chromium-review.googlesource.com/c/chromium/src/+/6042601 * chore: bump chromium in DEPS to 133.0.6864.0 * chore: bump chromium in DEPS to 133.0.6866.0 * chore: bump chromium in DEPS to 133.0.6868.0 * chore: bump chromium in DEPS to 133.0.6870.0 * chore: bump chromium in DEPS to 133.0.6872.0 * chore: bump chromium in DEPS to 133.0.6874.0 * chore: bump chromium in DEPS to 133.0.6876.0 * 6039992: Fix false activation logic for context menu. | https://chromium-review.googlesource.com/c/chromium/src/+/6039992 * chore: update patches * chore: update patches * chore: bump chromium in DEPS to 133.0.6878.0 * chore: update patches * [Build] Organize //components/dbus into a single component Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6055280 * Merge //components/dbus/* into a single //components/dbus, which matches how most components are organized. This avoids having many small shared libraries which incurs unnecessary overhead. * Limit visibility of //components/dbus/* to //components/dbus * fixup! Update _LIBCPP_ABI_VERSION to always have a default value while keeping unstable false due to changes in llvm https://github.com/llvm/llvm-project/pull/112094 * 6040416: Let s know which widget the input came on. | https://chromium-review.googlesource.com/c/chromium/src/+/6040416 * 6056267: [MPArch guest view] Fix authentication for MPArch guests | https://chromium-review.googlesource.com/c/chromium/src/+/6056267 * make_span() is deprecated: https://issues.chromium.org/issues/341907909 * fixup: https://issues.chromium.org/issues/341907909 * chore: delete extra bracket from removing make_span commit * fixup: 6059305: Make WTF::UTF8ConversionMode a scoped enum | https://chromium-review.googlesource.com/c/chromium/src/+/6059305 * 6051058: CookieInclusionStatus: Remove ctors which bypass invariants | https://chromium-review.googlesource.com/c/chromium/src/+/6051058 * 6038981: Remove most remaining CHECK(false)s | https://chromium-review.googlesource.com/c/chromium/src/+/6038981 * build: use third_party/simdutf in Node.js * chore: node ./script/gen-libc++-filenames.js * chore: fix strict-cast conversion error in subspan() Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6044946 * chore: fix strict-cast conversion error in base::as_bytes() Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6044946 * chore: fix strict-cast conversion error in span.split_at() Xref: https://chromium-review.googlesource.com/c/chromium/src/+/6044946 * chore: use shorthand target name * chore: better docs in build_add_public_config_simdutf_config.patch --------- Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com> Co-authored-by: clavin <clavin@electronjs.org> Co-authored-by: alice <alice@makenotion.com> Co-authored-by: Charles Kerr <charles@charleskerr.com>
148 lines
4.7 KiB
C++
148 lines
4.7 KiB
C++
// Copyright (c) 2021 Slack Technologies, Inc.
|
|
// Use of this source code is governed by the MIT license that can be
|
|
// found in the LICENSE file.
|
|
|
|
#include "shell/browser/net/asar/asar_file_validator.h"
|
|
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <string>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
#include "base/containers/span.h"
|
|
#include "base/logging.h"
|
|
#include "base/notreached.h"
|
|
#include "base/strings/string_number_conversions.h"
|
|
#include "base/strings/string_util.h"
|
|
#include "crypto/sha2.h"
|
|
|
|
namespace asar {
|
|
|
|
AsarFileValidator::AsarFileValidator(IntegrityPayload integrity,
|
|
base::File file)
|
|
: file_(std::move(file)), integrity_(std::move(integrity)) {
|
|
current_block_ = 0;
|
|
max_block_ = integrity_.blocks.size() - 1;
|
|
}
|
|
|
|
AsarFileValidator::~AsarFileValidator() = default;
|
|
|
|
void AsarFileValidator::EnsureBlockHashExists() {
|
|
if (current_hash_)
|
|
return;
|
|
|
|
current_hash_byte_count_ = 0U;
|
|
switch (integrity_.algorithm) {
|
|
case HashAlgorithm::kSHA256:
|
|
current_hash_ = crypto::SecureHash::Create(crypto::SecureHash::SHA256);
|
|
break;
|
|
case HashAlgorithm::kNone:
|
|
NOTREACHED();
|
|
}
|
|
}
|
|
|
|
void AsarFileValidator::OnRead(base::span<char> buffer,
|
|
mojo::FileDataSource::ReadResult* result) {
|
|
DCHECK(!done_reading_);
|
|
|
|
const uint32_t block_size = integrity_.block_size;
|
|
|
|
// |buffer| contains the read buffer. |result->bytes_read| is the actual
|
|
// bytes number that |source| read that should be less than buffer.size().
|
|
auto hashme = base::as_bytes(
|
|
buffer.subspan(0U, static_cast<size_t>(result->bytes_read)));
|
|
|
|
while (!std::empty(hashme)) {
|
|
if (current_block_ > max_block_)
|
|
LOG(FATAL) << "Unexpected block count while validating ASAR file stream";
|
|
|
|
EnsureBlockHashExists();
|
|
|
|
// hash as many bytes as will fit in the current block.
|
|
const auto n_left_in_block = block_size - current_hash_byte_count_;
|
|
const auto n_now =
|
|
std::min(static_cast<size_t>(n_left_in_block), std::size(hashme));
|
|
DCHECK_GT(n_now, 0U);
|
|
const auto [hashme_now, hashme_next] = hashme.split_at(n_now);
|
|
|
|
current_hash_->Update(hashme_now);
|
|
current_hash_byte_count_ += n_now;
|
|
total_hash_byte_count_ += n_now;
|
|
|
|
if (current_hash_byte_count_ == block_size && !FinishBlock())
|
|
LOG(FATAL) << "Streaming ASAR file block hash failed: " << current_block_;
|
|
|
|
hashme = hashme_next;
|
|
}
|
|
}
|
|
|
|
bool AsarFileValidator::FinishBlock() {
|
|
if (current_hash_byte_count_ == 0) {
|
|
if (!done_reading_ || current_block_ > max_block_) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (!current_hash_) {
|
|
// This happens when we fail to read the resource. Compute empty content's
|
|
// hash in this case.
|
|
current_hash_ = crypto::SecureHash::Create(crypto::SecureHash::SHA256);
|
|
}
|
|
|
|
// If the file reader is done we need to make sure we've either read up to the
|
|
// end of the file (the check below) or up to the end of a block_size byte
|
|
// boundary. If the below check fails we compute the next block boundary, how
|
|
// many bytes are needed to get there and then we manually read those bytes
|
|
// from our own file handle ensuring the data producer is unaware but we can
|
|
// validate the hash still.
|
|
if (done_reading_ &&
|
|
total_hash_byte_count_ - extra_read_ != read_max_ - read_start_) {
|
|
uint64_t bytes_needed = std::min(
|
|
integrity_.block_size - current_hash_byte_count_,
|
|
read_max_ - read_start_ - total_hash_byte_count_ + extra_read_);
|
|
uint64_t offset = read_start_ + total_hash_byte_count_ - extra_read_;
|
|
std::vector<uint8_t> abandoned_buffer(bytes_needed);
|
|
if (!file_.ReadAndCheck(offset, abandoned_buffer)) {
|
|
LOG(FATAL) << "Failed to read required portion of streamed ASAR archive";
|
|
}
|
|
current_hash_->Update(abandoned_buffer);
|
|
}
|
|
|
|
auto actual = std::array<uint8_t, crypto::kSHA256Length>{};
|
|
current_hash_->Finish(actual);
|
|
current_hash_.reset();
|
|
current_hash_byte_count_ = 0;
|
|
|
|
const auto& expected_hash = integrity_.blocks[current_block_];
|
|
const auto actual_hex_hash = base::ToLowerASCII(base::HexEncode(actual));
|
|
if (expected_hash != actual_hex_hash)
|
|
return false;
|
|
|
|
current_block_++;
|
|
|
|
return true;
|
|
}
|
|
|
|
void AsarFileValidator::OnDone() {
|
|
DCHECK(!done_reading_);
|
|
done_reading_ = true;
|
|
if (!FinishBlock()) {
|
|
LOG(FATAL) << "Failed to validate block while ending ASAR file stream: "
|
|
<< current_block_;
|
|
}
|
|
}
|
|
|
|
void AsarFileValidator::SetRange(uint64_t read_start,
|
|
uint64_t extra_read,
|
|
uint64_t read_max) {
|
|
read_start_ = read_start;
|
|
extra_read_ = extra_read;
|
|
read_max_ = read_max;
|
|
}
|
|
|
|
void AsarFileValidator::SetCurrentBlock(int current_block) {
|
|
current_block_ = current_block;
|
|
}
|
|
|
|
} // namespace asar
|