OLD | NEW |
| (Empty) |
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 "chrome/browser/net/packed_ct_ev_whitelist.h" | |
6 | |
7 #include <string.h> | |
8 | |
9 #include <algorithm> | |
10 | |
11 #include "base/big_endian.h" | |
12 #include "base/files/file_util.h" | |
13 #include "base/lazy_instance.h" | |
14 #include "base/logging.h" | |
15 #include "chrome/browser/net/bit_stream_reader.h" | |
16 #include "content/public/browser/browser_thread.h" | |
17 #include "net/ssl/ssl_config_service.h" | |
18 | |
19 namespace { | |
20 const uint8_t kCertHashLengthBits = 64; // 8 bytes | |
21 const uint8_t kCertHashLength = kCertHashLengthBits / 8; | |
22 const uint64_t kGolombMParameterBits = 47; // 2^47 | |
23 | |
24 void SetEVWhitelistInSSLConfigService( | |
25 const scoped_refptr<net::ct::EVCertsWhitelist>& new_whitelist) { | |
26 VLOG(1) << "Setting new EV Certs whitelist."; | |
27 net::SSLConfigService::SetEVCertsWhitelist(new_whitelist); | |
28 } | |
29 | |
30 int TruncatedHashesComparator(const void* v1, const void* v2) { | |
31 const uint64_t& h1(*(static_cast<const uint64_t*>(v1))); | |
32 const uint64_t& h2(*(static_cast<const uint64_t*>(v2))); | |
33 if (h1 < h2) | |
34 return -1; | |
35 else if (h1 > h2) | |
36 return 1; | |
37 return 0; | |
38 } | |
39 } // namespace | |
40 | |
41 void SetEVCertsWhitelist(scoped_refptr<net::ct::EVCertsWhitelist> whitelist) { | |
42 if (!whitelist->IsValid()) { | |
43 VLOG(1) << "EV Certs whitelist is not valid, not setting."; | |
44 return; | |
45 } | |
46 | |
47 base::Closure assign_cb = | |
48 base::Bind(SetEVWhitelistInSSLConfigService, whitelist); | |
49 content::BrowserThread::PostTask( | |
50 content::BrowserThread::IO, FROM_HERE, assign_cb); | |
51 } | |
52 | |
53 bool PackedEVCertsWhitelist::UncompressEVWhitelist( | |
54 const std::string& compressed_whitelist, | |
55 std::vector<uint64_t>* uncompressed_list) { | |
56 internal::BitStreamReader reader(base::StringPiece( | |
57 compressed_whitelist.data(), compressed_whitelist.size())); | |
58 std::vector<uint64_t> result; | |
59 | |
60 VLOG(1) << "Uncompressing EV whitelist of size " | |
61 << compressed_whitelist.size(); | |
62 uint64_t curr_hash(0); | |
63 if (!reader.ReadBits(kCertHashLengthBits, &curr_hash)) { | |
64 VLOG(1) << "Failed reading first hash."; | |
65 return false; | |
66 } | |
67 result.push_back(curr_hash); | |
68 // M is the tunable parameter used by the Golomb coding. | |
69 static const uint64_t kGolombParameterM = static_cast<uint64_t>(1) | |
70 << kGolombMParameterBits; | |
71 | |
72 while (reader.BitsLeft() > kGolombMParameterBits) { | |
73 uint64_t read_prefix = 0; | |
74 if (!reader.ReadUnaryEncoding(&read_prefix)) { | |
75 VLOG(1) << "Failed reading unary-encoded prefix."; | |
76 return false; | |
77 } | |
78 if (read_prefix > (UINT64_MAX / kGolombParameterM)) { | |
79 VLOG(1) << "Received value that would cause overflow: " << read_prefix; | |
80 return false; | |
81 } | |
82 | |
83 uint64_t r = 0; | |
84 if (!reader.ReadBits(kGolombMParameterBits, &r)) { | |
85 VLOG(1) << "Failed reading " << kGolombMParameterBits << " bits."; | |
86 return false; | |
87 } | |
88 DCHECK_LT(r, kGolombParameterM); | |
89 | |
90 uint64_t curr_diff = read_prefix * kGolombParameterM + r; | |
91 curr_hash += curr_diff; | |
92 | |
93 result.push_back(curr_hash); | |
94 } | |
95 | |
96 uncompressed_list->swap(result); | |
97 return true; | |
98 } | |
99 | |
100 PackedEVCertsWhitelist::PackedEVCertsWhitelist( | |
101 const std::string& compressed_whitelist) { | |
102 if (!UncompressEVWhitelist(compressed_whitelist, &whitelist_)) { | |
103 whitelist_.clear(); | |
104 return; | |
105 } | |
106 } | |
107 | |
108 PackedEVCertsWhitelist::~PackedEVCertsWhitelist() { | |
109 } | |
110 | |
111 bool PackedEVCertsWhitelist::ContainsCertificateHash( | |
112 const std::string& certificate_hash) const { | |
113 DCHECK(!whitelist_.empty()); | |
114 uint64_t hash_to_lookup; | |
115 | |
116 base::ReadBigEndian(certificate_hash.data(), &hash_to_lookup); | |
117 return bsearch(&hash_to_lookup, | |
118 &whitelist_[0], | |
119 whitelist_.size(), | |
120 kCertHashLength, | |
121 TruncatedHashesComparator) != NULL; | |
122 } | |
123 | |
124 bool PackedEVCertsWhitelist::IsValid() const { | |
125 return whitelist_.size() > 0; | |
126 } | |
OLD | NEW |