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 #ifndef EXTENSIONS_BROWSER_VERIFIED_CONTENTS_H_
      6 #define EXTENSIONS_BROWSER_VERIFIED_CONTENTS_H_
      7 
      8 #include <map>
      9 #include <string>
     10 #include <vector>
     11 
     12 #include "base/files/file_path.h"
     13 #include "base/version.h"
     14 
     15 namespace extensions {
     16 
     17 // This class encapsulates the data in a "verified_contents.json" file
     18 // generated by the webstore for a .crx file. That data includes a set of
     19 // signed expected hashes of file content which can be used to check for
     20 // corruption of extension files on local disk.
     21 class VerifiedContents {
     22  public:
     23   // This function fixes up a string in base64url encoding to be in standard
     24   // base64.
     25   //
     26   // The JSON signing spec we're following uses "base64url" encoding (RFC 4648
     27   // section 5 without padding). The slight differences from regular base64
     28   // encoding are:
     29   //   1. uses '_' instead of '/'
     30   //   2. uses '-' instead of '+'
     31   //   3. omits trailing '=' padding
     32   static bool FixupBase64Encoding(std::string* input);
     33 
     34   // Note: the public_key must remain valid for the lifetime of this object.
     35   VerifiedContents(const uint8* public_key, int public_key_size);
     36   ~VerifiedContents();
     37 
     38   // Returns true if we successfully parsed the verified_contents.json file at
     39   // |path| and validated the enclosed signature. The
     40   // |ignore_invalid_signature| argument can be set to make this still succeed
     41   // if the contents of the file were parsed successfully but the signature did
     42   // not validate. (Use with caution!)
     43   bool InitFrom(const base::FilePath& path, bool ignore_invalid_signature);
     44 
     45   int block_size() const { return block_size_; }
     46   const std::string& extension_id() const { return extension_id_; }
     47   const base::Version& version() const { return version_; }
     48 
     49   bool HasTreeHashRoot(const base::FilePath& relative_path) const;
     50 
     51   bool TreeHashRootEquals(const base::FilePath& relative_path,
     52                           const std::string& expected) const;
     53 
     54   // If InitFrom has not been called yet, or was used in "ignore invalid
     55   // signature" mode, this can return false.
     56   bool valid_signature() { return valid_signature_; }
     57 
     58  private:
     59   // Returns the base64url-decoded "payload" field from the json at |path|, if
     60   // the signature was valid (or ignore_invalid_signature was set to true).
     61   bool GetPayload(const base::FilePath& path,
     62                   std::string* payload,
     63                   bool ignore_invalid_signature);
     64 
     65   // The |protected_value| and |payload| arguments should be base64url encoded
     66   // strings, and |signature_bytes| should be a byte array. See comments in the
     67   // .cc file on GetPayload for where these come from in the overall input
     68   // file.
     69   bool VerifySignature(const std::string& protected_value,
     70                        const std::string& payload,
     71                        const std::string& signature_bytes);
     72 
     73   // The public key we should use for signature verification.
     74   const uint8* public_key_;
     75   const int public_key_size_;
     76 
     77   // Indicates whether the signature was successfully validated or not.
     78   bool valid_signature_;
     79 
     80   // The block size used for computing the treehash root hashes.
     81   int block_size_;
     82 
     83   // Information about which extension these signed hashes are for.
     84   std::string extension_id_;
     85   base::Version version_;
     86 
     87   // The expected treehash root hashes for each file, lower cased so we can do
     88   // case-insensitive lookups.
     89   //
     90   // We use a multi-map here so that we can do fast lookups of paths from
     91   // requests on case-insensitive systems (windows, mac) where the request path
     92   // might not have the exact right capitalization, but not break
     93   // case-sensitive systems (linux, chromeos). TODO(asargent) - we should give
     94   // developers client-side warnings in each of those cases, and have the
     95   // webstore reject the cases they can statically detect. See crbug.com/29941
     96   typedef std::multimap<base::FilePath::StringType, std::string> RootHashes;
     97   RootHashes root_hashes_;
     98 
     99   DISALLOW_COPY_AND_ASSIGN(VerifiedContents);
    100 };
    101 
    102 }  // namespace extensions
    103 
    104 #endif  // EXTENSIONS_BROWSER_VERIFIED_CONTENTS_H_
    105