| 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 <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 | 10 |
| 11 #include <cert.h> | 11 #include <cert.h> |
| 12 | 12 |
| 13 #include <vector> | 13 #include <vector> |
| 14 | 14 |
| 15 #include "base/lazy_instance.h" | 15 #include "base/lazy_instance.h" |
| 16 #include "base/logging.h" | 16 #include "base/logging.h" |
| 17 #include "base/mac/mac_logging.h" | 17 #include "base/mac/mac_logging.h" |
| 18 #include "base/mac/scoped_cftyperef.h" | 18 #include "base/mac/scoped_cftyperef.h" |
| 19 #include "base/memory/singleton.h" | 19 #include "base/memory/singleton.h" |
| 20 #include "base/pickle.h" | 20 #include "base/pickle.h" |
| 21 #include "base/sha1.h" | 21 #include "base/sha1.h" |
| 22 #include "base/strings/string_piece.h" | 22 #include "base/strings/string_piece.h" |
| 23 #include "base/strings/sys_string_conversions.h" | 23 #include "base/strings/sys_string_conversions.h" |
| 24 #include "base/synchronization/lock.h" | 24 #include "base/synchronization/lock.h" |
| 25 #include "crypto/cssm_init.h" | 25 #include "crypto/cssm_init.h" |
| 26 #include "crypto/mac_security_services_lock.h" | 26 #include "crypto/mac_security_services_lock.h" |
| 27 #include "crypto/nss_util.h" | 27 #include "crypto/nss_util.h" |
| 28 #include "crypto/rsa_private_key.h" | |
| 29 #include "net/cert/x509_util_mac.h" | 28 #include "net/cert/x509_util_mac.h" |
| 30 | 29 |
| 31 using base::ScopedCFTypeRef; | 30 using base::ScopedCFTypeRef; |
| 32 using base::Time; | 31 using base::Time; |
| 33 | 32 |
| 34 namespace net { | 33 namespace net { |
| 35 | 34 |
| 36 namespace { | 35 namespace { |
| 37 | 36 |
| 38 void GetCertDistinguishedName( | 37 void GetCertDistinguishedName( |
| (...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 319 return true; | 318 return true; |
| 320 | 319 |
| 321 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); | 320 for (OSCertHandles::iterator it = intermediate_ca_certs_.begin(); |
| 322 it != intermediate_ca_certs_.end(); ++it) { | 321 it != intermediate_ca_certs_.end(); ++it) { |
| 323 if (IsCertIssuerInEncodedList(*it, valid_issuers)) | 322 if (IsCertIssuerInEncodedList(*it, valid_issuers)) |
| 324 return true; | 323 return true; |
| 325 } | 324 } |
| 326 return false; | 325 return false; |
| 327 } | 326 } |
| 328 | 327 |
| 329 // static | |
| 330 X509Certificate* X509Certificate::CreateSelfSigned( | |
| 331 crypto::RSAPrivateKey* key, | |
| 332 const std::string& subject, | |
| 333 uint32 serial_number, | |
| 334 base::TimeDelta valid_duration) { | |
| 335 DCHECK(key); | |
| 336 DCHECK(!subject.empty()); | |
| 337 | |
| 338 if (valid_duration.InSeconds() > kuint32max) { | |
| 339 LOG(ERROR) << "valid_duration too big " << valid_duration.InSeconds(); | |
| 340 valid_duration = base::TimeDelta::FromSeconds(kuint32max); | |
| 341 } | |
| 342 | |
| 343 // There is a comment in | |
| 344 // http://www.opensource.apple.com/source/security_certtool/security_certtool-
31828/src/CertTool.cpp | |
| 345 // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have | |
| 346 // their high bit set. We will continue though and mask it out below. | |
| 347 if (serial_number & 0x80000000) | |
| 348 LOG(ERROR) << "serial_number has high bit set " << serial_number; | |
| 349 | |
| 350 // NSS is used to parse the subject string into a set of | |
| 351 // CSSM_OID/string pairs. There doesn't appear to be a system routine for | |
| 352 // parsing Distinguished Name strings. | |
| 353 crypto::EnsureNSSInit(); | |
| 354 | |
| 355 CSSMOIDStringVector subject_name_oids; | |
| 356 ScopedCertName subject_name( | |
| 357 CERT_AsciiToName(const_cast<char*>(subject.c_str()))); | |
| 358 if (!CERTNameToCSSMOIDVector(subject_name, &subject_name_oids)) { | |
| 359 DLOG(ERROR) << "Unable to generate CSSMOIDMap from " << subject; | |
| 360 return NULL; | |
| 361 } | |
| 362 | |
| 363 // Convert the map of oid/string pairs into an array of | |
| 364 // CSSM_APPLE_TP_NAME_OIDs. | |
| 365 std::vector<CSSM_APPLE_TP_NAME_OID> cssm_subject_names; | |
| 366 for (CSSMOIDStringVector::iterator iter = subject_name_oids.begin(); | |
| 367 iter != subject_name_oids.end(); ++iter) { | |
| 368 CSSM_APPLE_TP_NAME_OID cssm_subject_name; | |
| 369 cssm_subject_name.oid = iter->oid_; | |
| 370 cssm_subject_name.string = iter->string_.c_str(); | |
| 371 cssm_subject_names.push_back(cssm_subject_name); | |
| 372 } | |
| 373 | |
| 374 if (cssm_subject_names.empty()) { | |
| 375 DLOG(ERROR) << "cssm_subject_names.size() == 0. Input: " << subject; | |
| 376 return NULL; | |
| 377 } | |
| 378 | |
| 379 // Set up a certificate request. | |
| 380 CSSM_APPLE_TP_CERT_REQUEST certReq; | |
| 381 memset(&certReq, 0, sizeof(certReq)); | |
| 382 certReq.cspHand = crypto::GetSharedCSPHandle(); | |
| 383 certReq.clHand = crypto::GetSharedCLHandle(); | |
| 384 // See comment about serial numbers above. | |
| 385 certReq.serialNumber = serial_number & 0x7fffffff; | |
| 386 certReq.numSubjectNames = cssm_subject_names.size(); | |
| 387 certReq.subjectNames = &cssm_subject_names[0]; | |
| 388 certReq.numIssuerNames = 0; // Root. | |
| 389 certReq.issuerNames = NULL; | |
| 390 certReq.issuerNameX509 = NULL; | |
| 391 certReq.certPublicKey = key->public_key(); | |
| 392 certReq.issuerPrivateKey = key->key(); | |
| 393 // These are the Apple defaults. | |
| 394 certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA; | |
| 395 certReq.signatureOid = CSSMOID_SHA1WithRSA; | |
| 396 certReq.notBefore = 0; | |
| 397 certReq.notAfter = static_cast<uint32>(valid_duration.InSeconds()); | |
| 398 certReq.numExtensions = 0; | |
| 399 certReq.extensions = NULL; | |
| 400 certReq.challengeString = NULL; | |
| 401 | |
| 402 CSSM_TP_REQUEST_SET reqSet; | |
| 403 reqSet.NumberOfRequests = 1; | |
| 404 reqSet.Requests = &certReq; | |
| 405 | |
| 406 CSSM_FIELD policyId; | |
| 407 memset(&policyId, 0, sizeof(policyId)); | |
| 408 policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; | |
| 409 | |
| 410 CSSM_TP_CALLERAUTH_CONTEXT callerAuthContext; | |
| 411 memset(&callerAuthContext, 0, sizeof(callerAuthContext)); | |
| 412 callerAuthContext.Policy.NumberOfPolicyIds = 1; | |
| 413 callerAuthContext.Policy.PolicyIds = &policyId; | |
| 414 | |
| 415 CSSM_TP_HANDLE tp_handle = crypto::GetSharedTPHandle(); | |
| 416 CSSM_DATA refId; | |
| 417 memset(&refId, 0, sizeof(refId)); | |
| 418 sint32 estTime; | |
| 419 CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tp_handle, NULL, | |
| 420 CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, &reqSet, &callerAuthContext, | |
| 421 &estTime, &refId); | |
| 422 if (crtn) { | |
| 423 DLOG(ERROR) << "CSSM_TP_SubmitCredRequest failed " << crtn; | |
| 424 return NULL; | |
| 425 } | |
| 426 | |
| 427 CSSM_BOOL confirmRequired; | |
| 428 CSSM_TP_RESULT_SET* resultSet = NULL; | |
| 429 crtn = CSSM_TP_RetrieveCredResult(tp_handle, &refId, NULL, &estTime, | |
| 430 &confirmRequired, &resultSet); | |
| 431 ScopedEncodedCertResults scopedResults(resultSet); | |
| 432 crypto::CSSMFree(refId.Data); | |
| 433 if (crtn) { | |
| 434 DLOG(ERROR) << "CSSM_TP_RetrieveCredResult failed " << crtn; | |
| 435 return NULL; | |
| 436 } | |
| 437 | |
| 438 if (confirmRequired) { | |
| 439 // Potential leak here of resultSet. |confirmRequired| should never be | |
| 440 // true. | |
| 441 DLOG(ERROR) << "CSSM_TP_RetrieveCredResult required confirmation"; | |
| 442 return NULL; | |
| 443 } | |
| 444 | |
| 445 if (resultSet->NumberOfResults != 1) { | |
| 446 DLOG(ERROR) << "Unexpected number of results: " | |
| 447 << resultSet->NumberOfResults; | |
| 448 return NULL; | |
| 449 } | |
| 450 | |
| 451 CSSM_ENCODED_CERT* encCert = | |
| 452 reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results); | |
| 453 ScopedCFTypeRef<SecCertificateRef> scoped_cert; | |
| 454 SecCertificateRef certificate_ref = NULL; | |
| 455 OSStatus os_status = | |
| 456 SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType, | |
| 457 encCert->CertEncoding, &certificate_ref); | |
| 458 if (os_status != 0) { | |
| 459 OSSTATUS_DLOG(ERROR, os_status) << "SecCertificateCreateFromData failed"; | |
| 460 return NULL; | |
| 461 } | |
| 462 scoped_cert.reset(certificate_ref); | |
| 463 | |
| 464 return CreateFromHandle(scoped_cert, X509Certificate::OSCertHandles()); | |
| 465 } | |
| 466 | |
| 467 void X509Certificate::GetSubjectAltName( | 328 void X509Certificate::GetSubjectAltName( |
| 468 std::vector<std::string>* dns_names, | 329 std::vector<std::string>* dns_names, |
| 469 std::vector<std::string>* ip_addrs) const { | 330 std::vector<std::string>* ip_addrs) const { |
| 470 if (dns_names) | 331 if (dns_names) |
| 471 dns_names->clear(); | 332 dns_names->clear(); |
| 472 if (ip_addrs) | 333 if (ip_addrs) |
| 473 ip_addrs->clear(); | 334 ip_addrs->clear(); |
| 474 | 335 |
| 475 x509_util::CSSMCachedCertificate cached_cert; | 336 x509_util::CSSMCachedCertificate cached_cert; |
| 476 OSStatus status = cached_cert.Init(cert_handle_); | 337 OSStatus status = cached_cert.Init(cert_handle_); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 *type = kPublicKeyTypeDH; | 602 *type = kPublicKeyTypeDH; |
| 742 break; | 603 break; |
| 743 default: | 604 default: |
| 744 *type = kPublicKeyTypeUnknown; | 605 *type = kPublicKeyTypeUnknown; |
| 745 *size_bits = 0; | 606 *size_bits = 0; |
| 746 break; | 607 break; |
| 747 } | 608 } |
| 748 } | 609 } |
| 749 | 610 |
| 750 } // namespace net | 611 } // namespace net |
| OLD | NEW |