OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "base/base64.h" | 5 #include "base/base64.h" |
6 #include "base/debug/trace_event.h" | |
6 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
7 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
8 #include "base/logging.h" | 9 #include "base/logging.h" |
9 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
10 #include "base/strings/string_util.h" | 11 #include "base/strings/string_util.h" |
11 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
12 #include "base/time/time.h" | 13 #include "base/time/time.h" |
13 #include "base/values.h" | 14 #include "base/values.h" |
14 #include "crypto/sha2.h" | 15 #include "crypto/sha2.h" |
15 #include "net/cert/crl_set.h" | 16 #include "net/cert/crl_set.h" |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
144 } | 145 } |
145 | 146 |
146 // kCurrentFileVersion is the version of the CRLSet file format that we | 147 // kCurrentFileVersion is the version of the CRLSet file format that we |
147 // currently implement. | 148 // currently implement. |
148 static const int kCurrentFileVersion = 0; | 149 static const int kCurrentFileVersion = 0; |
149 | 150 |
150 static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, | 151 static bool ReadCRL(base::StringPiece* data, std::string* out_parent_spki_hash, |
151 std::vector<std::string>* out_serials) { | 152 std::vector<std::string>* out_serials) { |
152 if (data->size() < crypto::kSHA256Length) | 153 if (data->size() < crypto::kSHA256Length) |
153 return false; | 154 return false; |
154 *out_parent_spki_hash = std::string(data->data(), crypto::kSHA256Length); | 155 out_parent_spki_hash->assign(data->data(), crypto::kSHA256Length); |
155 data->remove_prefix(crypto::kSHA256Length); | 156 data->remove_prefix(crypto::kSHA256Length); |
156 | 157 |
157 if (data->size() < sizeof(uint32)) | 158 if (data->size() < sizeof(uint32)) |
158 return false; | 159 return false; |
159 uint32 num_serials; | 160 uint32 num_serials; |
160 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian | 161 memcpy(&num_serials, data->data(), sizeof(uint32)); // assumes little endian |
162 out_serials->reserve(num_serials); | |
agl
2014/06/02 18:07:25
Previously the memory usage of this code was limit
Philippe
2014/06/03 08:21:03
Good point :)
| |
161 data->remove_prefix(sizeof(uint32)); | 163 data->remove_prefix(sizeof(uint32)); |
162 | 164 |
163 for (uint32 i = 0; i < num_serials; ++i) { | 165 for (uint32 i = 0; i < num_serials; ++i) { |
164 uint8 serial_length; | |
165 if (data->size() < sizeof(uint8)) | 166 if (data->size() < sizeof(uint8)) |
166 return false; | 167 return false; |
167 memcpy(&serial_length, data->data(), sizeof(uint8)); | 168 |
169 uint8 serial_length = data->data()[0]; | |
168 data->remove_prefix(sizeof(uint8)); | 170 data->remove_prefix(sizeof(uint8)); |
169 | 171 |
170 if (data->size() < serial_length) | 172 if (data->size() < serial_length) |
171 return false; | 173 return false; |
172 std::string serial(data->data(), serial_length); | 174 |
173 data->remove_prefix(serial_length); | 175 data->remove_prefix(serial_length); |
174 out_serials->push_back(serial); | 176 out_serials->push_back(std::string()); |
177 out_serials->back().assign(data->data(), serial_length); | |
175 } | 178 } |
176 | 179 |
177 return true; | 180 return true; |
178 } | 181 } |
179 | 182 |
180 bool CRLSet::CopyBlockedSPKIsFromHeader(base::DictionaryValue* header_dict) { | 183 bool CRLSet::CopyBlockedSPKIsFromHeader(base::DictionaryValue* header_dict) { |
181 base::ListValue* blocked_spkis_list = NULL; | 184 base::ListValue* blocked_spkis_list = NULL; |
182 if (!header_dict->GetList("BlockedSPKIs", &blocked_spkis_list)) { | 185 if (!header_dict->GetList("BlockedSPKIs", &blocked_spkis_list)) { |
183 // BlockedSPKIs is optional, so it's fine if we don't find it. | 186 // BlockedSPKIs is optional, so it's fine if we don't find it. |
184 return true; | 187 return true; |
185 } | 188 } |
186 | 189 |
187 blocked_spkis_.clear(); | 190 blocked_spkis_.clear(); |
191 blocked_spkis_.reserve(blocked_spkis_list->GetSize()); | |
192 | |
193 std::string spki_sha256_base64; | |
188 | 194 |
189 for (size_t i = 0; i < blocked_spkis_list->GetSize(); ++i) { | 195 for (size_t i = 0; i < blocked_spkis_list->GetSize(); ++i) { |
190 std::string spki_sha256_base64, spki_sha256; | 196 spki_sha256_base64.clear(); |
197 | |
191 if (!blocked_spkis_list->GetString(i, &spki_sha256_base64)) | 198 if (!blocked_spkis_list->GetString(i, &spki_sha256_base64)) |
192 return false; | 199 return false; |
193 if (!base::Base64Decode(spki_sha256_base64, &spki_sha256)) | 200 |
201 blocked_spkis_.push_back(std::string()); | |
202 if (!base::Base64Decode(spki_sha256_base64, &blocked_spkis_.back())) { | |
203 blocked_spkis_.pop_back(); | |
194 return false; | 204 return false; |
195 blocked_spkis_.push_back(spki_sha256); | 205 } |
196 } | 206 } |
197 | 207 |
198 return true; | 208 return true; |
199 } | 209 } |
200 | 210 |
201 // static | 211 // static |
202 bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { | 212 bool CRLSet::Parse(base::StringPiece data, scoped_refptr<CRLSet>* out_crl_set) { |
213 TRACE_EVENT0("CRLSet", "Parse"); | |
203 // Other parts of Chrome assume that we're little endian, so we don't lose | 214 // Other parts of Chrome assume that we're little endian, so we don't lose |
204 // anything by doing this. | 215 // anything by doing this. |
205 #if defined(__BYTE_ORDER) | 216 #if defined(__BYTE_ORDER) |
206 // Linux check | 217 // Linux check |
207 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); | 218 COMPILE_ASSERT(__BYTE_ORDER == __LITTLE_ENDIAN, assumes_little_endian); |
208 #elif defined(__BIG_ENDIAN__) | 219 #elif defined(__BIG_ENDIAN__) |
209 // Mac check | 220 // Mac check |
210 #error assumes little endian | 221 #error assumes little endian |
211 #endif | 222 #endif |
212 | 223 |
(...skipping 18 matching lines...) Expand all Loading... | |
231 return false; | 242 return false; |
232 | 243 |
233 double not_after; | 244 double not_after; |
234 if (!header_dict->GetDouble("NotAfter", ¬_after)) { | 245 if (!header_dict->GetDouble("NotAfter", ¬_after)) { |
235 // NotAfter is optional for now. | 246 // NotAfter is optional for now. |
236 not_after = 0; | 247 not_after = 0; |
237 } | 248 } |
238 if (not_after < 0) | 249 if (not_after < 0) |
239 return false; | 250 return false; |
240 | 251 |
241 scoped_refptr<CRLSet> crl_set(new CRLSet); | 252 scoped_refptr<CRLSet> crl_set(new CRLSet()); |
242 crl_set->sequence_ = static_cast<uint32>(sequence); | 253 crl_set->sequence_ = static_cast<uint32>(sequence); |
243 crl_set->not_after_ = static_cast<uint64>(not_after); | 254 crl_set->not_after_ = static_cast<uint64>(not_after); |
255 crl_set->crls_.reserve(64); // Value observed experimentally. | |
244 | 256 |
245 for (size_t crl_index = 0; !data.empty(); crl_index++) { | 257 for (size_t crl_index = 0; !data.empty(); crl_index++) { |
246 std::string parent_spki_sha256; | 258 // Speculatively push back a pair and pass it to ReadCRL() to avoid |
247 std::vector<std::string> serials; | 259 // unnecessary copies. |
248 if (!ReadCRL(&data, &parent_spki_sha256, &serials)) | 260 crl_set->crls_.push_back( |
261 std::make_pair(std::string(), std::vector<std::string>())); | |
262 std::pair<std::string, std::vector<std::string> >* const back_pair = | |
263 &crl_set->crls_.back(); | |
264 | |
265 if (!ReadCRL(&data, &back_pair->first, &back_pair->second)) { | |
266 // Undo the speculative push_back() performed above. | |
267 crl_set->crls_.pop_back(); | |
249 return false; | 268 return false; |
269 } | |
250 | 270 |
251 crl_set->crls_.push_back(std::make_pair(parent_spki_sha256, serials)); | 271 crl_set->crls_index_by_issuer_[back_pair->first] = crl_index; |
252 crl_set->crls_index_by_issuer_[parent_spki_sha256] = crl_index; | |
253 } | 272 } |
254 | 273 |
255 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) | 274 if (!crl_set->CopyBlockedSPKIsFromHeader(header_dict.get())) |
256 return false; | 275 return false; |
257 | 276 |
258 *out_crl_set = crl_set; | 277 *out_crl_set = crl_set; |
259 return true; | 278 return true; |
260 } | 279 } |
261 | 280 |
262 // kMaxUncompressedChangesLength is the largest changes array that we'll | 281 // kMaxUncompressedChangesLength is the largest changes array that we'll |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
541 if (!serial.empty() && (serial[0] & 0x80) != 0) { | 560 if (!serial.empty() && (serial[0] & 0x80) != 0) { |
542 // This serial number is negative but the process which generates CRL sets | 561 // This serial number is negative but the process which generates CRL sets |
543 // will reject any certificates with negative serial numbers as invalid. | 562 // will reject any certificates with negative serial numbers as invalid. |
544 return UNKNOWN; | 563 return UNKNOWN; |
545 } | 564 } |
546 | 565 |
547 // Remove any leading zero bytes. | 566 // Remove any leading zero bytes. |
548 while (serial.size() > 1 && serial[0] == 0x00) | 567 while (serial.size() > 1 && serial[0] == 0x00) |
549 serial.remove_prefix(1); | 568 serial.remove_prefix(1); |
550 | 569 |
551 std::map<std::string, size_t>::const_iterator i = | 570 base::hash_map<std::string, size_t>::const_iterator i = |
552 crls_index_by_issuer_.find(issuer_spki_hash.as_string()); | 571 crls_index_by_issuer_.find(issuer_spki_hash.as_string()); |
553 if (i == crls_index_by_issuer_.end()) | 572 if (i == crls_index_by_issuer_.end()) |
554 return UNKNOWN; | 573 return UNKNOWN; |
555 const std::vector<std::string>& serials = crls_[i->second].second; | 574 const std::vector<std::string>& serials = crls_[i->second].second; |
556 | 575 |
557 for (std::vector<std::string>::const_iterator i = serials.begin(); | 576 for (std::vector<std::string>::const_iterator i = serials.begin(); |
558 i != serials.end(); ++i) { | 577 i != serials.end(); ++i) { |
559 if (base::StringPiece(*i) == serial) | 578 if (base::StringPiece(*i) == serial) |
560 return REVOKED; | 579 return REVOKED; |
561 } | 580 } |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
602 crl_set->crls_index_by_issuer_[spki] = 0; | 621 crl_set->crls_index_by_issuer_[spki] = 0; |
603 } | 622 } |
604 | 623 |
605 if (!serial_number.empty()) | 624 if (!serial_number.empty()) |
606 crl_set->crls_[0].second.push_back(serial_number); | 625 crl_set->crls_[0].second.push_back(serial_number); |
607 | 626 |
608 return crl_set; | 627 return crl_set; |
609 } | 628 } |
610 | 629 |
611 } // namespace net | 630 } // namespace net |
OLD | NEW |