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 |