Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(54)

Side by Side Diff: net/base/x509_certificate_mac.cc

Issue 8470012: When accessing certificate fields/extensions on OS X, only parse what is needed. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Review feedback Created 9 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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 <CoreServices/CoreServices.h> 8 #include <CoreServices/CoreServices.h>
9 #include <Security/Security.h> 9 #include <Security/Security.h>
10 #include <time.h> 10 #include <time.h>
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 base::mac::ScopedCFTypeRef<CFStringRef> error_string( 122 base::mac::ScopedCFTypeRef<CFStringRef> error_string(
123 SecCopyErrorMessageString(status, NULL)); 123 SecCopyErrorMessageString(status, NULL));
124 LOG(WARNING) << "Unknown error " << status 124 LOG(WARNING) << "Unknown error " << status
125 << " (" << base::SysCFStringRefToUTF8(error_string) << ")" 125 << " (" << base::SysCFStringRefToUTF8(error_string) << ")"
126 << " mapped to CERT_STATUS_INVALID"; 126 << " mapped to CERT_STATUS_INVALID";
127 return CERT_STATUS_INVALID; 127 return CERT_STATUS_INVALID;
128 } 128 }
129 } 129 }
130 } 130 }
131 131
132 struct CSSMFields { 132 // Wrapper for a CSSM_DATA_PTR that was obtained via one of the CSSM field
133 CSSMFields() : cl_handle(NULL), num_of_fields(0), fields(NULL) {} 133 // accessors (such as CSSM_CL_CertGet[First/Next]Value or
134 ~CSSMFields() { 134 // CSSM_CL_CertGet[First/Next]CachedValue).
135 if (cl_handle) 135 class CSSMFieldValue {
136 CSSM_CL_FreeFields(cl_handle, num_of_fields, &fields); 136 public:
137 CSSMFieldValue() : cl_handle_(NULL), oid_(NULL), field_(NULL) {}
138 CSSMFieldValue(CSSM_CL_HANDLE cl_handle,
139 const CSSM_OID* oid,
140 CSSM_DATA_PTR field)
141 : cl_handle_(cl_handle),
142 oid_(const_cast<CSSM_OID_PTR>(oid)),
143 field_(field) {
137 } 144 }
138 145
139 CSSM_CL_HANDLE cl_handle; 146 ~CSSMFieldValue() {
140 uint32 num_of_fields; 147 Reset(NULL, NULL, NULL);
141 CSSM_FIELD_PTR fields; 148 }
149
150 CSSM_OID_PTR oid() const { return oid_; }
151 CSSM_DATA_PTR field() const { return field_; }
152
153 // Returns the field as if it was an arbitrary type - most commonly, by
154 // interpreting the field as a specific CSSM/CDSA parsed type, such as
155 // CSSM_X509_SUBJECT_PUBLIC_KEY_INFO or CSSM_X509_ALGORITHM_IDENTIFIER.
156 // An added check is applied to ensure that the current field is large
157 // enough to actually contain the requested type.
158 template <typename T> const T* GetAs() const {
159 if (!field_ || field_->Length < sizeof(T))
160 return NULL;
161 return reinterpret_cast<const T*>(field_->Data);
162 }
163
164 void Reset(CSSM_CL_HANDLE cl_handle,
165 CSSM_OID_PTR oid,
166 CSSM_DATA_PTR field) {
167 if (cl_handle_ && oid_ && field_)
168 CSSM_CL_FreeFieldValue(cl_handle_, oid_, field_);
169 cl_handle_ = cl_handle;
170 oid_ = oid;
171 field_ = field;
172 }
173
174 private:
175 CSSM_CL_HANDLE cl_handle_;
176 CSSM_OID_PTR oid_;
177 CSSM_DATA_PTR field_;
178
179 DISALLOW_COPY_AND_ASSIGN(CSSMFieldValue);
142 }; 180 };
143 181
144 OSStatus GetCertFields(X509Certificate::OSCertHandle cert_handle, 182 // CSSMCachedCertificate is a container class that is used to wrap the
145 CSSMFields* fields) { 183 // CSSM_CL_CertCache APIs and provide safe and efficient access to
146 DCHECK(cert_handle); 184 // certificate fields in their CSSM form.
147 DCHECK(fields); 185 //
186 // To provide efficient access to certificate/CRL fields, CSSM provides an
187 // API/SPI to "cache" a certificate/CRL. The exact meaning of a cached
188 // certificate is not defined by CSSM, but is documented to generally be some
189 // intermediate or parsed form of the certificate. In the case of Apple's
190 // CSSM CL implementation, the intermediate form is the parsed certificate
191 // stored in an internal format (which happens to be NSS). By caching the
192 // certificate, callers that wish to access multiple fields (such as subject,
193 // issuer, and validity dates) do not need to repeatedly parse the entire
194 // certificate, nor are they forced to convert all fields from their NSS types
195 // to their CSSM equivalents. This latter point is especially helpful when
196 // running on OS X 10.5, as it will fail to convert some fields that reference
197 // unsupported algorithms, such as ECC.
198 class CSSMCachedCertificate {
199 public:
200 CSSMCachedCertificate() : cl_handle_(NULL), cached_cert_handle_(NULL) {}
201 ~CSSMCachedCertificate() {
202 if (cl_handle_ && cached_cert_handle_)
203 CSSM_CL_CertAbortCache(cl_handle_, cached_cert_handle_);
204 }
148 205
149 CSSM_DATA cert_data; 206 // Initializes the CSSMCachedCertificate by caching the specified
150 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); 207 // |os_cert_handle|. On success, returns noErr.
151 if (status) 208 // Note: Once initialized, the cached certificate should only be accessed
152 return status; 209 // from a single thread.
210 OSStatus Init(SecCertificateRef os_cert_handle) {
211 DCHECK(!cl_handle_ && !cached_cert_handle_);
212 DCHECK(os_cert_handle);
213 CSSM_DATA cert_data;
214 OSStatus status = SecCertificateGetData(os_cert_handle, &cert_data);
215 if (status)
216 return status;
217 status = SecCertificateGetCLHandle(os_cert_handle, &cl_handle_);
218 if (status) {
219 DCHECK(!cl_handle_);
220 return status;
221 }
153 222
154 status = SecCertificateGetCLHandle(cert_handle, &fields->cl_handle); 223 status = CSSM_CL_CertCache(cl_handle_, &cert_data, &cached_cert_handle_);
155 if (status) { 224 if (status)
156 DCHECK(!fields->cl_handle); 225 DCHECK(!cached_cert_handle_);
157 return status; 226 return status;
158 } 227 }
159 228
160 status = CSSM_CL_CertGetAllFields(fields->cl_handle, &cert_data, 229 // Fetches the first value for the field associated with |field_oid|.
161 &fields->num_of_fields, &fields->fields); 230 // If |field_oid| is a valid OID and is present in the current certificate,
162 return status; 231 // returns CSSM_OK and stores the first value in |field|. If additional
163 } 232 // values are associated with |field_oid|, they are ignored.
233 OSStatus GetField(const CSSM_OID* field_oid,
234 CSSMFieldValue* field) const {
235 DCHECK(cl_handle_);
236 DCHECK(cached_cert_handle_);
164 237
165 void GetCertDateForOID(X509Certificate::OSCertHandle cert_handle, 238 CSSM_OID_PTR oid = const_cast<CSSM_OID_PTR>(field_oid);
166 CSSM_OID oid, Time* result) { 239 CSSM_DATA_PTR field_ptr = NULL;
240 CSSM_HANDLE results_handle = NULL;
241 uint32 field_value_count = 0;
242 CSSM_RETURN status = CSSM_CL_CertGetFirstCachedFieldValue(
243 cl_handle_, cached_cert_handle_, oid, &results_handle,
244 &field_value_count, &field_ptr);
245 if (status)
246 return status;
247
248 // Note: |field_value_count| may be > 1, indicating that more than one
249 // value is present. This may happen with extensions, but for current
250 // usages, only the first value is returned.
251 CSSM_CL_CertAbortQuery(cl_handle_, results_handle);
252 field->Reset(cl_handle_, oid, field_ptr);
253 return CSSM_OK;
254 }
255
256 private:
257 CSSM_CL_HANDLE cl_handle_;
258 CSSM_HANDLE cached_cert_handle_;
259 };
260
261 void GetCertDateForOID(const CSSMCachedCertificate& cached_cert,
262 const CSSM_OID* oid,
263 Time* result) {
167 *result = Time::Time(); 264 *result = Time::Time();
168 265
169 CSSMFields fields; 266 CSSMFieldValue field;
170 OSStatus status = GetCertFields(cert_handle, &fields); 267 OSStatus status = cached_cert.GetField(oid, &field);
171 if (status) 268 if (status)
172 return; 269 return;
173 270
174 for (size_t field = 0; field < fields.num_of_fields; ++field) { 271 const CSSM_X509_TIME* x509_time = field.GetAs<CSSM_X509_TIME>();
175 if (CSSMOIDEqual(&fields.fields[field].FieldOid, &oid)) { 272 if (x509_time->timeType != BER_TAG_UTC_TIME &&
176 CSSM_X509_TIME* x509_time = reinterpret_cast<CSSM_X509_TIME*>( 273 x509_time->timeType != BER_TAG_GENERALIZED_TIME) {
177 fields.fields[field].FieldValue.Data); 274 LOG(ERROR) << "Unsupported date/time format "
178 if (x509_time->timeType != BER_TAG_UTC_TIME && 275 << x509_time->timeType;
179 x509_time->timeType != BER_TAG_GENERALIZED_TIME) { 276 return;
180 LOG(ERROR) << "Unsupported date/time format " 277 }
181 << x509_time->timeType;
182 return;
183 }
184 278
185 base::StringPiece time_string( 279 base::StringPiece time_string(
186 reinterpret_cast<const char*>(x509_time->time.Data), 280 reinterpret_cast<const char*>(x509_time->time.Data),
187 x509_time->time.Length); 281 x509_time->time.Length);
188 CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ? 282 CertDateFormat format = x509_time->timeType == BER_TAG_UTC_TIME ?
189 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME; 283 CERT_DATE_FORMAT_UTC_TIME : CERT_DATE_FORMAT_GENERALIZED_TIME;
190 if (!ParseCertificateDate(time_string, format, result)) 284 if (!ParseCertificateDate(time_string, format, result))
191 LOG(ERROR) << "Invalid certificate date/time " << time_string; 285 LOG(ERROR) << "Invalid certificate date/time " << time_string;
192 return;
193 }
194 }
195 } 286 }
196 287
197 std::string GetCertSerialNumber(X509Certificate::OSCertHandle cert_handle) { 288 std::string GetCertSerialNumber(const CSSMCachedCertificate& cached_cert) {
198 CSSMFields fields; 289 CSSMFieldValue serial_number;
199 OSStatus status = GetCertFields(cert_handle, &fields); 290 OSStatus status = cached_cert.GetField(&CSSMOID_X509V1SerialNumber,
200 if (status) 291 &serial_number);
201 return ""; 292 if (status || !serial_number.field())
293 return std::string();
202 294
203 std::string ret; 295 return std::string(
204 for (size_t field = 0; field < fields.num_of_fields; ++field) { 296 reinterpret_cast<const char*>(serial_number.field()->Data),
205 if (!CSSMOIDEqual(&fields.fields[field].FieldOid, 297 serial_number.field()->Length);
206 &CSSMOID_X509V1SerialNumber)) {
207 continue;
208 }
209 ret.assign(
210 reinterpret_cast<char*>(fields.fields[field].FieldValue.Data),
211 fields.fields[field].FieldValue.Length);
212 break;
213 }
214
215 return ret;
216 } 298 }
217 299
218 // Creates a SecPolicyRef for the given OID, with optional value. 300 // Creates a SecPolicyRef for the given OID, with optional value.
219 OSStatus CreatePolicy(const CSSM_OID* policy_OID, 301 OSStatus CreatePolicy(const CSSM_OID* policy_oid,
220 void* option_data, 302 void* option_data,
221 size_t option_length, 303 size_t option_length,
222 SecPolicyRef* policy) { 304 SecPolicyRef* policy) {
223 SecPolicySearchRef search; 305 SecPolicySearchRef search;
224 OSStatus err = SecPolicySearchCreate(CSSM_CERT_X_509v3, policy_OID, NULL, 306 OSStatus err = SecPolicySearchCreate(CSSM_CERT_X_509v3, policy_oid, NULL,
225 &search); 307 &search);
226 if (err) 308 if (err)
227 return err; 309 return err;
228 err = SecPolicySearchCopyNext(search, policy); 310 err = SecPolicySearchCopyNext(search, policy);
229 CFRelease(search); 311 CFRelease(search);
230 if (err) 312 if (err)
231 return err; 313 return err;
232 314
233 if (option_data) { 315 if (option_data) {
234 CSSM_DATA options_data = { 316 CSSM_DATA options_data = {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 if ((chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_IN_ANCHORS) || 397 if ((chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_IN_ANCHORS) ||
316 (chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_ROOT)) { 398 (chain_info[i].StatusBits & CSSM_CERT_STATUS_IS_ROOT)) {
317 // The current certificate is either in the user's trusted store or is 399 // The current certificate is either in the user's trusted store or is
318 // a root (self-signed) certificate. Ignore the signature algorithm for 400 // a root (self-signed) certificate. Ignore the signature algorithm for
319 // these certificates, as it is meaningless for security. We allow 401 // these certificates, as it is meaningless for security. We allow
320 // self-signed certificates (i == 0 & IS_ROOT), since we accept that 402 // self-signed certificates (i == 0 & IS_ROOT), since we accept that
321 // any security assertions by such a cert are inherently meaningless. 403 // any security assertions by such a cert are inherently meaningless.
322 continue; 404 continue;
323 } 405 }
324 406
325 CSSMFields cssm_fields; 407 CSSMCachedCertificate cached_cert;
326 OSStatus status = GetCertFields(chain_cert, &cssm_fields); 408 OSStatus status = cached_cert.Init(chain_cert);
327 if (status) 409 if (status)
328 continue; 410 continue;
329 CSSM_FIELD_PTR fields = cssm_fields.fields; 411 CSSMFieldValue signature_field;
330 for (size_t field = 0; field < cssm_fields.num_of_fields; ++field) { 412 status = cached_cert.GetField(&CSSMOID_X509V1SignatureAlgorithm,
331 if (!CSSMOIDEqual(&fields[field].FieldOid, 413 &signature_field);
332 &CSSMOID_X509V1SignatureAlgorithm)) { 414 if (status || !signature_field.field())
333 continue; 415 continue;
334 } 416 // Match the behaviour of OS X system tools and defensively check that
417 // sizes are appropriate. This would indicate a critical failure of the
418 // OS X certificate library, but based on history, it is best to play it
419 // safe.
420 const CSSM_X509_ALGORITHM_IDENTIFIER* sig_algorithm =
421 signature_field.GetAs<CSSM_X509_ALGORITHM_IDENTIFIER>();
422 if (!sig_algorithm)
423 continue;
335 424
336 CSSM_X509_ALGORITHM_IDENTIFIER* signature_algorithm = 425 const CSSM_OID* alg_oid = &sig_algorithm->algorithm;
337 reinterpret_cast<CSSM_X509_ALGORITHM_IDENTIFIER*>( 426 if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) {
338 fields[field].FieldValue.Data); 427 verify_result->has_md2 = true;
339 // Match the behaviour of OS X system tools and defensively check that 428 if (i != 0)
340 // sizes are appropriate. This would indicate a critical failure of the 429 verify_result->has_md2_ca = true;
341 // OS X certificate library, but based on history, it is best to play it 430 } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) {
342 // safe. 431 verify_result->has_md4 = true;
343 if (!signature_algorithm || (fields[field].FieldValue.Length != 432 } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) {
344 sizeof(CSSM_X509_ALGORITHM_IDENTIFIER))) { 433 verify_result->has_md5 = true;
345 break; 434 if (i != 0)
346 } 435 verify_result->has_md5_ca = true;
347 CSSM_OID_PTR alg_oid = &signature_algorithm->algorithm;
348 if (CSSMOIDEqual(alg_oid, &CSSMOID_MD2WithRSA)) {
349 verify_result->has_md2 = true;
350 if (i != 0)
351 verify_result->has_md2_ca = true;
352 } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD4WithRSA)) {
353 verify_result->has_md4 = true;
354 } else if (CSSMOIDEqual(alg_oid, &CSSMOID_MD5WithRSA)) {
355 verify_result->has_md5 = true;
356 if (i != 0)
357 verify_result->has_md5_ca = true;
358 }
359 break;
360 } 436 }
361 } 437 }
362 if (!verified_cert) 438 if (!verified_cert)
363 return; 439 return;
364 440
365 verify_result->verified_cert = 441 verify_result->verified_cert =
366 X509Certificate::CreateFromHandle(verified_cert, verified_chain); 442 X509Certificate::CreateFromHandle(verified_cert, verified_chain);
367 } 443 }
368 444
369 // Gets the issuer for a given cert, starting with the cert itself and 445 // Gets the issuer for a given cert, starting with the cert itself and
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 void X509Certificate::Initialize() { 679 void X509Certificate::Initialize() {
604 const CSSM_X509_NAME* name; 680 const CSSM_X509_NAME* name;
605 OSStatus status = SecCertificateGetSubject(cert_handle_, &name); 681 OSStatus status = SecCertificateGetSubject(cert_handle_, &name);
606 if (!status) 682 if (!status)
607 subject_.Parse(name); 683 subject_.Parse(name);
608 684
609 status = SecCertificateGetIssuer(cert_handle_, &name); 685 status = SecCertificateGetIssuer(cert_handle_, &name);
610 if (!status) 686 if (!status)
611 issuer_.Parse(name); 687 issuer_.Parse(name);
612 688
613 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotBefore, 689 CSSMCachedCertificate cached_cert;
614 &valid_start_); 690 if (cached_cert.Init(cert_handle_) == CSSM_OK) {
615 GetCertDateForOID(cert_handle_, CSSMOID_X509V1ValidityNotAfter, 691 GetCertDateForOID(cached_cert, &CSSMOID_X509V1ValidityNotBefore,
616 &valid_expiry_); 692 &valid_start_);
693 GetCertDateForOID(cached_cert, &CSSMOID_X509V1ValidityNotAfter,
694 &valid_expiry_);
695 serial_number_ = GetCertSerialNumber(cached_cert);
696 }
617 697
618 fingerprint_ = CalculateFingerprint(cert_handle_); 698 fingerprint_ = CalculateFingerprint(cert_handle_);
619 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_); 699 ca_fingerprint_ = CalculateCAFingerprint(intermediate_ca_certs_);
620 serial_number_ = GetCertSerialNumber(cert_handle_);
621 } 700 }
622 701
623 // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA 702 // IsIssuedByKnownRoot returns true if the given chain is rooted at a root CA
624 // that we recognise as a standard root. 703 // that we recognise as a standard root.
625 // static 704 // static
626 bool X509Certificate::IsIssuedByKnownRoot(CFArrayRef chain) { 705 bool X509Certificate::IsIssuedByKnownRoot(CFArrayRef chain) {
627 int n = CFArrayGetCount(chain); 706 int n = CFArrayGetCount(chain);
628 if (n < 1) 707 if (n < 1)
629 return false; 708 return false;
630 SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>( 709 SecCertificateRef root_ref = reinterpret_cast<SecCertificateRef>(
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after
773 } 852 }
774 853
775 void X509Certificate::GetSubjectAltName( 854 void X509Certificate::GetSubjectAltName(
776 std::vector<std::string>* dns_names, 855 std::vector<std::string>* dns_names,
777 std::vector<std::string>* ip_addrs) const { 856 std::vector<std::string>* ip_addrs) const {
778 if (dns_names) 857 if (dns_names)
779 dns_names->clear(); 858 dns_names->clear();
780 if (ip_addrs) 859 if (ip_addrs)
781 ip_addrs->clear(); 860 ip_addrs->clear();
782 861
783 CSSMFields fields; 862 CSSMCachedCertificate cached_cert;
784 OSStatus status = GetCertFields(cert_handle_, &fields); 863 OSStatus status = cached_cert.Init(cert_handle_);
785 if (status) 864 if (status)
786 return; 865 return;
866 CSSMFieldValue subject_alt_name;
867 status = cached_cert.GetField(&CSSMOID_SubjectAltName, &subject_alt_name);
868 if (status || !subject_alt_name.field())
869 return;
870 const CSSM_X509_EXTENSION* cssm_ext =
871 subject_alt_name.GetAs<CSSM_X509_EXTENSION>();
872 if (!cssm_ext || !cssm_ext->value.parsedValue)
873 return;
874 const CE_GeneralNames* alt_name =
875 reinterpret_cast<const CE_GeneralNames*>(cssm_ext->value.parsedValue);
787 876
788 for (size_t field = 0; field < fields.num_of_fields; ++field) { 877 for (size_t name = 0; name < alt_name->numNames; ++name) {
789 if (!CSSMOIDEqual(&fields.fields[field].FieldOid, &CSSMOID_SubjectAltName)) 878 const CE_GeneralName& name_struct = alt_name->generalName[name];
790 continue; 879 const CSSM_DATA& name_data = name_struct.name;
791 CSSM_X509_EXTENSION_PTR cssm_ext = 880 // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs
792 reinterpret_cast<CSSM_X509_EXTENSION_PTR>( 881 // respectively, both of which can be byte copied from
793 fields.fields[field].FieldValue.Data); 882 // CSSM_DATA::data into the appropriate output vector.
794 CE_GeneralNames* alt_name = 883 if (dns_names && name_struct.nameType == GNT_DNSName) {
795 reinterpret_cast<CE_GeneralNames*>(cssm_ext->value.parsedValue); 884 dns_names->push_back(std::string(
796 885 reinterpret_cast<const char*>(name_data.Data),
797 for (size_t name = 0; name < alt_name->numNames; ++name) { 886 name_data.Length));
798 const CE_GeneralName& name_struct = alt_name->generalName[name]; 887 } else if (ip_addrs && name_struct.nameType == GNT_IPAddress) {
799 const CSSM_DATA& name_data = name_struct.name; 888 ip_addrs->push_back(std::string(
800 // DNSName and IPAddress are encoded as IA5String and OCTET STRINGs 889 reinterpret_cast<const char*>(name_data.Data),
801 // respectively, both of which can be byte copied from 890 name_data.Length));
802 // CSSM_DATA::data into the appropriate output vector.
803 if (dns_names && name_struct.nameType == GNT_DNSName) {
804 dns_names->push_back(std::string(
805 reinterpret_cast<const char*>(name_data.Data),
806 name_data.Length));
807 } else if (ip_addrs && name_struct.nameType == GNT_IPAddress) {
808 ip_addrs->push_back(std::string(
809 reinterpret_cast<const char*>(name_data.Data),
810 name_data.Length));
811 }
812 } 891 }
813 } 892 }
814 } 893 }
815 894
816 int X509Certificate::VerifyInternal(const std::string& hostname, 895 int X509Certificate::VerifyInternal(const std::string& hostname,
817 int flags, 896 int flags,
818 CRLSet* crl_set, 897 CRLSet* crl_set,
819 CertVerifyResult* verify_result) const { 898 CertVerifyResult* verify_result) const {
820 ScopedCFTypeRef<CFArrayRef> trust_policies; 899 ScopedCFTypeRef<CFArrayRef> trust_policies;
821 OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies); 900 OSStatus status = CreateTrustPolicies(hostname, flags, &trust_policies);
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
1140 if (status) 1219 if (status)
1141 return sha1; 1220 return sha1;
1142 CC_SHA1_Update(&sha1_ctx, cert_data.Data, cert_data.Length); 1221 CC_SHA1_Update(&sha1_ctx, cert_data.Data, cert_data.Length);
1143 } 1222 }
1144 CC_SHA1_Final(sha1.data, &sha1_ctx); 1223 CC_SHA1_Final(sha1.data, &sha1_ctx);
1145 1224
1146 return sha1; 1225 return sha1;
1147 } 1226 }
1148 1227
1149 bool X509Certificate::SupportsSSLClientAuth() const { 1228 bool X509Certificate::SupportsSSLClientAuth() const {
1150 CSSMFields fields; 1229 CSSMCachedCertificate cached_cert;
1151 if (GetCertFields(cert_handle_, &fields) != noErr) 1230 OSStatus status = cached_cert.Init(cert_handle_);
1231 if (status)
1152 return false; 1232 return false;
1153 1233
1154 // Gather the extensions we care about. We do not support
1155 // CSSMOID_NetscapeCertType on OS X.
1156 const CE_ExtendedKeyUsage* ext_key_usage = NULL;
1157 const CE_KeyUsage* key_usage = NULL;
1158 for (unsigned f = 0; f < fields.num_of_fields; ++f) {
1159 const CSSM_FIELD& field = fields.fields[f];
1160 const CSSM_X509_EXTENSION* ext =
1161 reinterpret_cast<const CSSM_X509_EXTENSION*>(field.FieldValue.Data);
1162 if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_KeyUsage)) {
1163 key_usage = reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue);
1164 } else if (CSSMOIDEqual(&field.FieldOid, &CSSMOID_ExtendedKeyUsage)) {
1165 ext_key_usage =
1166 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
1167 }
1168 }
1169
1170 // RFC5280 says to take the intersection of the two extensions. 1234 // RFC5280 says to take the intersection of the two extensions.
1171 // 1235 //
1172 // Our underlying crypto libraries don't expose 1236 // Our underlying crypto libraries don't expose
1173 // ClientCertificateType, so for now we will not support fixed 1237 // ClientCertificateType, so for now we will not support fixed
1174 // Diffie-Hellman mechanisms. For rsa_sign, we need the 1238 // Diffie-Hellman mechanisms. For rsa_sign, we need the
1175 // digitalSignature bit. 1239 // digitalSignature bit.
1176 // 1240 //
1177 // In particular, if a key has the nonRepudiation bit and not the 1241 // In particular, if a key has the nonRepudiation bit and not the
1178 // digitalSignature one, we will not offer it to the user. 1242 // digitalSignature one, we will not offer it to the user.
1179 if (key_usage && !((*key_usage) & CE_KU_DigitalSignature)) 1243 CSSMFieldValue key_usage;
1180 return false; 1244 status = cached_cert.GetField(&CSSMOID_KeyUsage, &key_usage);
1181 if (ext_key_usage && !ExtendedKeyUsageAllows(ext_key_usage, 1245 if (status == CSSM_OK && key_usage.field()) {
1182 &CSSMOID_ClientAuth)) 1246 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
1183 return false; 1247 const CE_KeyUsage* key_usage_value =
1248 reinterpret_cast<const CE_KeyUsage*>(ext->value.parsedValue);
1249 if (!((*key_usage_value) & CE_KU_DigitalSignature))
1250 return false;
1251 }
1252
1253 status = cached_cert.GetField(&CSSMOID_ExtendedKeyUsage, &key_usage);
1254 if (status == CSSM_OK && key_usage.field()) {
1255 const CSSM_X509_EXTENSION* ext = key_usage.GetAs<CSSM_X509_EXTENSION>();
1256 const CE_ExtendedKeyUsage* ext_key_usage =
1257 reinterpret_cast<const CE_ExtendedKeyUsage*>(ext->value.parsedValue);
1258 if (!ExtendedKeyUsageAllows(ext_key_usage, &CSSMOID_ClientAuth))
1259 return false;
1260 }
1184 return true; 1261 return true;
1185 } 1262 }
1186 1263
1187 bool X509Certificate::IsIssuedBy( 1264 bool X509Certificate::IsIssuedBy(
1188 const std::vector<CertPrincipal>& valid_issuers) { 1265 const std::vector<CertPrincipal>& valid_issuers) {
1189 // Get the cert's issuer chain. 1266 // Get the cert's issuer chain.
1190 CFArrayRef cert_chain = NULL; 1267 CFArrayRef cert_chain = NULL;
1191 OSStatus result; 1268 OSStatus result;
1192 result = CopyCertChain(os_cert_handle(), &cert_chain); 1269 result = CopyCertChain(os_cert_handle(), &cert_chain);
1193 if (result) 1270 if (result)
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 CSSM_DATA cert_data; 1508 CSSM_DATA cert_data;
1432 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); 1509 OSStatus status = SecCertificateGetData(cert_handle, &cert_data);
1433 if (status) 1510 if (status)
1434 return false; 1511 return false;
1435 1512
1436 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), 1513 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data),
1437 cert_data.Length); 1514 cert_data.Length);
1438 } 1515 }
1439 1516
1440 } // namespace net 1517 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698