| OLD | NEW |
| 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 "extensions/browser/verified_contents.h" | 5 #include "extensions/browser/verified_contents.h" |
| 6 | 6 |
| 7 #include "base/base64.h" | 7 #include "base/base64.h" |
| 8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 9 #include "base/json/json_reader.h" | 9 #include "base/json/json_reader.h" |
| 10 #include "base/strings/string_util.h" | 10 #include "base/strings/string_util.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 std::string key, | 53 std::string key, |
| 54 std::string value) { | 54 std::string value) { |
| 55 for (ListValue::const_iterator i = list->begin(); i != list->end(); ++i) { | 55 for (ListValue::const_iterator i = list->begin(); i != list->end(); ++i) { |
| 56 if (!(*i)->IsType(Value::TYPE_DICTIONARY)) | 56 if (!(*i)->IsType(Value::TYPE_DICTIONARY)) |
| 57 continue; | 57 continue; |
| 58 DictionaryValue* dictionary = static_cast<DictionaryValue*>(*i); | 58 DictionaryValue* dictionary = static_cast<DictionaryValue*>(*i); |
| 59 std::string found_value; | 59 std::string found_value; |
| 60 if (dictionary->GetString(key, &found_value) && found_value == value) | 60 if (dictionary->GetString(key, &found_value) && found_value == value) |
| 61 return dictionary; | 61 return dictionary; |
| 62 } | 62 } |
| 63 return NULL; | 63 return nullptr; |
| 64 } | 64 } |
| 65 | 65 |
| 66 } // namespace | 66 } // namespace |
| 67 | 67 |
| 68 namespace extensions { | 68 namespace extensions { |
| 69 | 69 |
| 70 // static | 70 // static |
| 71 bool VerifiedContents::FixupBase64Encoding(std::string* input) { | 71 bool VerifiedContents::FixupBase64Encoding(std::string* input) { |
| 72 for (std::string::iterator i = input->begin(); i != input->end(); ++i) { | 72 for (std::string::iterator i = input->begin(); i != input->end(); ++i) { |
| 73 if (*i == '-') | 73 if (*i == '-') |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 136 return false; | 136 return false; |
| 137 extension_id_ = item_id; | 137 extension_id_ = item_id; |
| 138 | 138 |
| 139 std::string version_string; | 139 std::string version_string; |
| 140 if (!dictionary->GetString(kItemVersionKey, &version_string)) | 140 if (!dictionary->GetString(kItemVersionKey, &version_string)) |
| 141 return false; | 141 return false; |
| 142 version_ = base::Version(version_string); | 142 version_ = base::Version(version_string); |
| 143 if (!version_.IsValid()) | 143 if (!version_.IsValid()) |
| 144 return false; | 144 return false; |
| 145 | 145 |
| 146 ListValue* hashes_list = NULL; | 146 ListValue* hashes_list = nullptr; |
| 147 if (!dictionary->GetList(kContentHashesKey, &hashes_list)) | 147 if (!dictionary->GetList(kContentHashesKey, &hashes_list)) |
| 148 return false; | 148 return false; |
| 149 | 149 |
| 150 for (size_t i = 0; i < hashes_list->GetSize(); i++) { | 150 for (size_t i = 0; i < hashes_list->GetSize(); i++) { |
| 151 DictionaryValue* hashes = NULL; | 151 DictionaryValue* hashes = nullptr; |
| 152 if (!hashes_list->GetDictionary(i, &hashes)) | 152 if (!hashes_list->GetDictionary(i, &hashes)) |
| 153 return false; | 153 return false; |
| 154 std::string format; | 154 std::string format; |
| 155 if (!hashes->GetString(kFormatKey, &format) || format != kTreeHash) | 155 if (!hashes->GetString(kFormatKey, &format) || format != kTreeHash) |
| 156 continue; | 156 continue; |
| 157 | 157 |
| 158 int block_size = 0; | 158 int block_size = 0; |
| 159 int hash_block_size = 0; | 159 int hash_block_size = 0; |
| 160 if (!hashes->GetInteger(kBlockSizeKey, &block_size) || | 160 if (!hashes->GetInteger(kBlockSizeKey, &block_size) || |
| 161 !hashes->GetInteger(kHashBlockSizeKey, &hash_block_size)) | 161 !hashes->GetInteger(kHashBlockSizeKey, &hash_block_size)) |
| 162 return false; | 162 return false; |
| 163 block_size_ = block_size; | 163 block_size_ = block_size; |
| 164 | 164 |
| 165 // We don't support using a different block_size and hash_block_size at | 165 // We don't support using a different block_size and hash_block_size at |
| 166 // the moment. | 166 // the moment. |
| 167 if (block_size_ != hash_block_size) | 167 if (block_size_ != hash_block_size) |
| 168 return false; | 168 return false; |
| 169 | 169 |
| 170 ListValue* files = NULL; | 170 ListValue* files = nullptr; |
| 171 if (!hashes->GetList(kFilesKey, &files)) | 171 if (!hashes->GetList(kFilesKey, &files)) |
| 172 return false; | 172 return false; |
| 173 | 173 |
| 174 for (size_t j = 0; j < files->GetSize(); j++) { | 174 for (size_t j = 0; j < files->GetSize(); j++) { |
| 175 DictionaryValue* data = NULL; | 175 DictionaryValue* data = nullptr; |
| 176 if (!files->GetDictionary(j, &data)) | 176 if (!files->GetDictionary(j, &data)) |
| 177 return false; | 177 return false; |
| 178 std::string file_path_string; | 178 std::string file_path_string; |
| 179 std::string encoded_root_hash; | 179 std::string encoded_root_hash; |
| 180 std::string root_hash; | 180 std::string root_hash; |
| 181 if (!data->GetString(kPathKey, &file_path_string) || | 181 if (!data->GetString(kPathKey, &file_path_string) || |
| 182 !base::IsStringUTF8(file_path_string) || | 182 !base::IsStringUTF8(file_path_string) || |
| 183 !data->GetString(kRootHashKey, &encoded_root_hash) || | 183 !data->GetString(kRootHashKey, &encoded_root_hash) || |
| 184 !FixupBase64Encoding(&encoded_root_hash) || | 184 !FixupBase64Encoding(&encoded_root_hash) || |
| 185 !base::Base64Decode(encoded_root_hash, &root_hash)) | 185 !base::Base64Decode(encoded_root_hash, &root_hash)) |
| 186 return false; | 186 return false; |
| 187 base::FilePath file_path = | 187 base::FilePath file_path = |
| 188 base::FilePath::FromUTF8Unsafe(file_path_string); | 188 base::FilePath::FromUTF8Unsafe(file_path_string); |
| 189 root_hashes_[file_path] = std::string(); | 189 root_hashes_[file_path] = std::string(); |
| 190 root_hashes_[file_path].swap(root_hash); | 190 root_hashes_[file_path].swap(root_hash); |
| 191 } | 191 } |
| 192 | 192 |
| 193 break; | 193 break; |
| 194 } | 194 } |
| 195 return true; | 195 return true; |
| 196 } | 196 } |
| 197 | 197 |
| 198 const std::string* VerifiedContents::GetTreeHashRoot( | 198 const std::string* VerifiedContents::GetTreeHashRoot( |
| 199 const base::FilePath& relative_path) { | 199 const base::FilePath& relative_path) { |
| 200 std::map<base::FilePath, std::string>::const_iterator i = | 200 std::map<base::FilePath, std::string>::const_iterator i = |
| 201 root_hashes_.find(relative_path.NormalizePathSeparatorsTo('/')); | 201 root_hashes_.find(relative_path.NormalizePathSeparatorsTo('/')); |
| 202 if (i == root_hashes_.end()) | 202 if (i == root_hashes_.end()) |
| 203 return NULL; | 203 return nullptr; |
| 204 return &i->second; | 204 return &i->second; |
| 205 } | 205 } |
| 206 | 206 |
| 207 // We're loosely following the "JSON Web Signature" draft spec for signing | 207 // We're loosely following the "JSON Web Signature" draft spec for signing |
| 208 // a JSON payload: | 208 // a JSON payload: |
| 209 // | 209 // |
| 210 // http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-26 | 210 // http://tools.ietf.org/html/draft-ietf-jose-json-web-signature-26 |
| 211 // | 211 // |
| 212 // The idea is that you have some JSON that you want to sign, so you | 212 // The idea is that you have some JSON that you want to sign, so you |
| 213 // base64-encode that and put it as the "payload" field in a containing | 213 // base64-encode that and put it as the "payload" field in a containing |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 // { | 261 // { |
| 262 // "description": "treehash per file", | 262 // "description": "treehash per file", |
| 263 // "signed_content": { | 263 // "signed_content": { |
| 264 // "signatures": [ ... ], | 264 // "signatures": [ ... ], |
| 265 // "payload": "..." | 265 // "payload": "..." |
| 266 // } | 266 // } |
| 267 // } | 267 // } |
| 268 // ] | 268 // ] |
| 269 DictionaryValue* dictionary = | 269 DictionaryValue* dictionary = |
| 270 FindDictionaryWithValue(top_list, kDescriptionKey, kTreeHashPerFile); | 270 FindDictionaryWithValue(top_list, kDescriptionKey, kTreeHashPerFile); |
| 271 DictionaryValue* signed_content = NULL; | 271 DictionaryValue* signed_content = nullptr; |
| 272 if (!dictionary || | 272 if (!dictionary || |
| 273 !dictionary->GetDictionaryWithoutPathExpansion(kSignedContentKey, | 273 !dictionary->GetDictionaryWithoutPathExpansion(kSignedContentKey, |
| 274 &signed_content)) { | 274 &signed_content)) { |
| 275 return false; | 275 return false; |
| 276 } | 276 } |
| 277 | 277 |
| 278 ListValue* signatures = NULL; | 278 ListValue* signatures = nullptr; |
| 279 if (!signed_content->GetList(kSignaturesKey, &signatures)) | 279 if (!signed_content->GetList(kSignaturesKey, &signatures)) |
| 280 return false; | 280 return false; |
| 281 | 281 |
| 282 DictionaryValue* signature_dict = | 282 DictionaryValue* signature_dict = |
| 283 FindDictionaryWithValue(signatures, kHeaderKidKey, kWebstoreKId); | 283 FindDictionaryWithValue(signatures, kHeaderKidKey, kWebstoreKId); |
| 284 if (!signature_dict) | 284 if (!signature_dict) |
| 285 return false; | 285 return false; |
| 286 | 286 |
| 287 std::string protected_value; | 287 std::string protected_value; |
| 288 std::string encoded_signature; | 288 std::string encoded_signature; |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336 reinterpret_cast<const uint8*>(payload.data()), payload.size()); | 336 reinterpret_cast<const uint8*>(payload.data()), payload.size()); |
| 337 | 337 |
| 338 if (!signature_verifier.VerifyFinal()) { | 338 if (!signature_verifier.VerifyFinal()) { |
| 339 VLOG(1) << "Could not verify signature - VerifyFinal failure"; | 339 VLOG(1) << "Could not verify signature - VerifyFinal failure"; |
| 340 return false; | 340 return false; |
| 341 } | 341 } |
| 342 return true; | 342 return true; |
| 343 } | 343 } |
| 344 | 344 |
| 345 } // namespace extensions | 345 } // namespace extensions |
| OLD | NEW |