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

Side by Side Diff: components/update_client/component_unpacker.cc

Issue 2874503002: Refactor CRX verification in preparation to support CRX₃ files. (Closed)
Patch Set: through #51 Created 3 years, 7 months 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 unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/update_client/component_unpacker.h" 5 #include "components/update_client/component_unpacker.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <string> 8 #include <string>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/base64.h"
12 #include "base/bind.h" 11 #include "base/bind.h"
13 #include "base/files/file_path.h" 12 #include "base/files/file_path.h"
14 #include "base/files/file_util.h" 13 #include "base/files/file_util.h"
15 #include "base/files/scoped_file.h" 14 #include "base/files/scoped_file.h"
16 #include "base/json/json_file_value_serializer.h" 15 #include "base/json/json_file_value_serializer.h"
17 #include "base/location.h" 16 #include "base/location.h"
18 #include "base/logging.h" 17 #include "base/logging.h"
19 #include "base/macros.h" 18 #include "base/macros.h"
20 #include "base/numerics/safe_conversions.h" 19 #include "base/numerics/safe_conversions.h"
21 #include "base/strings/string_number_conversions.h" 20 #include "base/strings/string_number_conversions.h"
22 #include "base/strings/stringprintf.h" 21 #include "base/strings/stringprintf.h"
23 #include "base/values.h" 22 #include "base/values.h"
24 #include "components/crx_file/crx_file.h" 23 #include "components/crx_file/crx_verifier.h"
25 #include "components/update_client/component_patcher.h" 24 #include "components/update_client/component_patcher.h"
26 #include "components/update_client/update_client.h" 25 #include "components/update_client/update_client.h"
27 #include "components/update_client/update_client_errors.h" 26 #include "components/update_client/update_client_errors.h"
28 #include "crypto/secure_hash.h"
29 #include "crypto/sha2.h"
30 #include "third_party/zlib/google/zip.h" 27 #include "third_party/zlib/google/zip.h"
31 28
32 using crypto::SecureHash;
33 using crx_file::CrxFile;
34
35 namespace update_client { 29 namespace update_client {
36 30
37 // TODO(cpu): add a specific attribute check to a component json that the 31 // TODO(cpu): add a specific attribute check to a component json that the
38 // extension unpacker will reject, so that a component cannot be installed 32 // extension unpacker will reject, so that a component cannot be installed
39 // as an extension. 33 // as an extension.
40 std::unique_ptr<base::DictionaryValue> ReadManifest( 34 std::unique_ptr<base::DictionaryValue> ReadManifest(
41 const base::FilePath& unpack_path) { 35 const base::FilePath& unpack_path) {
42 base::FilePath manifest = 36 base::FilePath manifest =
43 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); 37 unpack_path.Append(FILE_PATH_LITERAL("manifest.json"));
44 if (!base::PathExists(manifest)) 38 if (!base::PathExists(manifest))
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 if (!UnpackInternal()) 76 if (!UnpackInternal())
83 EndUnpacking(); 77 EndUnpacking();
84 } 78 }
85 79
86 bool ComponentUnpacker::Verify() { 80 bool ComponentUnpacker::Verify() {
87 VLOG(1) << "Verifying component: " << path_.value(); 81 VLOG(1) << "Verifying component: " << path_.value();
88 if (pk_hash_.empty() || path_.empty()) { 82 if (pk_hash_.empty() || path_.empty()) {
89 error_ = UnpackerError::kInvalidParams; 83 error_ = UnpackerError::kInvalidParams;
90 return false; 84 return false;
91 } 85 }
92 // First, validate the CRX header and signature. As of today 86 const std::vector<std::vector<uint8_t>> required_keys = {pk_hash_};
93 // this is SHA1 with RSA 1024. 87 const crx_file::VerifierResult result =
94 std::string public_key_bytes; 88 crx_file::Verify(path_, crx_file::VerifierFormat::CRX2_OR_CRX3,
95 std::string public_key_base64; 89 required_keys, std::vector<uint8_t>(), nullptr, nullptr);
96 CrxFile::Header header; 90 if (result != crx_file::VerifierResult::OK_FULL &&
97 CrxFile::ValidateError error = CrxFile::ValidateSignature( 91 result != crx_file::VerifierResult::OK_DELTA) {
98 path_, std::string(), &public_key_base64, nullptr, &header);
99 if (error != CrxFile::ValidateError::NONE ||
100 !base::Base64Decode(public_key_base64, &public_key_bytes)) {
101 error_ = UnpackerError::kInvalidFile; 92 error_ = UnpackerError::kInvalidFile;
102 return false; 93 return false;
103 } 94 }
104 is_delta_ = CrxFile::HeaderIsDelta(header); 95 is_delta_ = result == crx_file::VerifierResult::OK_DELTA;
105
106 // File is valid and the digital signature matches. Now make sure
107 // the public key hash matches the expected hash. If they do we fully
108 // trust this CRX.
109 uint8_t hash[crypto::kSHA256Length] = {};
110 std::unique_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
111 sha256->Update(public_key_bytes.data(), public_key_bytes.size());
112 sha256->Finish(hash, arraysize(hash));
113
114 if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) {
115 VLOG(1) << "Hash mismatch: " << path_.value();
116 error_ = UnpackerError::kInvalidId;
117 return false;
118 }
119 VLOG(1) << "Verification successful: " << path_.value(); 96 VLOG(1) << "Verification successful: " << path_.value();
120 return true; 97 return true;
121 } 98 }
122 99
123 bool ComponentUnpacker::Unzip() { 100 bool ComponentUnpacker::Unzip() {
124 // Mind the reference to non-const type, passed as an argument below. 101 // Mind the reference to non-const type, passed as an argument below.
125 base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_; 102 base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_;
126 if (!base::CreateNewTempDirectory(base::FilePath::StringType(), 103 if (!base::CreateNewTempDirectory(base::FilePath::StringType(),
127 &destination)) { 104 &destination)) {
128 VLOG(1) << "Unable to create temporary directory for unpacking."; 105 VLOG(1) << "Unable to create temporary directory for unpacking.";
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 Result result; 157 Result result;
181 result.error = error_; 158 result.error = error_;
182 result.extended_error = extended_error_; 159 result.extended_error = extended_error_;
183 if (error_ == UnpackerError::kNone) 160 if (error_ == UnpackerError::kNone)
184 result.unpack_path = unpack_path_; 161 result.unpack_path = unpack_path_;
185 162
186 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, result)); 163 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, result));
187 } 164 }
188 165
189 } // namespace update_client 166 } // namespace update_client
OLDNEW
« no previous file with comments | « components/crx_file/crx_verifier.cc ('k') | components/update_client/component_unpacker_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698