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

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

Issue 2874503002: Refactor CRX verification in preparation to support CRX₃ files. (Closed)
Patch Set: No subclass 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/component_patcher_operation.h" 25 #include "components/update_client/component_patcher_operation.h"
27 #include "components/update_client/update_client.h" 26 #include "components/update_client/update_client.h"
28 #include "components/update_client/update_client_errors.h" 27 #include "components/update_client/update_client_errors.h"
29 #include "crypto/secure_hash.h"
30 #include "crypto/sha2.h"
31 #include "third_party/zlib/google/zip.h" 28 #include "third_party/zlib/google/zip.h"
32 29
33 using crypto::SecureHash; 30 using crx_file::CrxVerifier;
34 using crx_file::CrxFile;
35 31
36 namespace update_client { 32 namespace update_client {
37 33
38 // TODO(cpu): add a specific attribute check to a component json that the 34 // TODO(cpu): add a specific attribute check to a component json that the
39 // extension unpacker will reject, so that a component cannot be installed 35 // extension unpacker will reject, so that a component cannot be installed
40 // as an extension. 36 // as an extension.
41 std::unique_ptr<base::DictionaryValue> ReadManifest( 37 std::unique_ptr<base::DictionaryValue> ReadManifest(
42 const base::FilePath& unpack_path) { 38 const base::FilePath& unpack_path) {
43 base::FilePath manifest = 39 base::FilePath manifest =
44 unpack_path.Append(FILE_PATH_LITERAL("manifest.json")); 40 unpack_path.Append(FILE_PATH_LITERAL("manifest.json"));
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
83 if (!UnpackInternal()) 79 if (!UnpackInternal())
84 EndUnpacking(); 80 EndUnpacking();
85 } 81 }
86 82
87 bool ComponentUnpacker::Verify() { 83 bool ComponentUnpacker::Verify() {
88 VLOG(1) << "Verifying component: " << path_.value(); 84 VLOG(1) << "Verifying component: " << path_.value();
89 if (pk_hash_.empty() || path_.empty()) { 85 if (pk_hash_.empty() || path_.empty()) {
90 error_ = UnpackerError::kInvalidParams; 86 error_ = UnpackerError::kInvalidParams;
91 return false; 87 return false;
92 } 88 }
93 // First, validate the CRX header and signature. As of today 89 CrxVerifier verifier;
94 // this is SHA1 with RSA 1024. 90 verifier.RequireKeyProof(pk_hash_);
95 std::string public_key_bytes; 91 CrxVerifier::Result result = verifier.Verify(path_);
96 std::string public_key_base64; 92 if (result != CrxVerifier::Result::OK_FULL &&
97 CrxFile::Header header; 93 result != CrxVerifier::Result::OK_DELTA) {
98 CrxFile::ValidateError error = CrxFile::ValidateSignature(
99 path_, std::string(), &public_key_base64, nullptr, &header);
100 if (error != CrxFile::ValidateError::NONE ||
101 !base::Base64Decode(public_key_base64, &public_key_bytes)) {
102 error_ = UnpackerError::kInvalidFile; 94 error_ = UnpackerError::kInvalidFile;
103 return false; 95 return false;
104 } 96 }
105 is_delta_ = CrxFile::HeaderIsDelta(header); 97 is_delta_ = result == CrxVerifier::Result::OK_DELTA;
106
107 // File is valid and the digital signature matches. Now make sure
108 // the public key hash matches the expected hash. If they do we fully
109 // trust this CRX.
110 uint8_t hash[crypto::kSHA256Length] = {};
111 std::unique_ptr<SecureHash> sha256(SecureHash::Create(SecureHash::SHA256));
112 sha256->Update(public_key_bytes.data(), public_key_bytes.size());
113 sha256->Finish(hash, arraysize(hash));
114
115 if (!std::equal(pk_hash_.begin(), pk_hash_.end(), hash)) {
116 VLOG(1) << "Hash mismatch: " << path_.value();
117 error_ = UnpackerError::kInvalidId;
118 return false;
119 }
120 VLOG(1) << "Verification successful: " << path_.value(); 98 VLOG(1) << "Verification successful: " << path_.value();
121 return true; 99 return true;
122 } 100 }
123 101
124 bool ComponentUnpacker::Unzip() { 102 bool ComponentUnpacker::Unzip() {
125 // Mind the reference to non-const type, passed as an argument below. 103 // Mind the reference to non-const type, passed as an argument below.
126 base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_; 104 base::FilePath& destination = is_delta_ ? unpack_diff_path_ : unpack_path_;
127 if (!base::CreateNewTempDirectory(base::FilePath::StringType(), 105 if (!base::CreateNewTempDirectory(base::FilePath::StringType(),
128 &destination)) { 106 &destination)) {
129 VLOG(1) << "Unable to create temporary directory for unpacking."; 107 VLOG(1) << "Unable to create temporary directory for unpacking.";
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 Result result; 159 Result result;
182 result.error = error_; 160 result.error = error_;
183 result.extended_error = extended_error_; 161 result.extended_error = extended_error_;
184 if (error_ == UnpackerError::kNone) 162 if (error_ == UnpackerError::kNone)
185 result.unpack_path = unpack_path_; 163 result.unpack_path = unpack_path_;
186 164
187 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, result)); 165 task_runner_->PostTask(FROM_HERE, base::Bind(callback_, result));
188 } 166 }
189 167
190 } // namespace update_client 168 } // namespace update_client
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698