Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 297 OSStatus CreateTrustPolicies(const std::string& hostname, int flags, | 297 OSStatus CreateTrustPolicies(const std::string& hostname, int flags, |
| 298 ScopedCFTypeRef<CFArrayRef>* policies) { | 298 ScopedCFTypeRef<CFArrayRef>* policies) { |
| 299 ScopedCFTypeRef<CFMutableArrayRef> local_policies( | 299 ScopedCFTypeRef<CFMutableArrayRef> local_policies( |
| 300 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); | 300 CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks)); |
| 301 if (!local_policies) | 301 if (!local_policies) |
| 302 return memFullErr; | 302 return memFullErr; |
| 303 | 303 |
| 304 // Create an SSL SecPolicyRef, and configure it to perform hostname | 304 // Create an SSL SecPolicyRef, and configure it to perform hostname |
| 305 // validation. The hostname check does 99% of what we want, with the | 305 // validation. The hostname check does 99% of what we want, with the |
| 306 // exception of dotted IPv4 addreses, which we handle ourselves below. | 306 // exception of dotted IPv4 addreses, which we handle ourselves below. |
| 307 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { | |
| 308 CSSM_APPLE_TP_SSL_OPTS_VERSION, | |
| 309 hostname.size(), | |
| 310 hostname.data(), | |
| 311 0 | |
| 312 }; | |
| 313 SecPolicyRef ssl_policy; | 307 SecPolicyRef ssl_policy; |
| 314 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options, | 308 OSStatus status = X509Certificate::CreateSSLPolicy(true, hostname, |
| 315 sizeof(tp_ssl_options), &ssl_policy); | 309 &ssl_policy); |
| 316 if (status) | 310 if (status) |
| 317 return status; | 311 return status; |
| 318 CFArrayAppendValue(local_policies, ssl_policy); | 312 CFArrayAppendValue(local_policies, ssl_policy); |
| 319 CFRelease(ssl_policy); | 313 CFRelease(ssl_policy); |
| 320 | 314 |
| 321 // Manually add revocation policies. In order to actually disable revocation | 315 // Explicitly add revocation policies, in order to override system checks. |
|
wtc
2011/06/03 01:58:04
Nit: it's not clear what "system checks" means.
| |
| 322 // checking, the SecTrustRef must have at least one revocation policy | 316 status = X509Certificate::CreateRevocationPolicies( |
| 323 // associated with it. If none are present, the Apple TP will add policies | 317 (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED), |
| 324 // according to the system preferences, which will enable revocation | 318 local_policies); |
|
wtc
2011/06/03 01:58:04
Add
if (status)
return status;
| |
| 325 // checking even if the caller explicitly disabled it. An OCSP policy is | |
| 326 // used, rather than a CRL policy, because the Apple TP will force an OCSP | |
| 327 // policy to be present and enabled if it believes the certificate may chain | |
| 328 // to an EV root. By explicitly disabling network and OCSP cache access, | |
| 329 // then even if the Apple TP enables OCSP checking, no revocation checking | |
| 330 // will actually succeed. | |
| 331 CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options; | |
| 332 memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options)); | |
| 333 tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; | |
| 334 | |
| 335 if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { | |
| 336 // The default for the OCSP policy is to fetch responses via the network, | |
| 337 // unlike the CRL policy default. The policy is further modified to | |
| 338 // prefer OCSP over CRLs, if both are specified on the certificate. This | |
| 339 // is because an OCSP response is both sufficient and typically | |
| 340 // significantly smaller than the CRL counterpart. | |
| 341 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; | |
| 342 } else { | |
| 343 // Effectively disable OCSP checking by making it impossible to get an | |
| 344 // OCSP response. Even if the Apple TP forces OCSP, no checking will | |
| 345 // be able to succeed. If this happens, the Apple TP will report an error | |
| 346 // that OCSP was unavailable, but this will be handled and suppressed in | |
| 347 // X509Certificate::Verify(). | |
| 348 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET | | |
| 349 CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE; | |
| 350 } | |
| 351 | |
| 352 SecPolicyRef ocsp_policy; | |
| 353 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, &tp_ocsp_options, | |
| 354 sizeof(tp_ocsp_options), &ocsp_policy); | |
| 355 if (status) | |
| 356 return status; | |
| 357 CFArrayAppendValue(local_policies, ocsp_policy); | |
| 358 CFRelease(ocsp_policy); | |
| 359 | |
| 360 if (flags & X509Certificate::VERIFY_REV_CHECKING_ENABLED) { | |
| 361 CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; | |
| 362 memset(&tp_crl_options, 0, sizeof(tp_crl_options)); | |
| 363 tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; | |
| 364 tp_crl_options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; | |
| 365 | |
| 366 SecPolicyRef crl_policy; | |
| 367 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, | |
| 368 sizeof(tp_crl_options), &crl_policy); | |
| 369 if (status) | |
| 370 return status; | |
| 371 CFArrayAppendValue(local_policies, crl_policy); | |
| 372 CFRelease(crl_policy); | |
| 373 } | |
| 374 | 319 |
| 375 policies->reset(local_policies.release()); | 320 policies->reset(local_policies.release()); |
| 376 return noErr; | 321 return noErr; |
| 377 } | 322 } |
| 378 | 323 |
| 379 // Gets the issuer for a given cert, starting with the cert itself and | 324 // Gets the issuer for a given cert, starting with the cert itself and |
| 380 // including the intermediate and finally root certificates (if any). | 325 // including the intermediate and finally root certificates (if any). |
| 381 // This function calls SecTrust but doesn't actually pay attention to the trust | 326 // This function calls SecTrust but doesn't actually pay attention to the trust |
| 382 // result: it shouldn't be used to determine trust, just to traverse the chain. | 327 // result: it shouldn't be used to determine trust, just to traverse the chain. |
| 383 // Caller is responsible for releasing the value stored into *out_cert_chain. | 328 // Caller is responsible for releasing the value stored into *out_cert_chain. |
| 384 OSStatus CopyCertChain(SecCertificateRef cert_handle, | 329 OSStatus CopyCertChain(SecCertificateRef cert_handle, |
| 385 CFArrayRef* out_cert_chain) { | 330 CFArrayRef* out_cert_chain) { |
| 386 DCHECK(cert_handle); | 331 DCHECK(cert_handle); |
| 387 DCHECK(out_cert_chain); | 332 DCHECK(out_cert_chain); |
| 388 // Create an SSL policy ref configured for client cert evaluation. | 333 // Create an SSL policy ref configured for client cert evaluation. |
| 389 SecPolicyRef ssl_policy; | 334 SecPolicyRef ssl_policy; |
| 390 OSStatus result = X509Certificate::CreateSSLClientPolicy(&ssl_policy); | 335 OSStatus result = X509Certificate::CreateSSLPolicy(false, std::string(), |
| 336 &ssl_policy); | |
| 391 if (result) | 337 if (result) |
| 392 return result; | 338 return result; |
| 393 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); | 339 ScopedCFTypeRef<SecPolicyRef> scoped_ssl_policy(ssl_policy); |
| 394 | 340 |
| 395 // Create a SecTrustRef. | 341 // Create a SecTrustRef. |
| 396 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( | 342 ScopedCFTypeRef<CFArrayRef> input_certs(CFArrayCreate( |
| 397 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), | 343 NULL, const_cast<const void**>(reinterpret_cast<void**>(&cert_handle)), |
| 398 1, &kCFTypeArrayCallBacks)); | 344 1, &kCFTypeArrayCallBacks)); |
| 399 SecTrustRef trust_ref = NULL; | 345 SecTrustRef trust_ref = NULL; |
| 400 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); | 346 result = SecTrustCreateWithCertificates(input_certs, ssl_policy, &trust_ref); |
| (...skipping 794 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1195 X509Certificate::OSCertHandles())); | 1141 X509Certificate::OSCertHandles())); |
| 1196 for (unsigned j = 0; j < valid_issuers.size(); j++) { | 1142 for (unsigned j = 0; j < valid_issuers.size(); j++) { |
| 1197 if (cert->issuer().Matches(valid_issuers[j])) | 1143 if (cert->issuer().Matches(valid_issuers[j])) |
| 1198 return true; | 1144 return true; |
| 1199 } | 1145 } |
| 1200 } | 1146 } |
| 1201 return false; | 1147 return false; |
| 1202 } | 1148 } |
| 1203 | 1149 |
| 1204 // static | 1150 // static |
| 1205 OSStatus X509Certificate::CreateSSLClientPolicy(SecPolicyRef* out_policy) { | 1151 OSStatus X509Certificate::CreateSSLPolicy(bool is_server, |
| 1206 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options = { | 1152 const std::string& hostname, |
| 1207 CSSM_APPLE_TP_SSL_OPTS_VERSION, | 1153 SecPolicyRef* policy) { |
| 1208 0, | 1154 CSSM_APPLE_TP_SSL_OPTIONS tp_ssl_options; |
| 1209 NULL, | 1155 memset(&tp_ssl_options, 0, sizeof(tp_ssl_options)); |
| 1210 CSSM_APPLE_TP_SSL_CLIENT | 1156 tp_ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION; |
| 1211 }; | 1157 if (is_server && !hostname.empty()) { |
| 1212 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, | 1158 tp_ssl_options.ServerName = hostname.c_str(); |
|
wtc
2011/06/03 01:58:04
Use hostname.data(), which does not require conver
| |
| 1213 &tp_ssl_options, | 1159 tp_ssl_options.ServerNameLen = hostname.size(); |
| 1214 sizeof(tp_ssl_options), | 1160 } |
| 1215 out_policy); | 1161 if (!is_server) |
| 1162 tp_ssl_options.Flags |= CSSM_APPLE_TP_SSL_CLIENT; | |
| 1163 | |
| 1164 return CreatePolicy(&CSSMOID_APPLE_TP_SSL, &tp_ssl_options, | |
| 1165 sizeof(tp_ssl_options), policy); | |
| 1216 } | 1166 } |
| 1217 | 1167 |
| 1218 // static | 1168 // static |
| 1169 OSStatus X509Certificate::CreateBasicX509Policy(SecPolicyRef* policy) { | |
| 1170 return CreatePolicy(&CSSMOID_APPLE_X509_BASIC, NULL, 0, policy); | |
| 1171 } | |
| 1172 | |
| 1173 // static | |
| 1174 OSStatus X509Certificate::CreateRevocationPolicies( | |
| 1175 bool enable_revocation_checking, | |
| 1176 CFMutableArrayRef policies) { | |
| 1177 // In order to actually disable revocation checking, the SecTrustRef must | |
| 1178 // have at least one revocation policy associated with it. If none are | |
| 1179 // present, the Apple TP will add policies according to the system | |
| 1180 // preferences, which will enable revocation checking even if the caller | |
| 1181 // explicitly disabled it. An OCSP policy is used, rather than a CRL policy, | |
| 1182 // because the Apple TP will force an OCSP policy to be present and enabled | |
| 1183 // if it believes the certificate may chain to an EV root. By explicitly | |
| 1184 // disabling network and OCSP cache access, then even if the Apple TP | |
| 1185 // enables OCSP checking, no revocation checking will actually succeed. | |
| 1186 CSSM_APPLE_TP_OCSP_OPTIONS tp_ocsp_options; | |
| 1187 memset(&tp_ocsp_options, 0, sizeof(tp_ocsp_options)); | |
| 1188 tp_ocsp_options.Version = CSSM_APPLE_TP_OCSP_OPTS_VERSION; | |
| 1189 | |
| 1190 if (enable_revocation_checking) { | |
| 1191 // The default for the OCSP policy is to fetch responses via the network, | |
| 1192 // unlike the CRL policy default. The policy is further modified to | |
| 1193 // prefer OCSP over CRLs, if both are specified on the certificate. This | |
| 1194 // is because an OCSP response is both sufficient and typically | |
| 1195 // significantly smaller than the CRL counterpart. | |
| 1196 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_SUFFICIENT; | |
| 1197 } else { | |
| 1198 // Effectively disable OCSP checking by making it impossible to get an | |
| 1199 // OCSP response. Even if the Apple TP forces OCSP, no checking will | |
| 1200 // be able to succeed. If this happens, the Apple TP will report an error | |
| 1201 // that OCSP was unavailable, but this will be handled and suppressed in | |
| 1202 // X509Certificate::Verify(). | |
| 1203 tp_ocsp_options.Flags = CSSM_TP_ACTION_OCSP_DISABLE_NET | | |
| 1204 CSSM_TP_ACTION_OCSP_CACHE_READ_DISABLE; | |
| 1205 } | |
| 1206 | |
| 1207 SecPolicyRef ocsp_policy; | |
| 1208 OSStatus status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_OCSP, | |
| 1209 &tp_ocsp_options, sizeof(tp_ocsp_options), | |
| 1210 &ocsp_policy); | |
| 1211 if (status) | |
| 1212 return status; | |
| 1213 CFArrayAppendValue(policies, ocsp_policy); | |
| 1214 CFRelease(ocsp_policy); | |
| 1215 | |
| 1216 if (enable_revocation_checking) { | |
| 1217 CSSM_APPLE_TP_CRL_OPTIONS tp_crl_options; | |
| 1218 memset(&tp_crl_options, 0, sizeof(tp_crl_options)); | |
| 1219 tp_crl_options.Version = CSSM_APPLE_TP_CRL_OPTS_VERSION; | |
| 1220 tp_crl_options.CrlFlags = CSSM_TP_ACTION_FETCH_CRL_FROM_NET; | |
| 1221 | |
| 1222 SecPolicyRef crl_policy; | |
| 1223 status = CreatePolicy(&CSSMOID_APPLE_TP_REVOCATION_CRL, &tp_crl_options, | |
| 1224 sizeof(tp_crl_options), &crl_policy); | |
| 1225 if (status) | |
| 1226 return status; | |
| 1227 CFArrayAppendValue(policies, crl_policy); | |
| 1228 CFRelease(crl_policy); | |
| 1229 } | |
| 1230 | |
| 1231 return status; | |
| 1232 } | |
| 1233 | |
| 1234 | |
| 1235 // static | |
| 1219 bool X509Certificate::GetSSLClientCertificates( | 1236 bool X509Certificate::GetSSLClientCertificates( |
| 1220 const std::string& server_domain, | 1237 const std::string& server_domain, |
| 1221 const std::vector<CertPrincipal>& valid_issuers, | 1238 const std::vector<CertPrincipal>& valid_issuers, |
| 1222 CertificateList* certs) { | 1239 CertificateList* certs) { |
| 1223 ScopedCFTypeRef<SecIdentityRef> preferred_identity; | 1240 ScopedCFTypeRef<SecIdentityRef> preferred_identity; |
| 1224 if (!server_domain.empty()) { | 1241 if (!server_domain.empty()) { |
| 1225 // See if there's an identity preference for this domain: | 1242 // See if there's an identity preference for this domain: |
| 1226 ScopedCFTypeRef<CFStringRef> domain_str( | 1243 ScopedCFTypeRef<CFStringRef> domain_str( |
| 1227 base::SysUTF8ToCFStringRef("https://" + server_domain)); | 1244 base::SysUTF8ToCFStringRef("https://" + server_domain)); |
| 1228 SecIdentityRef identity = NULL; | 1245 SecIdentityRef identity = NULL; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1346 CSSM_DATA cert_data; | 1363 CSSM_DATA cert_data; |
| 1347 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); | 1364 OSStatus status = SecCertificateGetData(cert_handle, &cert_data); |
| 1348 if (status) | 1365 if (status) |
| 1349 return false; | 1366 return false; |
| 1350 | 1367 |
| 1351 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), | 1368 return pickle->WriteData(reinterpret_cast<char*>(cert_data.Data), |
| 1352 cert_data.Length); | 1369 cert_data.Length); |
| 1353 } | 1370 } |
| 1354 | 1371 |
| 1355 } // namespace net | 1372 } // namespace net |
| OLD | NEW |