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

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

Issue 7384002: Added CreateOriginBound method to x509_certificate.h. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Cleaned up the Threadsafe OID singleton wrapper class. Created 9 years, 4 months 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
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 <cert.h> 7 #include <cert.h>
8 #include <cryptohi.h> 8 #include <cryptohi.h>
9 #include <keyhi.h> 9 #include <keyhi.h>
10 #include <nss.h> 10 #include <nss.h>
11 #include <pk11pub.h> 11 #include <pk11pub.h>
12 #include <prerror.h> 12 #include <prerror.h>
13 #include <prtime.h> 13 #include <prtime.h>
14 #include <secder.h> 14 #include <secder.h>
15 #include <secerr.h> 15 #include <secerr.h>
16 #include <sechash.h> 16 #include <sechash.h>
17 #include <sslerr.h> 17 #include <sslerr.h>
18 18
19 #include "base/logging.h" 19 #include "base/logging.h"
20 #include "base/memory/scoped_ptr.h" 20 #include "base/memory/scoped_ptr.h"
21 #include "base/memory/singleton.h"
21 #include "base/pickle.h" 22 #include "base/pickle.h"
22 #include "base/time.h" 23 #include "base/time.h"
23 #include "crypto/nss_util.h" 24 #include "crypto/nss_util.h"
24 #include "crypto/rsa_private_key.h" 25 #include "crypto/rsa_private_key.h"
25 #include "net/base/cert_status_flags.h" 26 #include "net/base/cert_status_flags.h"
26 #include "net/base/cert_verify_result.h" 27 #include "net/base/cert_verify_result.h"
27 #include "net/base/ev_root_ca_metadata.h" 28 #include "net/base/ev_root_ca_metadata.h"
28 #include "net/base/net_errors.h" 29 #include "net/base/net_errors.h"
29 30
30 namespace net { 31 namespace net {
31 32
32 namespace { 33 namespace {
33 34
35 class ObCertOIDWrapper {
36 private:
37 ObCertOIDWrapper();
38
39 public:
40 static SECOidTag ObCertOIDTag;
41
42 static ObCertOIDWrapper* GetInstance() {
43 return Singleton<ObCertOIDWrapper>::get();
44 }
45
46 friend struct DefaultSingletonTraits<ObCertOIDWrapper>;
47
48 DISALLOW_COPY_AND_ASSIGN(ObCertOIDWrapper);
49 };
wtc 2011/08/19 18:18:08 The public: section should precede the private: se
mdietz 2011/08/22 20:09:00 Done.
50
51 SECOidTag ObCertOIDWrapper::ObCertOIDTag;
52
53 ObCertOIDWrapper::ObCertOIDWrapper() {
54 // It's harmless if multiple threads enter this block concurrently.
wtc 2011/08/19 18:18:08 Delete this line.
mdietz 2011/08/22 20:09:00 Done.
55 // 1.3.6.1.4.1.11129.2.1.6
56 // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
57 // certificateExtensions.originBoundCertificate)
58 static const uint8 kObCertOID[] = {
59 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x06
60 };
61 SECOidData oid_data;
62 memset(&oid_data, 0, sizeof(oid_data));
63 oid_data.oid.data = const_cast<uint8*>(kObCertOID);
64 oid_data.oid.len = sizeof(kObCertOID);
65 oid_data.offset = SEC_OID_UNKNOWN;
66 oid_data.desc = "Origin Bound Certificate";
67 oid_data.mechanism = CKM_INVALID_MECHANISM;
68 oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
69 ObCertOIDWrapper::ObCertOIDTag = SECOID_AddEntry(&oid_data);
70 if(ObCertOIDWrapper::ObCertOIDTag == SEC_OID_UNKNOWN) {
71 LOG(ERROR) << "OB_CERT OID tag creation failed";
72 }
wtc 2011/08/19 18:18:08 Remove the curly braces for one-liner if bodies.
mdietz 2011/08/22 20:09:00 Done, also added space to fit "if (" coding style.
73 }
74
34 class ScopedCERTCertificatePolicies { 75 class ScopedCERTCertificatePolicies {
35 public: 76 public:
36 explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies) 77 explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies)
37 : policies_(policies) {} 78 : policies_(policies) {}
38 79
39 ~ScopedCERTCertificatePolicies() { 80 ~ScopedCERTCertificatePolicies() {
40 if (policies_) 81 if (policies_)
41 CERT_DestroyCertificatePoliciesExtension(policies_); 82 CERT_DestroyCertificatePoliciesExtension(policies_);
42 } 83 }
43 84
(...skipping 573 matching lines...) Expand 10 before | Expand all | Expand 10 after
617 658
618 serial_number_ = std::string( 659 serial_number_ = std::string(
619 reinterpret_cast<char*>(cert_handle_->serialNumber.data), 660 reinterpret_cast<char*>(cert_handle_->serialNumber.data),
620 cert_handle_->serialNumber.len); 661 cert_handle_->serialNumber.len);
621 // Remove leading zeros. 662 // Remove leading zeros.
622 while (serial_number_.size() > 1 && serial_number_[0] == 0) 663 while (serial_number_.size() > 1 && serial_number_[0] == 0)
623 serial_number_ = serial_number_.substr(1, serial_number_.size() - 1); 664 serial_number_ = serial_number_.substr(1, serial_number_.size() - 1);
624 } 665 }
625 666
626 // static 667 // static
627 X509Certificate* X509Certificate::CreateSelfSigned( 668 CERTCertificate* CreateCertificate(
wtc 2011/08/19 18:18:08 Remove the // static comments for CreateCertific
mdietz 2011/08/22 20:09:00 Done.
628 crypto::RSAPrivateKey* key, 669 crypto::RSAPrivateKey* key,
629 const std::string& subject, 670 const std::string& subject,
630 uint32 serial_number, 671 uint32 serial_number,
631 base::TimeDelta valid_duration) { 672 base::TimeDelta valid_duration) {
632 DCHECK(key);
633
634 // Create info about public key. 673 // Create info about public key.
635 CERTSubjectPublicKeyInfo* spki = 674 CERTSubjectPublicKeyInfo* spki =
636 SECKEY_CreateSubjectPublicKeyInfo(key->public_key()); 675 SECKEY_CreateSubjectPublicKeyInfo(key->public_key());
637 if (!spki) 676 if (!spki)
638 return NULL; 677 return NULL;
639 678
640 // Create the certificate request. 679 // Create the certificate request.
641 CERTName* subject_name = 680 CERTName* subject_name =
642 CERT_AsciiToName(const_cast<char*>(subject.c_str())); 681 CERT_AsciiToName(const_cast<char*>(subject.c_str()));
643 CERTCertificateRequest* cert_request = 682 CERTCertificateRequest* cert_request =
(...skipping 17 matching lines...) Expand all
661 if (!cert) { 700 if (!cert) {
662 PRErrorCode prerr = PR_GetError(); 701 PRErrorCode prerr = PR_GetError();
663 LOG(ERROR) << "Failed to create certificate: " << prerr; 702 LOG(ERROR) << "Failed to create certificate: " << prerr;
664 } 703 }
665 704
666 // Cleanup for resources used to generate the cert. 705 // Cleanup for resources used to generate the cert.
667 CERT_DestroyName(subject_name); 706 CERT_DestroyName(subject_name);
668 CERT_DestroyValidity(validity); 707 CERT_DestroyValidity(validity);
669 CERT_DestroyCertificateRequest(cert_request); 708 CERT_DestroyCertificateRequest(cert_request);
670 709
671 if (!cert) 710 return cert;
672 return NULL; 711 }
673 712
674 // Sign the cert here. The logic of this method references SignCert() in NSS 713 // static
675 // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert. 714 X509Certificate* SignCertificate(
wtc 2011/08/19 18:18:08 The comment for this function should point out the
mdietz 2011/08/22 20:09:00 Added the TODO for now. If I get a chance, I'll d
676 715 CERTCertificate* cert,
716 crypto::RSAPrivateKey* key) {
677 // |arena| is used to encode the cert. 717 // |arena| is used to encode the cert.
678 PRArenaPool* arena = cert->arena; 718 PRArenaPool* arena = cert->arena;
679 SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->key()->keyType, 719 SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->key()->keyType,
680 SEC_OID_SHA1); 720 SEC_OID_SHA1);
681 if (algo_id == SEC_OID_UNKNOWN) { 721 if (algo_id == SEC_OID_UNKNOWN) {
682 CERT_DestroyCertificate(cert); 722 CERT_DestroyCertificate(cert);
683 return NULL; 723 return NULL;
684 } 724 }
685 725
686 SECStatus rv = SECOID_SetAlgorithmID(arena, &cert->signature, algo_id, 0); 726 SECStatus rv = SECOID_SetAlgorithmID(arena, &cert->signature, algo_id, 0);
(...skipping 28 matching lines...) Expand all
715 // Sign the ASN1 encoded cert and save it to |result|. 755 // Sign the ASN1 encoded cert and save it to |result|.
716 rv = SEC_DerSignData(arena, result, der.data, der.len, key->key(), algo_id); 756 rv = SEC_DerSignData(arena, result, der.data, der.len, key->key(), algo_id);
717 if (rv != SECSuccess) { 757 if (rv != SECSuccess) {
718 CERT_DestroyCertificate(cert); 758 CERT_DestroyCertificate(cert);
719 return NULL; 759 return NULL;
720 } 760 }
721 761
722 // Save the signed result to the cert. 762 // Save the signed result to the cert.
723 cert->derCert = *result; 763 cert->derCert = *result;
724 764
725 X509Certificate* x509_cert = CreateFromHandle(cert, OSCertHandles()); 765 X509Certificate* x509_cert =
766 X509Certificate::CreateFromHandle(cert, X509Certificate::OSCertHandles());
726 CERT_DestroyCertificate(cert); 767 CERT_DestroyCertificate(cert);
727 return x509_cert; 768 return x509_cert;
728 } 769 }
729 770
771 // static
772 X509Certificate* X509Certificate::CreateSelfSigned(
773 crypto::RSAPrivateKey* key,
774 const std::string& subject,
775 uint32 serial_number,
776 base::TimeDelta valid_duration) {
777 DCHECK(key);
778
779 CERTCertificate* cert = CreateCertificate(key,
780 subject,
781 serial_number,
782 valid_duration);
783
784 if(!cert)
785 return NULL;
786
787 // Sign the cert here. The logic of this method references SignCert() in NSS
788 // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert.
wtc 2011/08/19 18:18:08 Move this comment before the SignCertificate() fun
mdietz 2011/08/22 20:09:00 Done.
789
790 X509Certificate* x509_cert = SignCertificate(cert, key);
791
792 if(!x509_cert)
793 return NULL;
wtc 2011/08/19 18:18:08 Remove this, because this is handled by the retu
mdietz 2011/08/22 20:09:00 Done.
794
795 return x509_cert;
796 }
797
730 void X509Certificate::GetSubjectAltName( 798 void X509Certificate::GetSubjectAltName(
731 std::vector<std::string>* dns_names, 799 std::vector<std::string>* dns_names,
732 std::vector<std::string>* ip_addrs) const { 800 std::vector<std::string>* ip_addrs) const {
733 if (dns_names) 801 if (dns_names)
734 dns_names->clear(); 802 dns_names->clear();
735 if (ip_addrs) 803 if (ip_addrs)
736 ip_addrs->clear(); 804 ip_addrs->clear();
737 805
738 SECItem alt_name; 806 SECItem alt_name;
739 SECStatus rv = CERT_FindCertExtension(cert_handle_, 807 SECStatus rv = CERT_FindCertExtension(cert_handle_,
(...skipping 23 matching lines...) Expand all
763 reinterpret_cast<char*>(name->name.other.data), 831 reinterpret_cast<char*>(name->name.other.data),
764 name->name.other.len)); 832 name->name.other.len));
765 } 833 }
766 name = CERT_GetNextGeneralName(name); 834 name = CERT_GetNextGeneralName(name);
767 if (name == alt_name_list) 835 if (name == alt_name_list)
768 break; 836 break;
769 } 837 }
770 PORT_FreeArena(arena, PR_FALSE); 838 PORT_FreeArena(arena, PR_FALSE);
771 } 839 }
772 840
841 // static
842 X509Certificate* X509Certificate::CreateOriginBound(
wtc 2011/08/19 18:18:08 Move this function up to follow CreateSelfSigned()
mdietz 2011/08/22 20:09:00 Done.
843 crypto::RSAPrivateKey* key,
844 const std::string& subject,
845 const std::string& origin,
846 uint32 serial_number,
847 base::TimeDelta valid_duration) {
848 DCHECK(key);
849
850 CERTCertificate* cert = CreateCertificate(key,
851 subject,
wtc 2011/08/19 18:18:08 Change subject to "CN=anonymous.invalid"
852 serial_number,
853 valid_duration);
854
855 if(!cert)
856 return NULL;
857
858 SECStatus ok;
859
860 // Create opaque handle used to add extensions later.
861 void* cert_handle;
862 if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) {
863 LOG(ERROR) << "Unable to get opaque handle for adding extensions";
864 return NULL;
865 }
866
867 // Create stack allocated SECItem for IA5String encoding
wtc 2011/08/19 18:18:08 Nit: remove "stack allocated". Add a period.
mdietz 2011/08/22 20:09:00 Done.
868 SECItem origin_string_item = {
869 siAsciiString,
870 (unsigned char*)origin.data(),
871 origin.size()
872 };
873
874 // IA5Encode and arena allocate SECItem
875 SECItem* asn1_origin_string;
876 if ((asn1_origin_string = SEC_ASN1EncodeItem(cert->arena,
877 NULL,
878 &origin_string_item,
879 SEC_ASN1_GET(
880 SEC_IA5StringTemplate
881 )))
882 == NULL){
wtc 2011/08/19 18:18:08 I would format this as follows: SECItem* asn1_or
mdietz 2011/08/22 20:09:00 Much cleaner, thanks. On 2011/08/19 18:18:08, wtc
883 LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension";
884 return NULL;
885 }
886
887 // Add the extension to the opaque handle
888 if((ok = CERT_AddExtension(cert_handle,
rkn 2011/08/18 22:59:41 Can you replace all instances of "if(" with "if ("
wtc 2011/08/19 18:18:08 No need to save the function return value in the '
mdietz 2011/08/22 20:09:00 Done.
889 ObCertOIDWrapper::GetInstance()->ObCertOIDTag,
890 asn1_origin_string,
891 PR_TRUE, PR_TRUE))
892 != SECSuccess){
893 LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle";
894 return NULL;
895 }
896
897 // Copy extension into x509 cert
898 if((ok = CERT_FinishExtensions(cert_handle)) != SECSuccess){
899 LOG(ERROR) << "Unable to copy extension to X509 cert";
900 return NULL;
901 }
902
903 // Sign the cert here. The logic of this method references SignCert() in NSS
904 // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert.
905
906 X509Certificate* x509_cert = SignCertificate(cert, key);
907
908 if(!x509_cert)
909 return NULL;
910
911 return x509_cert;
912 }
913
773 int X509Certificate::VerifyInternal(const std::string& hostname, 914 int X509Certificate::VerifyInternal(const std::string& hostname,
774 int flags, 915 int flags,
775 CertVerifyResult* verify_result) const { 916 CertVerifyResult* verify_result) const {
776 // Make sure that the hostname matches with the common name of the cert. 917 // Make sure that the hostname matches with the common name of the cert.
777 SECStatus status = CERT_VerifyCertName(cert_handle_, hostname.c_str()); 918 SECStatus status = CERT_VerifyCertName(cert_handle_, hostname.c_str());
778 if (status != SECSuccess) 919 if (status != SECSuccess)
779 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 920 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
780 921
781 // Make sure that the cert is valid now. 922 // Make sure that the cert is valid now.
782 SECCertTimeValidity validity = CERT_CheckCertValidTimes( 923 SECCertTimeValidity validity = CERT_CheckCertValidTimes(
(...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 1150
1010 // static 1151 // static
1011 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle, 1152 bool X509Certificate::WriteOSCertHandleToPickle(OSCertHandle cert_handle,
1012 Pickle* pickle) { 1153 Pickle* pickle) {
1013 return pickle->WriteData( 1154 return pickle->WriteData(
1014 reinterpret_cast<const char*>(cert_handle->derCert.data), 1155 reinterpret_cast<const char*>(cert_handle->derCert.data),
1015 cert_handle->derCert.len); 1156 cert_handle->derCert.len);
1016 } 1157 }
1017 1158
1018 } // namespace net 1159 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698