| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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/base/x509_certificate.h" | 5 #include "net/base/x509_certificate.h" |
| 6 | 6 |
| 7 #include <CommonCrypto/CommonDigest.h> | 7 #include <CommonCrypto/CommonDigest.h> |
| 8 #include <time.h> | 8 #include <time.h> |
| 9 | 9 |
| 10 #include "base/histogram.h" | |
| 11 #include "base/logging.h" | 10 #include "base/logging.h" |
| 12 #include "base/pickle.h" | 11 #include "base/pickle.h" |
| 13 #include "net/base/cert_status_flags.h" | 12 #include "net/base/cert_status_flags.h" |
| 14 #include "net/base/ev_root_ca_metadata.h" | 13 #include "net/base/ev_root_ca_metadata.h" |
| 15 | 14 |
| 16 using base::Time; | 15 using base::Time; |
| 17 | 16 |
| 18 namespace net { | 17 namespace net { |
| 19 | 18 |
| 20 namespace { | 19 namespace { |
| 21 | 20 |
| 22 // Calculates the SHA-1 fingerprint of the certificate. Returns an empty | |
| 23 // (all zero) fingerprint on failure. | |
| 24 X509Certificate::Fingerprint CalculateFingerprint( | |
| 25 X509Certificate::OSCertHandle cert) { | |
| 26 X509Certificate::Fingerprint sha1; | |
| 27 memset(sha1.data, 0, sizeof(sha1.data)); | |
| 28 | |
| 29 CSSM_DATA cert_data; | |
| 30 OSStatus status = SecCertificateGetData(cert, &cert_data); | |
| 31 if (status) | |
| 32 return sha1; | |
| 33 | |
| 34 DCHECK(NULL != cert_data.Data); | |
| 35 DCHECK(0 != cert_data.Length); | |
| 36 | |
| 37 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); | |
| 38 | |
| 39 return sha1; | |
| 40 } | |
| 41 | |
| 42 inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) { | 21 inline bool CSSMOIDEqual(const CSSM_OID* oid1, const CSSM_OID* oid2) { |
| 43 return oid1->Length == oid2->Length && | 22 return oid1->Length == oid2->Length && |
| 44 (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0); | 23 (memcmp(oid1->Data, oid2->Data, oid1->Length) == 0); |
| 45 } | 24 } |
| 46 | 25 |
| 47 void ParsePrincipal(const CSSM_X509_NAME* name, | 26 void ParsePrincipal(const CSSM_X509_NAME* name, |
| 48 X509Certificate::Principal* principal) { | 27 X509Certificate::Principal* principal) { |
| 49 std::vector<std::string> common_names, locality_names, state_names, | 28 std::vector<std::string> common_names, locality_names, state_names, |
| 50 country_names; | 29 country_names; |
| 51 | 30 |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, | 214 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, |
| 236 &valid_expiry_); | 215 &valid_expiry_); |
| 237 | 216 |
| 238 fingerprint_ = CalculateFingerprint(cert_handle_); | 217 fingerprint_ = CalculateFingerprint(cert_handle_); |
| 239 | 218 |
| 240 // Store the certificate in the cache in case we need it later. | 219 // Store the certificate in the cache in case we need it later. |
| 241 X509Certificate::Cache::GetInstance()->Insert(this); | 220 X509Certificate::Cache::GetInstance()->Insert(this); |
| 242 } | 221 } |
| 243 | 222 |
| 244 // static | 223 // static |
| 245 X509Certificate* X509Certificate::CreateFromHandle(OSCertHandle cert_handle) { | |
| 246 DCHECK(cert_handle); | |
| 247 | |
| 248 // Check if we already have this certificate in memory. | |
| 249 X509Certificate::Cache* cache = X509Certificate::Cache::GetInstance(); | |
| 250 X509Certificate* cert = cache->Find(CalculateFingerprint(cert_handle)); | |
| 251 if (cert) { | |
| 252 // We've found a certificate with the same fingerprint in our cache. We own | |
| 253 // the |cert_handle|, which makes it our job to free it. | |
| 254 CFRelease(cert_handle); | |
| 255 DHISTOGRAM_COUNTS(L"X509CertificateReuseCount", 1); | |
| 256 return cert; | |
| 257 } | |
| 258 // Otherwise, allocate a new object. | |
| 259 return new X509Certificate(cert_handle); | |
| 260 } | |
| 261 | |
| 262 // static | |
| 263 X509Certificate* X509Certificate::CreateFromBytes(const char* data, | |
| 264 int length) { | |
| 265 CSSM_DATA cert_data; | |
| 266 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); | |
| 267 cert_data.Length = length; | |
| 268 | |
| 269 OSCertHandle cert_handle = NULL; | |
| 270 OSStatus status = SecCertificateCreateFromData(&cert_data, | |
| 271 CSSM_CERT_X_509v3, | |
| 272 CSSM_CERT_ENCODING_BER, | |
| 273 &cert_handle); | |
| 274 if (status) | |
| 275 return NULL; | |
| 276 | |
| 277 return CreateFromHandle(cert_handle); | |
| 278 } | |
| 279 | |
| 280 // static | |
| 281 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | 224 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, |
| 282 void** pickle_iter) { | 225 void** pickle_iter) { |
| 283 const char* data; | 226 const char* data; |
| 284 int length; | 227 int length; |
| 285 if (!pickle.ReadData(pickle_iter, &data, &length)) | 228 if (!pickle.ReadData(pickle_iter, &data, &length)) |
| 286 return NULL; | 229 return NULL; |
| 287 | 230 |
| 288 return CreateFromBytes(data, length); | 231 return CreateFromBytes(data, length); |
| 289 } | 232 } |
| 290 | 233 |
| 291 X509Certificate::X509Certificate(OSCertHandle cert_handle) | |
| 292 : cert_handle_(cert_handle) { | |
| 293 Initialize(); | |
| 294 } | |
| 295 | |
| 296 X509Certificate::X509Certificate(std::string subject, std::string issuer, | |
| 297 Time start_date, Time expiration_date) | |
| 298 : subject_(subject), | |
| 299 issuer_(issuer), | |
| 300 valid_start_(start_date), | |
| 301 valid_expiry_(expiration_date), | |
| 302 cert_handle_(NULL) { | |
| 303 memset(fingerprint_.data, 0, sizeof(fingerprint_.data)); | |
| 304 } | |
| 305 | |
| 306 void X509Certificate::Persist(Pickle* pickle) { | 234 void X509Certificate::Persist(Pickle* pickle) { |
| 307 CSSM_DATA cert_data; | 235 CSSM_DATA cert_data; |
| 308 OSStatus status = SecCertificateGetData(cert_handle_, &cert_data); | 236 OSStatus status = SecCertificateGetData(cert_handle_, &cert_data); |
| 309 if (status) { | 237 if (status) { |
| 310 NOTREACHED(); | 238 NOTREACHED(); |
| 311 return; | 239 return; |
| 312 } | 240 } |
| 313 | 241 |
| 314 pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), cert_data.Length); | 242 pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), cert_data.Length); |
| 315 } | 243 } |
| 316 | 244 |
| 317 X509Certificate::~X509Certificate() { | |
| 318 // We might not be in the cache, but it is safe to remove ourselves anyway. | |
| 319 X509Certificate::Cache::GetInstance()->Remove(this); | |
| 320 if (cert_handle_) | |
| 321 CFRelease(cert_handle_); | |
| 322 } | |
| 323 | |
| 324 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { | 245 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { |
| 325 dns_names->clear(); | 246 dns_names->clear(); |
| 326 | 247 |
| 327 GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName, | 248 GetCertGeneralNamesForOID(cert_handle_, CSSMOID_SubjectAltName, GNT_DNSName, |
| 328 dns_names); | 249 dns_names); |
| 329 | 250 |
| 330 if (dns_names->empty()) | 251 if (dns_names->empty()) |
| 331 dns_names->push_back(subject_.common_name); | 252 dns_names->push_back(subject_.common_name); |
| 332 } | 253 } |
| 333 | 254 |
| 334 // Returns true if the certificate is an extended-validation certificate. | 255 // Returns true if the certificate is an extended-validation certificate. |
| 335 // | 256 // |
| 336 // The certificate has already been verified by the HTTP library. cert_status | 257 // The certificate has already been verified by the HTTP library. cert_status |
| 337 // represents the result of that verification. This function performs | 258 // represents the result of that verification. This function performs |
| 338 // additional checks of the certificatePolicies extensions of the certificates | 259 // additional checks of the certificatePolicies extensions of the certificates |
| 339 // in the certificate chain according to Section 7 (pp. 11-12) of the EV | 260 // in the certificate chain according to Section 7 (pp. 11-12) of the EV |
| 340 // Certificate Guidelines Version 1.0 at | 261 // Certificate Guidelines Version 1.0 at |
| 341 // http://cabforum.org/EV_Certificate_Guidelines.pdf. | 262 // http://cabforum.org/EV_Certificate_Guidelines.pdf. |
| 342 bool X509Certificate::IsEV(int cert_status) const { | 263 bool X509Certificate::IsEV(int cert_status) const { |
| 343 // TODO(avi): implement this | 264 // TODO(avi): implement this |
| 344 NOTIMPLEMENTED(); | 265 NOTIMPLEMENTED(); |
| 345 return false; | 266 return false; |
| 346 } | 267 } |
| 347 | 268 |
| 269 // static |
| 270 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
| 271 const char* data, int length) { |
| 272 CSSM_DATA cert_data; |
| 273 cert_data.Data = const_cast<uint8*>(reinterpret_cast<const uint8*>(data)); |
| 274 cert_data.Length = length; |
| 275 |
| 276 OSCertHandle cert_handle = NULL; |
| 277 OSStatus status = SecCertificateCreateFromData(&cert_data, |
| 278 CSSM_CERT_X_509v3, |
| 279 CSSM_CERT_ENCODING_BER, |
| 280 &cert_handle); |
| 281 if (status) |
| 282 return NULL; |
| 283 |
| 284 return cert_handle; |
| 285 } |
| 286 |
| 287 // static |
| 288 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
| 289 CFRelease(cert_handle); |
| 290 } |
| 291 |
| 292 // static |
| 293 X509Certificate::Fingerprint X509Certificate::CalculateFingerprint( |
| 294 OSCertHandle cert) { |
| 295 Fingerprint sha1; |
| 296 memset(sha1.data, 0, sizeof(sha1.data)); |
| 297 |
| 298 CSSM_DATA cert_data; |
| 299 OSStatus status = SecCertificateGetData(cert, &cert_data); |
| 300 if (status) |
| 301 return sha1; |
| 302 |
| 303 DCHECK(NULL != cert_data.Data); |
| 304 DCHECK(0 != cert_data.Length); |
| 305 |
| 306 CC_SHA1(cert_data.Data, cert_data.Length, sha1.data); |
| 307 |
| 308 return sha1; |
| 309 } |
| 310 |
| 348 } // namespace net | 311 } // namespace net |
| OLD | NEW |