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 "net/cert/x509_certificate.h" | 5 #include "net/cert/x509_certificate.h" |
6 | 6 |
7 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. | 7 #include <blapi.h> // Implement CalculateChainFingerprint() with NSS. |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/pickle.h" | 11 #include "base/pickle.h" |
12 #include "base/sha1.h" | 12 #include "base/sha1.h" |
13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
14 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
15 #include "crypto/capi_util.h" | 15 #include "crypto/capi_util.h" |
16 #include "crypto/scoped_capi_types.h" | 16 #include "crypto/scoped_capi_types.h" |
17 #include "net/base/net_errors.h" | 17 #include "net/base/net_errors.h" |
18 | 18 |
19 #pragma comment(lib, "crypt32.lib") | 19 #pragma comment(lib, "crypt32.lib") |
20 | 20 |
21 using base::Time; | 21 using base::Time; |
22 | 22 |
23 namespace net { | 23 namespace net { |
24 | 24 |
25 namespace { | 25 namespace { |
26 | 26 |
27 typedef crypto::ScopedCAPIHandle< | 27 typedef crypto::ScopedCAPIHandle< |
28 HCERTSTORE, | 28 HCERTSTORE, |
29 crypto::CAPIDestroyerWithFlags<HCERTSTORE, | 29 crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0> > |
30 CertCloseStore, 0> > ScopedHCERTSTORE; | 30 ScopedHCERTSTORE; |
31 | 31 |
32 void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded, | 32 void ExplodedTimeToSystemTime(const base::Time::Exploded& exploded, |
33 SYSTEMTIME* system_time) { | 33 SYSTEMTIME* system_time) { |
34 system_time->wYear = exploded.year; | 34 system_time->wYear = exploded.year; |
35 system_time->wMonth = exploded.month; | 35 system_time->wMonth = exploded.month; |
36 system_time->wDayOfWeek = exploded.day_of_week; | 36 system_time->wDayOfWeek = exploded.day_of_week; |
37 system_time->wDay = exploded.day_of_month; | 37 system_time->wDay = exploded.day_of_month; |
38 system_time->wHour = exploded.hour; | 38 system_time->wHour = exploded.hour; |
39 system_time->wMinute = exploded.minute; | 39 system_time->wMinute = exploded.minute; |
40 system_time->wSecond = exploded.second; | 40 system_time->wSecond = exploded.second; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 output->reset(alt_name_info); | 73 output->reset(alt_name_info); |
74 } | 74 } |
75 | 75 |
76 void AddCertsFromStore(HCERTSTORE store, | 76 void AddCertsFromStore(HCERTSTORE store, |
77 X509Certificate::OSCertHandles* results) { | 77 X509Certificate::OSCertHandles* results) { |
78 PCCERT_CONTEXT cert = NULL; | 78 PCCERT_CONTEXT cert = NULL; |
79 | 79 |
80 while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) { | 80 while ((cert = CertEnumCertificatesInStore(store, cert)) != NULL) { |
81 PCCERT_CONTEXT to_add = NULL; | 81 PCCERT_CONTEXT to_add = NULL; |
82 if (CertAddCertificateContextToStore( | 82 if (CertAddCertificateContextToStore( |
83 NULL, // The cert won't be persisted in any cert store. This breaks | 83 NULL, // The cert won't be persisted in any cert store. This breaks |
84 // any association the context currently has to |store|, which | 84 // any association the context currently has to |store|, which |
85 // allows us, the caller, to safely close |store| without | 85 // allows us, the caller, to safely close |store| without |
86 // releasing the cert handles. | 86 // releasing the cert handles. |
87 cert, | 87 cert, |
88 CERT_STORE_ADD_USE_EXISTING, | 88 CERT_STORE_ADD_USE_EXISTING, |
89 &to_add) && to_add != NULL) { | 89 &to_add) && |
| 90 to_add != NULL) { |
90 // When processing stores generated from PKCS#7/PKCS#12 files, it | 91 // When processing stores generated from PKCS#7/PKCS#12 files, it |
91 // appears that the order returned is the inverse of the order that it | 92 // appears that the order returned is the inverse of the order that it |
92 // appeared in the file. | 93 // appeared in the file. |
93 // TODO(rsleevi): Ensure this order is consistent across all Win | 94 // TODO(rsleevi): Ensure this order is consistent across all Win |
94 // versions | 95 // versions |
95 results->insert(results->begin(), to_add); | 96 results->insert(results->begin(), to_add); |
96 } | 97 } |
97 } | 98 } |
98 } | 99 } |
99 | 100 |
100 X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { | 101 X509Certificate::OSCertHandles ParsePKCS7(const char* data, size_t length) { |
101 X509Certificate::OSCertHandles results; | 102 X509Certificate::OSCertHandles results; |
102 CERT_BLOB data_blob; | 103 CERT_BLOB data_blob; |
103 data_blob.cbData = length; | 104 data_blob.cbData = length; |
104 data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data)); | 105 data_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(data)); |
105 | 106 |
106 HCERTSTORE out_store = NULL; | 107 HCERTSTORE out_store = NULL; |
107 | 108 |
108 DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | | 109 DWORD expected_types = CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED | |
109 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | | 110 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED | |
110 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED; | 111 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED; |
111 | 112 |
112 if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, &data_blob, expected_types, | 113 if (!CryptQueryObject(CERT_QUERY_OBJECT_BLOB, |
113 CERT_QUERY_FORMAT_FLAG_BINARY, 0, NULL, NULL, NULL, | 114 &data_blob, |
114 &out_store, NULL, NULL) || out_store == NULL) { | 115 expected_types, |
| 116 CERT_QUERY_FORMAT_FLAG_BINARY, |
| 117 0, |
| 118 NULL, |
| 119 NULL, |
| 120 NULL, |
| 121 &out_store, |
| 122 NULL, |
| 123 NULL) || |
| 124 out_store == NULL) { |
115 return results; | 125 return results; |
116 } | 126 } |
117 | 127 |
118 AddCertsFromStore(out_store, &results); | 128 AddCertsFromStore(out_store, &results); |
119 CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG); | 129 CertCloseStore(out_store, CERT_CLOSE_STORE_CHECK_FLAG); |
120 | 130 |
121 return results; | 131 return results; |
122 } | 132 } |
123 | 133 |
124 // Given a CERT_NAME_BLOB, returns true if it appears in a given list, | 134 // Given a CERT_NAME_BLOB, returns true if it appears in a given list, |
125 // formatted as a vector of strings holding DER-encoded X.509 | 135 // formatted as a vector of strings holding DER-encoded X.509 |
126 // DistinguishedName entries. | 136 // DistinguishedName entries. |
127 bool IsCertNameBlobInIssuerList( | 137 bool IsCertNameBlobInIssuerList(CERT_NAME_BLOB* name_blob, |
128 CERT_NAME_BLOB* name_blob, | 138 const std::vector<std::string>& issuer_names) { |
129 const std::vector<std::string>& issuer_names) { | |
130 for (std::vector<std::string>::const_iterator it = issuer_names.begin(); | 139 for (std::vector<std::string>::const_iterator it = issuer_names.begin(); |
131 it != issuer_names.end(); ++it) { | 140 it != issuer_names.end(); |
| 141 ++it) { |
132 CERT_NAME_BLOB issuer_blob; | 142 CERT_NAME_BLOB issuer_blob; |
133 issuer_blob.pbData = | 143 issuer_blob.pbData = reinterpret_cast<BYTE*>(const_cast<char*>(it->data())); |
134 reinterpret_cast<BYTE*>(const_cast<char*>(it->data())); | |
135 issuer_blob.cbData = static_cast<DWORD>(it->length()); | 144 issuer_blob.cbData = static_cast<DWORD>(it->length()); |
136 | 145 |
137 BOOL rb = CertCompareCertificateName( | 146 BOOL rb = CertCompareCertificateName( |
138 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob); | 147 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, &issuer_blob, name_blob); |
139 if (rb) | 148 if (rb) |
140 return true; | 149 return true; |
141 } | 150 } |
142 return false; | 151 return false; |
143 } | 152 } |
144 | 153 |
145 } // namespace | 154 } // namespace |
146 | 155 |
147 void X509Certificate::Initialize() { | 156 void X509Certificate::Initialize() { |
148 DCHECK(cert_handle_); | 157 DCHECK(cert_handle_); |
149 subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData, | 158 subject_.ParseDistinguishedName(cert_handle_->pCertInfo->Subject.pbData, |
150 cert_handle_->pCertInfo->Subject.cbData); | 159 cert_handle_->pCertInfo->Subject.cbData); |
151 issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData, | 160 issuer_.ParseDistinguishedName(cert_handle_->pCertInfo->Issuer.pbData, |
152 cert_handle_->pCertInfo->Issuer.cbData); | 161 cert_handle_->pCertInfo->Issuer.cbData); |
153 | 162 |
154 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); | 163 valid_start_ = Time::FromFileTime(cert_handle_->pCertInfo->NotBefore); |
155 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); | 164 valid_expiry_ = Time::FromFileTime(cert_handle_->pCertInfo->NotAfter); |
156 | 165 |
157 fingerprint_ = CalculateFingerprint(cert_handle_); | 166 fingerprint_ = CalculateFingerprint(cert_handle_); |
158 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); | 167 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); |
159 | 168 |
160 const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; | 169 const CRYPT_INTEGER_BLOB* serial = &cert_handle_->pCertInfo->SerialNumber; |
161 scoped_ptr<uint8[]> serial_bytes(new uint8[serial->cbData]); | 170 scoped_ptr<uint8[]> serial_bytes(new uint8[serial->cbData]); |
162 for (unsigned i = 0; i < serial->cbData; i++) | 171 for (unsigned i = 0; i < serial->cbData; i++) |
163 serial_bytes[i] = serial->pbData[serial->cbData - i - 1]; | 172 serial_bytes[i] = serial->pbData[serial->cbData - i - 1]; |
164 serial_number_ = std::string( | 173 serial_number_ = |
165 reinterpret_cast<char*>(serial_bytes.get()), serial->cbData); | 174 std::string(reinterpret_cast<char*>(serial_bytes.get()), serial->cbData); |
166 } | 175 } |
167 | 176 |
168 void X509Certificate::GetSubjectAltName( | 177 void X509Certificate::GetSubjectAltName( |
169 std::vector<std::string>* dns_names, | 178 std::vector<std::string>* dns_names, |
170 std::vector<std::string>* ip_addrs) const { | 179 std::vector<std::string>* ip_addrs) const { |
171 if (dns_names) | 180 if (dns_names) |
172 dns_names->clear(); | 181 dns_names->clear(); |
173 if (ip_addrs) | 182 if (ip_addrs) |
174 ip_addrs->clear(); | 183 ip_addrs->clear(); |
175 | 184 |
176 if (!cert_handle_) | 185 if (!cert_handle_) |
177 return; | 186 return; |
178 | 187 |
179 scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info; | 188 scoped_ptr<CERT_ALT_NAME_INFO, base::FreeDeleter> alt_name_info; |
180 GetCertSubjectAltName(cert_handle_, &alt_name_info); | 189 GetCertSubjectAltName(cert_handle_, &alt_name_info); |
181 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get(); | 190 CERT_ALT_NAME_INFO* alt_name = alt_name_info.get(); |
182 if (alt_name) { | 191 if (alt_name) { |
183 int num_entries = alt_name->cAltEntry; | 192 int num_entries = alt_name->cAltEntry; |
184 for (int i = 0; i < num_entries; i++) { | 193 for (int i = 0; i < num_entries; i++) { |
185 // dNSName is an ASN.1 IA5String representing a string of ASCII | 194 // dNSName is an ASN.1 IA5String representing a string of ASCII |
186 // characters, so we can use UTF16ToASCII here. | 195 // characters, so we can use UTF16ToASCII here. |
187 const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i]; | 196 const CERT_ALT_NAME_ENTRY& entry = alt_name->rgAltEntry[i]; |
188 | 197 |
189 if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) { | 198 if (dns_names && entry.dwAltNameChoice == CERT_ALT_NAME_DNS_NAME) { |
190 dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName)); | 199 dns_names->push_back(base::UTF16ToASCII(entry.pwszDNSName)); |
191 } else if (ip_addrs && | 200 } else if (ip_addrs && |
192 entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) { | 201 entry.dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS) { |
193 ip_addrs->push_back(std::string( | 202 ip_addrs->push_back( |
194 reinterpret_cast<const char*>(entry.IPAddress.pbData), | 203 std::string(reinterpret_cast<const char*>(entry.IPAddress.pbData), |
195 entry.IPAddress.cbData)); | 204 entry.IPAddress.cbData)); |
196 } | 205 } |
197 } | 206 } |
198 } | 207 } |
199 } | 208 } |
200 | 209 |
201 PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const { | 210 PCCERT_CONTEXT X509Certificate::CreateOSCertChainForCert() const { |
202 // Create an in-memory certificate store to hold this certificate and | 211 // Create an in-memory certificate store to hold this certificate and |
203 // any intermediate certificates in |intermediate_ca_certs_|. The store | 212 // any intermediate certificates in |intermediate_ca_certs_|. The store |
204 // will be referenced in the returned PCCERT_CONTEXT, and will not be freed | 213 // will be referenced in the returned PCCERT_CONTEXT, and will not be freed |
205 // until the PCCERT_CONTEXT is freed. | 214 // until the PCCERT_CONTEXT is freed. |
206 ScopedHCERTSTORE store(CertOpenStore( | 215 ScopedHCERTSTORE store( |
207 CERT_STORE_PROV_MEMORY, 0, NULL, | 216 CertOpenStore(CERT_STORE_PROV_MEMORY, |
208 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, NULL)); | 217 0, |
| 218 NULL, |
| 219 CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, |
| 220 NULL)); |
209 if (!store.get()) | 221 if (!store.get()) |
210 return NULL; | 222 return NULL; |
211 | 223 |
212 // NOTE: This preserves all of the properties of |os_cert_handle()| except | 224 // NOTE: This preserves all of the properties of |os_cert_handle()| except |
213 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two | 225 // for CERT_KEY_PROV_HANDLE_PROP_ID and CERT_KEY_CONTEXT_PROP_ID - the two |
214 // properties that hold access to already-opened private keys. If a handle | 226 // properties that hold access to already-opened private keys. If a handle |
215 // has already been unlocked (eg: PIN prompt), then the first time that the | 227 // has already been unlocked (eg: PIN prompt), then the first time that the |
216 // identity is used for client auth, it may prompt the user again. | 228 // identity is used for client auth, it may prompt the user again. |
217 PCCERT_CONTEXT primary_cert; | 229 PCCERT_CONTEXT primary_cert; |
218 BOOL ok = CertAddCertificateContextToStore(store.get(), os_cert_handle(), | 230 BOOL ok = CertAddCertificateContextToStore( |
219 CERT_STORE_ADD_ALWAYS, | 231 store.get(), os_cert_handle(), CERT_STORE_ADD_ALWAYS, &primary_cert); |
220 &primary_cert); | |
221 if (!ok || !primary_cert) | 232 if (!ok || !primary_cert) |
222 return NULL; | 233 return NULL; |
223 | 234 |
224 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { | 235 for (size_t i = 0; i < intermediate_ca_certs_.size(); ++i) { |
225 CertAddCertificateContextToStore(store.get(), intermediate_ca_certs_[i], | 236 CertAddCertificateContextToStore( |
226 CERT_STORE_ADD_ALWAYS, NULL); | 237 store.get(), intermediate_ca_certs_[i], CERT_STORE_ADD_ALWAYS, NULL); |
227 } | 238 } |
228 | 239 |
229 // Note: |store| is explicitly not released, as the call to CertCloseStore() | 240 // Note: |store| is explicitly not released, as the call to CertCloseStore() |
230 // when |store| goes out of scope will not actually free the store. Instead, | 241 // when |store| goes out of scope will not actually free the store. Instead, |
231 // the store will be freed when |primary_cert| is freed. | 242 // the store will be freed when |primary_cert| is freed. |
232 return primary_cert; | 243 return primary_cert; |
233 } | 244 } |
234 | 245 |
235 // static | 246 // static |
236 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, | 247 bool X509Certificate::GetDEREncoded(X509Certificate::OSCertHandle cert_handle, |
237 std::string* encoded) { | 248 std::string* encoded) { |
238 if (!cert_handle->pbCertEncoded || !cert_handle->cbCertEncoded) | 249 if (!cert_handle->pbCertEncoded || !cert_handle->cbCertEncoded) |
239 return false; | 250 return false; |
240 encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded), | 251 encoded->assign(reinterpret_cast<char*>(cert_handle->pbCertEncoded), |
241 cert_handle->cbCertEncoded); | 252 cert_handle->cbCertEncoded); |
242 return true; | 253 return true; |
243 } | 254 } |
244 | 255 |
245 // static | 256 // static |
246 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, | 257 bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, |
247 X509Certificate::OSCertHandle b) { | 258 X509Certificate::OSCertHandle b) { |
248 DCHECK(a && b); | 259 DCHECK(a && b); |
249 if (a == b) | 260 if (a == b) |
250 return true; | 261 return true; |
251 return a->cbCertEncoded == b->cbCertEncoded && | 262 return a->cbCertEncoded == b->cbCertEncoded && |
252 memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0; | 263 memcmp(a->pbCertEncoded, b->pbCertEncoded, a->cbCertEncoded) == 0; |
253 } | 264 } |
254 | 265 |
255 // static | 266 // static |
256 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 267 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
257 const char* data, int length) { | 268 const char* data, |
| 269 int length) { |
258 OSCertHandle cert_handle = NULL; | 270 OSCertHandle cert_handle = NULL; |
259 if (!CertAddEncodedCertificateToStore( | 271 if (!CertAddEncodedCertificateToStore(NULL, |
260 NULL, X509_ASN_ENCODING, reinterpret_cast<const BYTE*>(data), | 272 X509_ASN_ENCODING, |
261 length, CERT_STORE_ADD_USE_EXISTING, &cert_handle)) | 273 reinterpret_cast<const BYTE*>(data), |
| 274 length, |
| 275 CERT_STORE_ADD_USE_EXISTING, |
| 276 &cert_handle)) |
262 return NULL; | 277 return NULL; |
263 | 278 |
264 return cert_handle; | 279 return cert_handle; |
265 } | 280 } |
266 | 281 |
267 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( | 282 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
268 const char* data, int length, Format format) { | 283 const char* data, |
| 284 int length, |
| 285 Format format) { |
269 OSCertHandles results; | 286 OSCertHandles results; |
270 switch (format) { | 287 switch (format) { |
271 case FORMAT_SINGLE_CERTIFICATE: { | 288 case FORMAT_SINGLE_CERTIFICATE: { |
272 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); | 289 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); |
273 if (handle != NULL) | 290 if (handle != NULL) |
274 results.push_back(handle); | 291 results.push_back(handle); |
275 break; | 292 break; |
276 } | 293 } |
277 case FORMAT_PKCS7: | 294 case FORMAT_PKCS7: |
278 results = ParsePKCS7(data, length); | 295 results = ParsePKCS7(data, length); |
(...skipping 11 matching lines...) Expand all Loading... |
290 OSCertHandle cert_handle) { | 307 OSCertHandle cert_handle) { |
291 return CertDuplicateCertificateContext(cert_handle); | 308 return CertDuplicateCertificateContext(cert_handle); |
292 } | 309 } |
293 | 310 |
294 // static | 311 // static |
295 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 312 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
296 CertFreeCertificateContext(cert_handle); | 313 CertFreeCertificateContext(cert_handle); |
297 } | 314 } |
298 | 315 |
299 // static | 316 // static |
300 SHA1HashValue X509Certificate::CalculateFingerprint( | 317 SHA1HashValue X509Certificate::CalculateFingerprint(OSCertHandle cert) { |
301 OSCertHandle cert) { | |
302 DCHECK(NULL != cert->pbCertEncoded); | 318 DCHECK(NULL != cert->pbCertEncoded); |
303 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); | 319 DCHECK_NE(static_cast<DWORD>(0), cert->cbCertEncoded); |
304 | 320 |
305 BOOL rv; | 321 BOOL rv; |
306 SHA1HashValue sha1; | 322 SHA1HashValue sha1; |
307 DWORD sha1_size = sizeof(sha1.data); | 323 DWORD sha1_size = sizeof(sha1.data); |
308 rv = CryptHashCertificate(NULL, CALG_SHA1, 0, cert->pbCertEncoded, | 324 rv = CryptHashCertificate(NULL, |
309 cert->cbCertEncoded, sha1.data, &sha1_size); | 325 CALG_SHA1, |
| 326 0, |
| 327 cert->pbCertEncoded, |
| 328 cert->cbCertEncoded, |
| 329 sha1.data, |
| 330 &sha1_size); |
310 DCHECK(rv && sha1_size == sizeof(sha1.data)); | 331 DCHECK(rv && sha1_size == sizeof(sha1.data)); |
311 if (!rv) | 332 if (!rv) |
312 memset(sha1.data, 0, sizeof(sha1.data)); | 333 memset(sha1.data, 0, sizeof(sha1.data)); |
313 return sha1; | 334 return sha1; |
314 } | 335 } |
315 | 336 |
316 // TODO(wtc): This function is implemented with NSS low-level hash | 337 // TODO(wtc): This function is implemented with NSS low-level hash |
317 // functions to ensure it is fast. Reimplement this function with | 338 // functions to ensure it is fast. Reimplement this function with |
318 // CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead. | 339 // CryptoAPI. May need to cache the HCRYPTPROV to reduce the overhead. |
319 // static | 340 // static |
(...skipping 11 matching lines...) Expand all Loading... |
331 SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded); | 352 SHA1_Update(sha1_ctx, ca_cert->pbCertEncoded, ca_cert->cbCertEncoded); |
332 } | 353 } |
333 unsigned int result_len; | 354 unsigned int result_len; |
334 SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH); | 355 SHA1_End(sha1_ctx, sha1.data, &result_len, SHA1_LENGTH); |
335 SHA1_DestroyContext(sha1_ctx, PR_TRUE); | 356 SHA1_DestroyContext(sha1_ctx, PR_TRUE); |
336 | 357 |
337 return sha1; | 358 return sha1; |
338 } | 359 } |
339 | 360 |
340 // static | 361 // static |
341 X509Certificate::OSCertHandle | 362 X509Certificate::OSCertHandle X509Certificate::ReadOSCertHandleFromPickle( |
342 X509Certificate::ReadOSCertHandleFromPickle(PickleIterator* pickle_iter) { | 363 PickleIterator* pickle_iter) { |
343 const char* data; | 364 const char* data; |
344 int length; | 365 int length; |
345 if (!pickle_iter->ReadData(&data, &length)) | 366 if (!pickle_iter->ReadData(&data, &length)) |
346 return NULL; | 367 return NULL; |
347 | 368 |
348 // Legacy serialized certificates were serialized with extended attributes, | 369 // Legacy serialized certificates were serialized with extended attributes, |
349 // rather than as DER only. As a result, these serialized certificates are | 370 // rather than as DER only. As a result, these serialized certificates are |
350 // not portable across platforms and may have side-effects on Windows due | 371 // not portable across platforms and may have side-effects on Windows due |
351 // to extended attributes being serialized/deserialized - | 372 // to extended attributes being serialized/deserialized - |
352 // http://crbug.com/118706. To avoid deserializing these attributes, write | 373 // http://crbug.com/118706. To avoid deserializing these attributes, write |
353 // the deserialized cert into a temporary cert store and then create a new | 374 // the deserialized cert into a temporary cert store and then create a new |
354 // cert from the DER - that is, without attributes. | 375 // cert from the DER - that is, without attributes. |
355 ScopedHCERTSTORE store( | 376 ScopedHCERTSTORE store( |
356 CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)); | 377 CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL)); |
357 if (!store.get()) | 378 if (!store.get()) |
358 return NULL; | 379 return NULL; |
359 | 380 |
360 OSCertHandle cert_handle = NULL; | 381 OSCertHandle cert_handle = NULL; |
361 if (!CertAddSerializedElementToStore( | 382 if (!CertAddSerializedElementToStore( |
362 store.get(), reinterpret_cast<const BYTE*>(data), length, | 383 store.get(), |
363 CERT_STORE_ADD_NEW, 0, CERT_STORE_CERTIFICATE_CONTEXT_FLAG, | 384 reinterpret_cast<const BYTE*>(data), |
364 NULL, reinterpret_cast<const void **>(&cert_handle))) { | 385 length, |
| 386 CERT_STORE_ADD_NEW, |
| 387 0, |
| 388 CERT_STORE_CERTIFICATE_CONTEXT_FLAG, |
| 389 NULL, |
| 390 reinterpret_cast<const void**>(&cert_handle))) { |
365 return NULL; | 391 return NULL; |
366 } | 392 } |
367 | 393 |
368 std::string encoded; | 394 std::string encoded; |
369 bool ok = GetDEREncoded(cert_handle, &encoded); | 395 bool ok = GetDEREncoded(cert_handle, &encoded); |
370 FreeOSCertHandle(cert_handle); | 396 FreeOSCertHandle(cert_handle); |
371 cert_handle = NULL; | 397 cert_handle = NULL; |
372 | 398 |
373 if (ok) | 399 if (ok) |
374 cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size()); | 400 cert_handle = CreateOSCertHandleFromBytes(encoded.data(), encoded.size()); |
375 return cert_handle; | 401 return cert_handle; |
376 } | 402 } |
377 | 403 |
378 // static | 404 // static |
379 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, | 405 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, |
380 Pickle* pickle) { | 406 Pickle* pickle) { |
381 return pickle->WriteData( | 407 return pickle->WriteData(reinterpret_cast<char*>(cert_handle->pbCertEncoded), |
382 reinterpret_cast<char*>(cert_handle->pbCertEncoded), | 408 cert_handle->cbCertEncoded); |
383 cert_handle->cbCertEncoded); | |
384 } | 409 } |
385 | 410 |
386 // static | 411 // static |
387 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, | 412 void X509Certificate::GetPublicKeyInfo(OSCertHandle cert_handle, |
388 size_t* size_bits, | 413 size_t* size_bits, |
389 PublicKeyType* type) { | 414 PublicKeyType* type) { |
390 *type = kPublicKeyTypeUnknown; | 415 *type = kPublicKeyTypeUnknown; |
391 *size_bits = 0; | 416 *size_bits = 0; |
392 | 417 |
393 PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo( | 418 PCCRYPT_OID_INFO oid_info = CryptFindOIDInfo( |
394 CRYPT_OID_INFO_OID_KEY, | 419 CRYPT_OID_INFO_OID_KEY, |
395 cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, | 420 cert_handle->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId, |
396 CRYPT_PUBKEY_ALG_OID_GROUP_ID); | 421 CRYPT_PUBKEY_ALG_OID_GROUP_ID); |
397 if (!oid_info) | 422 if (!oid_info) |
398 return; | 423 return; |
399 | 424 |
400 CHECK_EQ(oid_info->dwGroupId, | 425 CHECK_EQ(oid_info->dwGroupId, |
401 static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID)); | 426 static_cast<DWORD>(CRYPT_PUBKEY_ALG_OID_GROUP_ID)); |
402 | 427 |
403 *size_bits = CertGetPublicKeyLength( | 428 *size_bits = |
404 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, | 429 CertGetPublicKeyLength(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, |
405 &cert_handle->pCertInfo->SubjectPublicKeyInfo); | 430 &cert_handle->pCertInfo->SubjectPublicKeyInfo); |
406 | 431 |
407 if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) { | 432 if (IS_SPECIAL_OID_INFO_ALGID(oid_info->Algid)) { |
408 // For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS | 433 // For an EC public key, oid_info->Algid is CALG_OID_INFO_PARAMETERS |
409 // (0xFFFFFFFE). Need to handle it as a special case. | 434 // (0xFFFFFFFE). Need to handle it as a special case. |
410 if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) { | 435 if (strcmp(oid_info->pszOID, szOID_ECC_PUBLIC_KEY) == 0) { |
411 *type = kPublicKeyTypeECDSA; | 436 *type = kPublicKeyTypeECDSA; |
412 } else { | 437 } else { |
413 NOTREACHED(); | 438 NOTREACHED(); |
414 } | 439 } |
415 return; | 440 return; |
(...skipping 10 matching lines...) Expand all Loading... |
426 *type = kPublicKeyTypeECDSA; | 451 *type = kPublicKeyTypeECDSA; |
427 break; | 452 break; |
428 case CALG_ECDH: | 453 case CALG_ECDH: |
429 *type = kPublicKeyTypeECDH; | 454 *type = kPublicKeyTypeECDH; |
430 break; | 455 break; |
431 } | 456 } |
432 } | 457 } |
433 | 458 |
434 bool X509Certificate::IsIssuedByEncoded( | 459 bool X509Certificate::IsIssuedByEncoded( |
435 const std::vector<std::string>& valid_issuers) { | 460 const std::vector<std::string>& valid_issuers) { |
436 | |
437 // If the certificate's issuer in the list? | 461 // If the certificate's issuer in the list? |
438 if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer, | 462 if (IsCertNameBlobInIssuerList(&cert_handle_->pCertInfo->Issuer, |
439 valid_issuers)) { | 463 valid_issuers)) { |
440 return true; | 464 return true; |
441 } | 465 } |
442 // Otherwise, is any of the intermediate CA subjects in the list? | 466 // Otherwise, is any of the intermediate CA subjects in the list? |
443 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | 467 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); |
444 it != intermediate_ca_certs_.end(); ++it) { | 468 it != intermediate_ca_certs_.end(); |
445 if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer, | 469 ++it) { |
446 valid_issuers)) { | 470 if (IsCertNameBlobInIssuerList(&(*it)->pCertInfo->Issuer, valid_issuers)) { |
447 return true; | 471 return true; |
448 } | 472 } |
449 } | 473 } |
450 | 474 |
451 return false; | 475 return false; |
452 } | 476 } |
453 | 477 |
454 } // namespace net | 478 } // namespace net |
OLD | NEW |