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 <cert.h> | 7 #include <cert.h> |
8 #include <nss.h> | 8 #include <nss.h> |
9 #include <pk11pub.h> | 9 #include <pk11pub.h> |
10 #include <prerror.h> | 10 #include <prerror.h> |
11 #include <prtime.h> | 11 #include <prtime.h> |
12 #include <secder.h> | 12 #include <secder.h> |
13 #include <secerr.h> | 13 #include <secerr.h> |
14 #include <sechash.h> | 14 #include <sechash.h> |
15 #include <sslerr.h> | 15 #include <sslerr.h> |
16 | 16 |
| 17 #include <limits> |
| 18 |
17 #include "base/logging.h" | 19 #include "base/logging.h" |
18 #include "base/pickle.h" | 20 #include "base/pickle.h" |
19 #include "base/time.h" | 21 #include "base/time.h" |
20 #include "base/nss_util.h" | 22 #include "base/nss_util.h" |
| 23 #include "base/crypto/scoped_nss_types.h" |
21 #include "net/base/cert_status_flags.h" | 24 #include "net/base/cert_status_flags.h" |
22 #include "net/base/cert_verify_result.h" | 25 #include "net/base/cert_verify_result.h" |
23 #include "net/base/ev_root_ca_metadata.h" | 26 #include "net/base/ev_root_ca_metadata.h" |
24 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
25 | 28 |
26 namespace net { | 29 namespace net { |
27 | 30 |
28 namespace { | 31 namespace { |
29 | 32 |
30 class ScopedCERTCertificate { | 33 typedef scoped_ptr_malloc<CERTCertificatePolicies, |
31 public: | 34 base::NSSDestroyer<CERTCertificatePolicies, |
32 explicit ScopedCERTCertificate(CERTCertificate* cert) | 35 CERT_DestroyCertificatePoliciesExtension> > |
33 : cert_(cert) {} | 36 ScopedCERTCertificatePolicies; |
34 | |
35 ~ScopedCERTCertificate() { | |
36 if (cert_) | |
37 CERT_DestroyCertificate(cert_); | |
38 } | |
39 | |
40 private: | |
41 CERTCertificate* cert_; | |
42 | |
43 DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificate); | |
44 }; | |
45 | |
46 class ScopedCERTCertList { | |
47 public: | |
48 explicit ScopedCERTCertList(CERTCertList* cert_list) | |
49 : cert_list_(cert_list) {} | |
50 | |
51 ~ScopedCERTCertList() { | |
52 if (cert_list_) | |
53 CERT_DestroyCertList(cert_list_); | |
54 } | |
55 | |
56 private: | |
57 CERTCertList* cert_list_; | |
58 | |
59 DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertList); | |
60 }; | |
61 | |
62 class ScopedCERTCertificatePolicies { | |
63 public: | |
64 explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies) | |
65 : policies_(policies) {} | |
66 | |
67 ~ScopedCERTCertificatePolicies() { | |
68 if (policies_) | |
69 CERT_DestroyCertificatePoliciesExtension(policies_); | |
70 } | |
71 | |
72 private: | |
73 CERTCertificatePolicies* policies_; | |
74 | |
75 DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificatePolicies); | |
76 }; | |
77 | 37 |
78 // ScopedCERTValOutParam manages destruction of values in the CERTValOutParam | 38 // ScopedCERTValOutParam manages destruction of values in the CERTValOutParam |
79 // array that cvout points to. cvout must be initialized as passed to | 39 // array that cvout points to. cvout must be initialized as passed to |
80 // CERT_PKIXVerifyCert, so that the array must be terminated with | 40 // CERT_PKIXVerifyCert, so that the array must be terminated with |
81 // cert_po_end type. | 41 // cert_po_end type. |
82 // When it goes out of scope, it destroys values of cert_po_trustAnchor | 42 // When it goes out of scope, it destroys values of cert_po_trustAnchor |
83 // and cert_po_certList types, but doesn't release the array itself. | 43 // and cert_po_certList types, but doesn't release the array itself. |
84 class ScopedCERTValOutParam { | 44 class ScopedCERTValOutParam { |
85 public: | 45 public: |
86 explicit ScopedCERTValOutParam(CERTValOutParam* cvout) | 46 explicit ScopedCERTValOutParam(CERTValOutParam* cvout) |
(...skipping 477 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
564 SECOidTag oid_tag = policy_info->oid; | 524 SECOidTag oid_tag = policy_info->oid; |
565 if (oid_tag == SEC_OID_UNKNOWN) | 525 if (oid_tag == SEC_OID_UNKNOWN) |
566 continue; | 526 continue; |
567 if (oid_tag == ev_policy_tag) | 527 if (oid_tag == ev_policy_tag) |
568 return true; | 528 return true; |
569 } | 529 } |
570 LOG(ERROR) << "No EV Policy Tag"; | 530 LOG(ERROR) << "No EV Policy Tag"; |
571 return false; | 531 return false; |
572 } | 532 } |
573 | 533 |
| 534 struct CollectCertsCallbackArgs { |
| 535 X509Certificate::OSCertHandle (*createFn)(const char* data, size_t length); |
| 536 X509Certificate::OSCertHandles* results; |
| 537 }; |
| 538 |
| 539 SECStatus PR_CALLBACK |
| 540 CollectCertsCallback(void* arg, SECItem** certs, int numcerts) { |
| 541 if (numcerts < 0) |
| 542 return SECFailure; // In the event of wrapping |
| 543 |
| 544 CollectCertsCallbackArgs* args = |
| 545 reinterpret_cast<CollectCertsCallbackArgs*>(arg); |
| 546 |
| 547 for (int i = 0; i < numcerts; ++i) { |
| 548 X509Certificate::OSCertHandle handle = args->createFn( |
| 549 reinterpret_cast<char*>(certs[i]->data), certs[i]->len); |
| 550 if (handle) |
| 551 args->results->push_back(handle); |
| 552 } |
| 553 |
| 554 return SECSuccess; |
| 555 } |
| 556 |
574 } // namespace | 557 } // namespace |
575 | 558 |
576 void X509Certificate::Initialize() { | 559 void X509Certificate::Initialize() { |
577 ParsePrincipal(&cert_handle_->subject, &subject_); | 560 ParsePrincipal(&cert_handle_->subject, &subject_); |
578 ParsePrincipal(&cert_handle_->issuer, &issuer_); | 561 ParsePrincipal(&cert_handle_->issuer, &issuer_); |
579 | 562 |
580 ParseDate(&cert_handle_->validity.notBefore, &valid_start_); | 563 ParseDate(&cert_handle_->validity.notBefore, &valid_start_); |
581 ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); | 564 ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); |
582 | 565 |
583 fingerprint_ = CalculateFingerprint(cert_handle_); | 566 fingerprint_ = CalculateFingerprint(cert_handle_); |
584 } | 567 } |
585 | 568 |
586 // static | 569 // static |
587 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, | 570 X509Certificate* X509Certificate::CreateFromPickle(const Pickle& pickle, |
588 void** pickle_iter) { | 571 void** pickle_iter) { |
589 const char* data; | 572 const char* data; |
590 int length; | 573 int length; |
591 if (!pickle.ReadData(pickle_iter, &data, &length)) | 574 if (!pickle.ReadData(pickle_iter, &data, &length)) |
592 return NULL; | 575 return NULL; |
593 | 576 |
594 return CreateFromBytes(data, length); | 577 return CreateFromBytes(data, length, FORMAT_DER); |
595 } | 578 } |
596 | 579 |
597 void X509Certificate::Persist(Pickle* pickle) { | 580 void X509Certificate::Persist(Pickle* pickle) { |
598 pickle->WriteData(reinterpret_cast<const char*>(cert_handle_->derCert.data), | 581 pickle->WriteData(reinterpret_cast<const char*>(cert_handle_->derCert.data), |
599 cert_handle_->derCert.len); | 582 cert_handle_->derCert.len); |
600 } | 583 } |
601 | 584 |
602 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { | 585 void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { |
603 dns_names->clear(); | 586 dns_names->clear(); |
604 | 587 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
713 return false; | 696 return false; |
714 | 697 |
715 if (!CheckCertPolicies(cert_handle_, ev_policy_tag)) | 698 if (!CheckCertPolicies(cert_handle_, ev_policy_tag)) |
716 return false; | 699 return false; |
717 | 700 |
718 return true; | 701 return true; |
719 } | 702 } |
720 | 703 |
721 // static | 704 // static |
722 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( | 705 X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( |
723 const char* data, int length) { | 706 const char* data, size_t length) { |
| 707 if (length > static_cast<size_t>(std::numeric_limits<unsigned int>::max())) |
| 708 return NULL; |
| 709 |
724 base::EnsureNSSInit(); | 710 base::EnsureNSSInit(); |
725 | 711 |
726 if (!NSS_IsInitialized()) | 712 if (!NSS_IsInitialized()) |
727 return NULL; | 713 return NULL; |
728 | 714 |
729 // Make a copy of |data| since CERT_DecodeCertPackage might modify it. | 715 SECItem der_cert; |
730 char* data_copy = new char[length]; | 716 der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); |
731 memcpy(data_copy, data, length); | 717 der_cert.len = static_cast<unsigned int>(length); |
| 718 der_cert.type = siDERCertBuffer; |
732 | 719 |
733 // Parse into a certificate structure. | 720 // Parse into a certificate structure. |
734 CERTCertificate* cert = CERT_DecodeCertFromPackage(data_copy, length); | 721 CERTCertificate* cert = |
735 delete [] data_copy; | 722 CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, |
| 723 PR_FALSE, PR_TRUE); |
736 if (!cert) | 724 if (!cert) |
737 LOG(ERROR) << "Couldn't parse a certificate from " << length << " bytes"; | 725 return NULL; |
| 726 |
738 return cert; | 727 return cert; |
739 } | 728 } |
740 | 729 |
741 // static | 730 // static |
| 731 X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( |
| 732 const char* data, size_t length, CertificateFormat format) { |
| 733 OSCertHandles results; |
| 734 |
| 735 if (length > static_cast<size_t>(std::numeric_limits<int>::max())) |
| 736 return results; |
| 737 |
| 738 switch (format) { |
| 739 case FORMAT_DER: |
| 740 { |
| 741 OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); |
| 742 if (handle) |
| 743 results.push_back(handle); |
| 744 } |
| 745 break; |
| 746 case FORMAT_LEGACY_NETSCAPE: |
| 747 case FORMAT_PKCS7: |
| 748 { |
| 749 // Make a copy since CERT_DecodeCertPackage may modify it |
| 750 scoped_array<char> data_copy(new char[length]); |
| 751 memcpy(data_copy.get(), data, length); |
| 752 |
| 753 CollectCertsCallbackArgs args; |
| 754 args.results = &results; |
| 755 args.createFn = &X509Certificate::CreateOSCertHandleFromBytes; |
| 756 |
| 757 SECStatus result = CERT_DecodeCertPackage(data_copy.get(), |
| 758 static_cast<int>(length), CollectCertsCallback, &args); |
| 759 if (result != SECSuccess) |
| 760 results.clear(); |
| 761 } |
| 762 break; |
| 763 default: |
| 764 NOTREACHED() << "Certificate format " << format << " unimplemented"; |
| 765 break; |
| 766 } |
| 767 |
| 768 return results; |
| 769 } |
| 770 |
| 771 // static |
742 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( | 772 X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( |
743 OSCertHandle cert_handle) { | 773 OSCertHandle cert_handle) { |
744 return CERT_DupCertificate(cert_handle); | 774 return CERT_DupCertificate(cert_handle); |
745 } | 775 } |
746 | 776 |
747 // static | 777 // static |
748 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { | 778 void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { |
749 CERT_DestroyCertificate(cert_handle); | 779 CERT_DestroyCertificate(cert_handle); |
750 } | 780 } |
751 | 781 |
752 // static | 782 // static |
753 X509Certificate::Fingerprint X509Certificate::CalculateFingerprint( | 783 X509Certificate::Fingerprint X509Certificate::CalculateFingerprint( |
754 OSCertHandle cert) { | 784 OSCertHandle cert) { |
755 Fingerprint sha1; | 785 Fingerprint sha1; |
756 memset(sha1.data, 0, sizeof(sha1.data)); | 786 memset(sha1.data, 0, sizeof(sha1.data)); |
757 | 787 |
758 DCHECK(NULL != cert->derCert.data); | 788 DCHECK(NULL != cert->derCert.data); |
759 DCHECK(0 != cert->derCert.len); | 789 DCHECK(0 != cert->derCert.len); |
760 | 790 |
761 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, | 791 SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, |
762 cert->derCert.data, cert->derCert.len); | 792 cert->derCert.data, cert->derCert.len); |
763 DCHECK(rv == SECSuccess); | 793 DCHECK(rv == SECSuccess); |
764 | 794 |
765 return sha1; | 795 return sha1; |
766 } | 796 } |
767 | 797 |
768 } // namespace net | 798 } // namespace net |
OLD | NEW |