OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 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 "net/quic/crypto/common_cert_set.h" | |
6 | |
7 #include <cstddef> | |
8 | |
9 #include "base/logging.h" | |
10 #include "base/macros.h" | |
11 #include "base/memory/singleton.h" | |
12 #include "net/quic/quic_utils.h" | |
13 | |
14 using base::StringPiece; | |
15 | |
16 namespace net { | |
17 | |
18 namespace common_cert_set_1 { | |
19 #include "net/quic/crypto/common_cert_set_1.c" | |
20 } | |
21 | |
22 namespace common_cert_set_2 { | |
23 #include "net/quic/crypto/common_cert_set_2.c" | |
24 } | |
25 | |
26 namespace { | |
27 | |
28 struct CertSet { | |
29 // num_certs contains the number of certificates in this set. | |
30 size_t num_certs; | |
31 // certs is an array of |num_certs| pointers to the DER encoded certificates. | |
32 const unsigned char* const* certs; | |
33 // lens is an array of |num_certs| integers describing the length, in bytes, | |
34 // of each certificate. | |
35 const size_t* lens; | |
36 // hash contains the 64-bit, FNV-1a hash of this set. | |
37 uint64_t hash; | |
38 }; | |
39 | |
40 const CertSet kSets[] = { | |
41 { | |
42 common_cert_set_1::kNumCerts, common_cert_set_1::kCerts, | |
43 common_cert_set_1::kLens, common_cert_set_1::kHash, | |
44 }, | |
45 { | |
46 common_cert_set_2::kNumCerts, common_cert_set_2::kCerts, | |
47 common_cert_set_2::kLens, common_cert_set_2::kHash, | |
48 }, | |
49 }; | |
50 | |
51 const uint64_t kSetHashes[] = { | |
52 common_cert_set_1::kHash, common_cert_set_2::kHash, | |
53 }; | |
54 | |
55 // Compare returns a value less than, equal to or greater than zero if |a| is | |
56 // lexicographically less than, equal to or greater than |b|, respectively. | |
57 int Compare(StringPiece a, const unsigned char* b, size_t b_len) { | |
58 size_t len = a.size(); | |
59 if (len > b_len) { | |
60 len = b_len; | |
61 } | |
62 int n = memcmp(a.data(), b, len); | |
63 if (n != 0) { | |
64 return n; | |
65 } | |
66 | |
67 if (a.size() < b_len) { | |
68 return -1; | |
69 } else if (a.size() > b_len) { | |
70 return 1; | |
71 } | |
72 return 0; | |
73 } | |
74 | |
75 // CommonCertSetsQUIC implements the CommonCertSets interface using the default | |
76 // certificate sets. | |
77 class CommonCertSetsQUIC : public CommonCertSets { | |
78 public: | |
79 // CommonCertSets interface. | |
80 StringPiece GetCommonHashes() const override { | |
81 return StringPiece(reinterpret_cast<const char*>(kSetHashes), | |
82 sizeof(uint64_t) * arraysize(kSetHashes)); | |
83 } | |
84 | |
85 StringPiece GetCert(uint64_t hash, uint32_t index) const override { | |
86 for (size_t i = 0; i < arraysize(kSets); i++) { | |
87 if (kSets[i].hash == hash) { | |
88 if (index < kSets[i].num_certs) { | |
89 return StringPiece( | |
90 reinterpret_cast<const char*>(kSets[i].certs[index]), | |
91 kSets[i].lens[index]); | |
92 } | |
93 break; | |
94 } | |
95 } | |
96 | |
97 return StringPiece(); | |
98 } | |
99 | |
100 bool MatchCert(StringPiece cert, | |
101 StringPiece common_set_hashes, | |
102 uint64_t* out_hash, | |
103 uint32_t* out_index) const override { | |
104 if (common_set_hashes.size() % sizeof(uint64_t) != 0) { | |
105 return false; | |
106 } | |
107 | |
108 for (size_t i = 0; i < common_set_hashes.size() / sizeof(uint64_t); i++) { | |
109 uint64_t hash; | |
110 memcpy(&hash, common_set_hashes.data() + i * sizeof(uint64_t), | |
111 sizeof(uint64_t)); | |
112 | |
113 for (size_t j = 0; j < arraysize(kSets); j++) { | |
114 if (kSets[j].hash != hash) { | |
115 continue; | |
116 } | |
117 | |
118 if (kSets[j].num_certs == 0) { | |
119 continue; | |
120 } | |
121 | |
122 // Binary search for a matching certificate. | |
123 size_t min = 0; | |
124 size_t max = kSets[j].num_certs - 1; | |
125 while (max >= min) { | |
126 size_t mid = min + ((max - min) / 2); | |
127 int n = Compare(cert, kSets[j].certs[mid], kSets[j].lens[mid]); | |
128 if (n < 0) { | |
129 if (mid == 0) { | |
130 break; | |
131 } | |
132 max = mid - 1; | |
133 } else if (n > 0) { | |
134 min = mid + 1; | |
135 } else { | |
136 *out_hash = hash; | |
137 *out_index = mid; | |
138 return true; | |
139 } | |
140 } | |
141 } | |
142 } | |
143 | |
144 return false; | |
145 } | |
146 | |
147 static CommonCertSetsQUIC* GetInstance() { | |
148 return base::Singleton<CommonCertSetsQUIC>::get(); | |
149 } | |
150 | |
151 private: | |
152 CommonCertSetsQUIC() {} | |
153 ~CommonCertSetsQUIC() override {} | |
154 | |
155 friend struct base::DefaultSingletonTraits<CommonCertSetsQUIC>; | |
156 DISALLOW_COPY_AND_ASSIGN(CommonCertSetsQUIC); | |
157 }; | |
158 | |
159 } // anonymous namespace | |
160 | |
161 CommonCertSets::~CommonCertSets() {} | |
162 | |
163 // static | |
164 const CommonCertSets* CommonCertSets::GetInstanceQUIC() { | |
165 return CommonCertSetsQUIC::GetInstance(); | |
166 } | |
167 | |
168 } // namespace net | |
OLD | NEW |