Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2215)

Unified Diff: chrome/browser/extensions/sandboxed_unpacker.cc

Issue 829583002: Validate hash_sha256 checksum on .crx update. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add histogram description. Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/sandboxed_unpacker.cc
diff --git a/chrome/browser/extensions/sandboxed_unpacker.cc b/chrome/browser/extensions/sandboxed_unpacker.cc
index b2c6a3b3a53e3aeae8465af79f609cb002d1385a..a4a079c8d57f64ca835dc1242594a65275c44381 100644
--- a/chrome/browser/extensions/sandboxed_unpacker.cc
+++ b/chrome/browser/extensions/sandboxed_unpacker.cc
@@ -18,6 +18,7 @@
#include "base/numerics/safe_conversions.h"
#include "base/path_service.h"
#include "base/sequenced_task_runner.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "chrome/browser/extensions/extension_service.h"
@@ -32,6 +33,8 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/utility_process_host.h"
#include "content/public/common/common_param_traits.h"
+#include "crypto/secure_hash.h"
+#include "crypto/sha2.h"
#include "crypto/signature_verifier.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension.h"
@@ -40,6 +43,7 @@
#include "extensions/common/file_util.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/manifest_handlers/icons_handler.h"
+#include "extensions/common/switches.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/codec/png_codec.h"
@@ -63,6 +67,10 @@ using crx_file::CrxFile;
#define UNPACK_RATE_HISTOGRAM(name, rate) \
UMA_HISTOGRAM_CUSTOM_COUNTS(name, rate, 1, 100000, 100);
+// Record if the .crx hash sum is the same as in the updater manifest.
+#define CRX_HASH_CHECK_HISTOGRAM(name, success) \
+ UMA_HISTOGRAM_BOOLEAN(name, success)
+
namespace extensions {
namespace {
@@ -216,18 +224,25 @@ bool ReadMessageCatalogsFromFile(const base::FilePath& extension_path,
SandboxedUnpacker::SandboxedUnpacker(
const base::FilePath& crx_path,
+ const std::string& package_hash,
Manifest::Location location,
int creation_flags,
const base::FilePath& extensions_dir,
const scoped_refptr<base::SequencedTaskRunner>& unpacker_io_task_runner,
SandboxedUnpackerClient* client)
: crx_path_(crx_path),
+ package_hash_(package_hash),
+ check_crx_hash_(false),
client_(client),
extensions_dir_(extensions_dir),
got_response_(false),
location_(location),
creation_flags_(creation_flags),
unpacker_io_task_runner_(unpacker_io_task_runner) {
+ if (!package_hash_.empty()) {
+ check_crx_hash_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
+ extensions::switches::kEnableCrxHashCheck);
+ }
}
bool SandboxedUnpacker::CreateTempDirectory() {
@@ -422,9 +437,27 @@ void SandboxedUnpacker::OnUnpackExtensionFailed(const base::string16& error) {
error));
}
+static size_t fread_sha256(void* ptr,
+ size_t size,
+ size_t nmemb,
+ FILE* stream,
+ scoped_ptr<crypto::SecureHash>& hash) {
+ size_t len = fread(ptr, size, nmemb, stream);
+ if (len > 0 && hash) {
+ hash->Update(ptr, len * size);
+ }
+ return len;
+}
+
bool SandboxedUnpacker::ValidateSignature() {
base::ScopedFILE file(base::OpenFile(crx_path_, "rb"));
+ scoped_ptr<crypto::SecureHash> hash;
+
+ if (!package_hash_.empty()) {
+ hash.reset(crypto::SecureHash::Create(crypto::SecureHash::SHA256));
+ }
+
if (!file.get()) {
// Could not open crx file for reading.
#if defined (OS_WIN)
@@ -458,7 +491,7 @@ bool SandboxedUnpacker::ValidateSignature() {
// code in the code base. So for now, this assumes that we're running
// on a little endian machine with 4 byte alignment.
CrxFile::Header header;
- size_t len = fread(&header, 1, sizeof(header), file.get());
+ size_t len = fread_sha256(&header, 1, sizeof(header), file.get(), hash);
if (len < sizeof(header)) {
// Invalid crx header
ReportFailure(
@@ -519,7 +552,8 @@ bool SandboxedUnpacker::ValidateSignature() {
std::vector<uint8> key;
key.resize(header.key_size);
- len = fread(&key.front(), sizeof(uint8), header.key_size, file.get());
+ len = fread_sha256(&key.front(), sizeof(uint8), header.key_size, file.get(),
+ hash);
if (len < header.key_size) {
// Invalid public key
ReportFailure(
@@ -532,8 +566,8 @@ bool SandboxedUnpacker::ValidateSignature() {
std::vector<uint8> signature;
signature.resize(header.signature_size);
- len = fread(&signature.front(), sizeof(uint8), header.signature_size,
- file.get());
+ len = fread_sha256(&signature.front(), sizeof(uint8), header.signature_size,
+ file.get(), hash);
if (len < header.signature_size) {
// Invalid signature
ReportFailure(
@@ -562,7 +596,7 @@ bool SandboxedUnpacker::ValidateSignature() {
}
unsigned char buf[1 << 12];
- while ((len = fread(buf, 1, sizeof(buf), file.get())) > 0)
+ while ((len = fread_sha256(buf, 1, sizeof(buf), file.get(), hash)) > 0)
verifier.VerifyUpdate(buf, len);
if (!verifier.VerifyFinal()) {
@@ -575,6 +609,26 @@ bool SandboxedUnpacker::ValidateSignature() {
return false;
}
+ if (hash) {
+ uint8 output3[crypto::kSHA256Length];
Dmitry Polukhin 2015/01/15 12:45:13 Why so strange name 'output3'?
+ hash->Finish(output3, sizeof(output3));
+ if (base::StringToLowerASCII(base::HexEncode(output3, sizeof(output3)))
+ != package_hash_) {
+ // Package hash verification failed
+ CRX_HASH_CHECK_HISTOGRAM("Extensions.SandboxUnpackHashCheck", false);
+ if (check_crx_hash_) {
Dmitry Polukhin 2015/01/15 12:45:13 I would also print error message to log.
+ ReportFailure(
+ CRX_HASH_VERIFICATION_FAILED,
+ l10n_util::GetStringFUTF16(
+ IDS_EXTENSION_PACKAGE_ERROR_CODE,
+ ASCIIToUTF16("CRX_HASH_VERIFICATION_FAILED")));
+ return false;
+ }
+ } else {
+ CRX_HASH_CHECK_HISTOGRAM("Extensions.SandboxUnpackHashCheck", true);
+ }
+ }
+
std::string public_key =
std::string(reinterpret_cast<char*>(&key.front()), key.size());
base::Base64Encode(public_key, &public_key_);

Powered by Google App Engine
This is Rietveld 408576698