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