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 3// found in the LICENSE file. 4 5#include "extensions/browser/content_hash_reader.h" 6 7#include "base/base64.h" 8#include "base/file_util.h" 9#include "base/json/json_reader.h" 10#include "base/strings/string_util.h" 11#include "base/values.h" 12#include "crypto/sha2.h" 13#include "extensions/browser/computed_hashes.h" 14#include "extensions/browser/content_hash_tree.h" 15#include "extensions/browser/verified_contents.h" 16#include "extensions/common/extension.h" 17#include "extensions/common/file_util.h" 18 19using base::DictionaryValue; 20using base::ListValue; 21using base::Value; 22 23namespace extensions { 24 25ContentHashReader::ContentHashReader(const std::string& extension_id, 26 const base::Version& extension_version, 27 const base::FilePath& extension_root, 28 const base::FilePath& relative_path, 29 const ContentVerifierKey& key) 30 : extension_id_(extension_id), 31 extension_version_(extension_version.GetString()), 32 extension_root_(extension_root), 33 relative_path_(relative_path), 34 key_(key), 35 status_(NOT_INITIALIZED), 36 have_verified_contents_(false), 37 have_computed_hashes_(false), 38 block_size_(0) { 39} 40 41ContentHashReader::~ContentHashReader() { 42} 43 44bool ContentHashReader::Init() { 45 DCHECK_EQ(status_, NOT_INITIALIZED); 46 status_ = FAILURE; 47 base::FilePath verified_contents_path = 48 file_util::GetVerifiedContentsPath(extension_root_); 49 50 if (!base::PathExists(verified_contents_path)) 51 return false; 52 53 verified_contents_.reset(new VerifiedContents(key_.data, key_.size)); 54 if (!verified_contents_->InitFrom(verified_contents_path, false) || 55 !verified_contents_->valid_signature() || 56 !verified_contents_->version().Equals(extension_version_) || 57 verified_contents_->extension_id() != extension_id_) 58 return false; 59 60 have_verified_contents_ = true; 61 62 base::FilePath computed_hashes_path = 63 file_util::GetComputedHashesPath(extension_root_); 64 if (!base::PathExists(computed_hashes_path)) 65 return false; 66 67 ComputedHashes::Reader reader; 68 if (!reader.InitFromFile(computed_hashes_path)) 69 return false; 70 71 have_computed_hashes_ = true; 72 73 if (!reader.GetHashes(relative_path_, &block_size_, &hashes_) || 74 block_size_ % crypto::kSHA256Length != 0) 75 return false; 76 77 const std::string* expected_root = 78 verified_contents_->GetTreeHashRoot(relative_path_); 79 if (!expected_root) 80 return false; 81 82 std::string root = 83 ComputeTreeHashRoot(hashes_, block_size_ / crypto::kSHA256Length); 84 if (*expected_root != root) 85 return false; 86 87 status_ = SUCCESS; 88 return true; 89} 90 91int ContentHashReader::block_count() const { 92 DCHECK(status_ != NOT_INITIALIZED); 93 return hashes_.size(); 94} 95 96int ContentHashReader::block_size() const { 97 DCHECK(status_ != NOT_INITIALIZED); 98 return block_size_; 99} 100 101bool ContentHashReader::GetHashForBlock(int block_index, 102 const std::string** result) const { 103 if (status_ != SUCCESS) 104 return false; 105 DCHECK(block_index >= 0); 106 107 if (static_cast<unsigned>(block_index) >= hashes_.size()) 108 return false; 109 *result = &hashes_[block_index]; 110 111 return true; 112} 113 114} // namespace extensions 115