diff options
Diffstat (limited to 'net/cert')
-rw-r--r-- | net/cert/x509_certificate.h | 27 | ||||
-rw-r--r-- | net/cert/x509_certificate_ios.cc | 12 | ||||
-rw-r--r-- | net/cert/x509_certificate_mac.cc | 139 | ||||
-rw-r--r-- | net/cert/x509_certificate_nss.cc | 25 | ||||
-rw-r--r-- | net/cert/x509_certificate_openssl.cc | 11 | ||||
-rw-r--r-- | net/cert/x509_certificate_unittest.cc | 126 | ||||
-rw-r--r-- | net/cert/x509_certificate_win.cc | 62 | ||||
-rw-r--r-- | net/cert/x509_util.h | 26 | ||||
-rw-r--r-- | net/cert/x509_util_nss.cc | 189 | ||||
-rw-r--r-- | net/cert/x509_util_nss.h | 14 | ||||
-rw-r--r-- | net/cert/x509_util_openssl.cc | 10 | ||||
-rw-r--r-- | net/cert/x509_util_unittest.cc | 136 |
12 files changed, 261 insertions, 516 deletions
diff --git a/net/cert/x509_certificate.h b/net/cert/x509_certificate.h index b75efa7..d12c0ba 100644 --- a/net/cert/x509_certificate.h +++ b/net/cert/x509_certificate.h @@ -37,10 +37,6 @@ struct CERTCertificateStr; class Pickle; class PickleIterator; -namespace crypto { -class RSAPrivateKey; -} // namespace crypto - namespace net { class CRLSet; @@ -195,29 +191,6 @@ class NET_EXPORT X509Certificate int length, int format); - // Create a self-signed certificate containing the public key in |key|. - // Subject, serial number and validity period are given as parameters. - // The certificate is signed by the private key in |key|. The hashing - // algorithm for the signature is SHA-1. - // - // |subject| is a distinguished name defined in RFC4514. - // - // An example: - // CN=Michael Wong,O=FooBar Corporation,DC=foobar,DC=com - // - // SECURITY WARNING - // - // Using self-signed certificates has the following security risks: - // 1. Encryption without authentication and thus vulnerable to - // man-in-the-middle attacks. - // 2. Self-signed certificates cannot be revoked. - // - // Use this certificate only after the above risks are acknowledged. - static X509Certificate* CreateSelfSigned(crypto::RSAPrivateKey* key, - const std::string& subject, - uint32 serial_number, - base::TimeDelta valid_duration); - // Appends a representation of this object to the given pickle. void Persist(Pickle* pickle); diff --git a/net/cert/x509_certificate_ios.cc b/net/cert/x509_certificate_ios.cc index 32a4883..efeb54e 100644 --- a/net/cert/x509_certificate_ios.cc +++ b/net/cert/x509_certificate_ios.cc @@ -85,18 +85,6 @@ bool X509Certificate::IsIssuedByEncoded( nss_chain.cert_chain(), issuers); } -// static -X509Certificate* X509Certificate::CreateSelfSigned( - crypto::RSAPrivateKey* key, - const std::string& subject, - uint32 serial_number, - base::TimeDelta valid_duration) { - DCHECK(key); - DCHECK(!subject.empty()); - NOTIMPLEMENTED(); - return NULL; -} - void X509Certificate::GetSubjectAltName( std::vector<std::string>* dns_names, std::vector<std::string>* ip_addrs) const { diff --git a/net/cert/x509_certificate_mac.cc b/net/cert/x509_certificate_mac.cc index fd9aaca..2f8ce43 100644 --- a/net/cert/x509_certificate_mac.cc +++ b/net/cert/x509_certificate_mac.cc @@ -25,7 +25,6 @@ #include "crypto/cssm_init.h" #include "crypto/mac_security_services_lock.h" #include "crypto/nss_util.h" -#include "crypto/rsa_private_key.h" #include "net/cert/x509_util_mac.h" using base::ScopedCFTypeRef; @@ -326,144 +325,6 @@ bool X509Certificate::IsIssuedByEncoded( return false; } -// static -X509Certificate* X509Certificate::CreateSelfSigned( - crypto::RSAPrivateKey* key, - const std::string& subject, - uint32 serial_number, - base::TimeDelta valid_duration) { - DCHECK(key); - DCHECK(!subject.empty()); - - if (valid_duration.InSeconds() > kuint32max) { - LOG(ERROR) << "valid_duration too big " << valid_duration.InSeconds(); - valid_duration = base::TimeDelta::FromSeconds(kuint32max); - } - - // There is a comment in - // http://www.opensource.apple.com/source/security_certtool/security_certtool-31828/src/CertTool.cpp - // that serial_numbers being passed into CSSM_TP_SubmitCredRequest can't have - // their high bit set. We will continue though and mask it out below. - if (serial_number & 0x80000000) - LOG(ERROR) << "serial_number has high bit set " << serial_number; - - // NSS is used to parse the subject string into a set of - // CSSM_OID/string pairs. There doesn't appear to be a system routine for - // parsing Distinguished Name strings. - crypto::EnsureNSSInit(); - - CSSMOIDStringVector subject_name_oids; - ScopedCertName subject_name( - CERT_AsciiToName(const_cast<char*>(subject.c_str()))); - if (!CERTNameToCSSMOIDVector(subject_name, &subject_name_oids)) { - DLOG(ERROR) << "Unable to generate CSSMOIDMap from " << subject; - return NULL; - } - - // Convert the map of oid/string pairs into an array of - // CSSM_APPLE_TP_NAME_OIDs. - std::vector<CSSM_APPLE_TP_NAME_OID> cssm_subject_names; - for (CSSMOIDStringVector::iterator iter = subject_name_oids.begin(); - iter != subject_name_oids.end(); ++iter) { - CSSM_APPLE_TP_NAME_OID cssm_subject_name; - cssm_subject_name.oid = iter->oid_; - cssm_subject_name.string = iter->string_.c_str(); - cssm_subject_names.push_back(cssm_subject_name); - } - - if (cssm_subject_names.empty()) { - DLOG(ERROR) << "cssm_subject_names.size() == 0. Input: " << subject; - return NULL; - } - - // Set up a certificate request. - CSSM_APPLE_TP_CERT_REQUEST certReq; - memset(&certReq, 0, sizeof(certReq)); - certReq.cspHand = crypto::GetSharedCSPHandle(); - certReq.clHand = crypto::GetSharedCLHandle(); - // See comment about serial numbers above. - certReq.serialNumber = serial_number & 0x7fffffff; - certReq.numSubjectNames = cssm_subject_names.size(); - certReq.subjectNames = &cssm_subject_names[0]; - certReq.numIssuerNames = 0; // Root. - certReq.issuerNames = NULL; - certReq.issuerNameX509 = NULL; - certReq.certPublicKey = key->public_key(); - certReq.issuerPrivateKey = key->key(); - // These are the Apple defaults. - certReq.signatureAlg = CSSM_ALGID_SHA1WithRSA; - certReq.signatureOid = CSSMOID_SHA1WithRSA; - certReq.notBefore = 0; - certReq.notAfter = static_cast<uint32>(valid_duration.InSeconds()); - certReq.numExtensions = 0; - certReq.extensions = NULL; - certReq.challengeString = NULL; - - CSSM_TP_REQUEST_SET reqSet; - reqSet.NumberOfRequests = 1; - reqSet.Requests = &certReq; - - CSSM_FIELD policyId; - memset(&policyId, 0, sizeof(policyId)); - policyId.FieldOid = CSSMOID_APPLE_TP_LOCAL_CERT_GEN; - - CSSM_TP_CALLERAUTH_CONTEXT callerAuthContext; - memset(&callerAuthContext, 0, sizeof(callerAuthContext)); - callerAuthContext.Policy.NumberOfPolicyIds = 1; - callerAuthContext.Policy.PolicyIds = &policyId; - - CSSM_TP_HANDLE tp_handle = crypto::GetSharedTPHandle(); - CSSM_DATA refId; - memset(&refId, 0, sizeof(refId)); - sint32 estTime; - CSSM_RETURN crtn = CSSM_TP_SubmitCredRequest(tp_handle, NULL, - CSSM_TP_AUTHORITY_REQUEST_CERTISSUE, &reqSet, &callerAuthContext, - &estTime, &refId); - if (crtn) { - DLOG(ERROR) << "CSSM_TP_SubmitCredRequest failed " << crtn; - return NULL; - } - - CSSM_BOOL confirmRequired; - CSSM_TP_RESULT_SET* resultSet = NULL; - crtn = CSSM_TP_RetrieveCredResult(tp_handle, &refId, NULL, &estTime, - &confirmRequired, &resultSet); - ScopedEncodedCertResults scopedResults(resultSet); - crypto::CSSMFree(refId.Data); - if (crtn) { - DLOG(ERROR) << "CSSM_TP_RetrieveCredResult failed " << crtn; - return NULL; - } - - if (confirmRequired) { - // Potential leak here of resultSet. |confirmRequired| should never be - // true. - DLOG(ERROR) << "CSSM_TP_RetrieveCredResult required confirmation"; - return NULL; - } - - if (resultSet->NumberOfResults != 1) { - DLOG(ERROR) << "Unexpected number of results: " - << resultSet->NumberOfResults; - return NULL; - } - - CSSM_ENCODED_CERT* encCert = - reinterpret_cast<CSSM_ENCODED_CERT*>(resultSet->Results); - ScopedCFTypeRef<SecCertificateRef> scoped_cert; - SecCertificateRef certificate_ref = NULL; - OSStatus os_status = - SecCertificateCreateFromData(&encCert->CertBlob, encCert->CertType, - encCert->CertEncoding, &certificate_ref); - if (os_status != 0) { - OSSTATUS_DLOG(ERROR, os_status) << "SecCertificateCreateFromData failed"; - return NULL; - } - scoped_cert.reset(certificate_ref); - - return CreateFromHandle(scoped_cert, X509Certificate::OSCertHandles()); -} - void X509Certificate::GetSubjectAltName( std::vector<std::string>* dns_names, std::vector<std::string>* ip_addrs) const { diff --git a/net/cert/x509_certificate_nss.cc b/net/cert/x509_certificate_nss.cc index bbc448f..8448a49 100644 --- a/net/cert/x509_certificate_nss.cc +++ b/net/cert/x509_certificate_nss.cc @@ -20,7 +20,6 @@ #include "base/strings/stringprintf.h" #include "base/time.h" #include "crypto/nss_util.h" -#include "crypto/rsa_private_key.h" #include "crypto/scoped_nss_types.h" #include "net/cert/x509_util_nss.h" @@ -114,30 +113,6 @@ std::string X509Certificate::GetDefaultNickname(CertType type) const { return result; } -// static -X509Certificate* X509Certificate::CreateSelfSigned( - crypto::RSAPrivateKey* key, - const std::string& subject, - uint32 serial_number, - base::TimeDelta valid_duration) { - DCHECK(key); - base::Time not_valid_before = base::Time::Now(); - base::Time not_valid_after = not_valid_before + valid_duration; - CERTCertificate* cert = x509_util::CreateSelfSignedCert(key->public_key(), - key->key(), - subject, - serial_number, - not_valid_before, - not_valid_after); - if (!cert) - return NULL; - - X509Certificate* x509_cert = X509Certificate::CreateFromHandle( - cert, X509Certificate::OSCertHandles()); - CERT_DestroyCertificate(cert); - return x509_cert; -} - void X509Certificate::GetSubjectAltName( std::vector<std::string>* dns_names, std::vector<std::string>* ip_addrs) const { diff --git a/net/cert/x509_certificate_openssl.cc b/net/cert/x509_certificate_openssl.cc index 82475ff..bdf2bf2 100644 --- a/net/cert/x509_certificate_openssl.cc +++ b/net/cert/x509_certificate_openssl.cc @@ -362,17 +362,6 @@ X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( return results; } -// static -X509Certificate* X509Certificate::CreateSelfSigned( - crypto::RSAPrivateKey* key, - const std::string& subject, - uint32 serial_number, - base::TimeDelta valid_duration) { - // TODO(port): Implement. See http://crbug.com/91512. - NOTIMPLEMENTED(); - return NULL; -} - void X509Certificate::GetSubjectAltName( std::vector<std::string>* dns_names, std::vector<std::string>* ip_addrs) const { diff --git a/net/cert/x509_certificate_unittest.cc b/net/cert/x509_certificate_unittest.cc index 427431d..a457538 100644 --- a/net/cert/x509_certificate_unittest.cc +++ b/net/cert/x509_certificate_unittest.cc @@ -795,132 +795,6 @@ TEST(X509CertificateTest, GetDefaultNickname) { } #endif -#if !defined(OS_IOS) // TODO(ios): Unable to create certificates. -#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX) -// This test creates a self-signed cert from a private key and then verify the -// content of the certificate. -TEST(X509CertificateTest, CreateSelfSigned) { - scoped_ptr<crypto::RSAPrivateKey> private_key( - crypto::RSAPrivateKey::Create(1024)); - scoped_refptr<X509Certificate> cert = - X509Certificate::CreateSelfSigned( - private_key.get(), "CN=subject", 1, base::TimeDelta::FromDays(1)); - - EXPECT_EQ("subject", cert->subject().GetDisplayName()); - EXPECT_FALSE(cert->HasExpired()); - - const uint8 private_key_info[] = { - 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, - 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, - 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, - 0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, - 0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, - 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, - 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, - 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, - 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, - 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, - 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, - 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, - 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, - 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, - 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, - 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, - 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, - 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, - 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, - 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, - 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, - 0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, - 0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb, - 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7, - 0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, - 0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95, - 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6, - 0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, - 0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e, - 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b, - 0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, - 0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa, - 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38, - 0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, - 0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e, - 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e, - 0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, - 0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00, - 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c, - 0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, - 0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82, - 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89, - 0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, - 0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8, - 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2, - 0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, - 0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1, - 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72, - 0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, - 0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62, - 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c, - 0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, - 0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6, - 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b, - 0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, - 0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9, - 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda, - 0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, - 0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93, - 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae, - 0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, - 0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17, - 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41, - 0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, - 0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1, - 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0, - 0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, - 0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd, - 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69, - 0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, - 0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7, - 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f, - 0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, - 0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99, - 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6, - 0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, - 0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb, - 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca, - 0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, - 0xb1, 0xc5, 0x15, 0xf3 - }; - - std::vector<uint8> input; - input.resize(sizeof(private_key_info)); - memcpy(&input.front(), private_key_info, sizeof(private_key_info)); - - private_key.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); - ASSERT_TRUE(private_key.get()); - - cert = X509Certificate::CreateSelfSigned( - private_key.get(), "CN=subject", 1, base::TimeDelta::FromDays(1)); - - EXPECT_EQ("subject", cert->subject().GetDisplayName()); - EXPECT_FALSE(cert->HasExpired()); -} - -TEST(X509CertificateTest, GetDEREncoded) { - scoped_ptr<crypto::RSAPrivateKey> private_key( - crypto::RSAPrivateKey::Create(1024)); - scoped_refptr<X509Certificate> cert = - X509Certificate::CreateSelfSigned( - private_key.get(), "CN=subject", 0, base::TimeDelta::FromDays(1)); - - std::string der_cert; - EXPECT_TRUE(X509Certificate::GetDEREncoded(cert->os_cert_handle(), - &der_cert)); - EXPECT_FALSE(der_cert.empty()); -} -#endif -#endif // !defined(OS_IOS) - class X509CertificateParseTest : public testing::TestWithParam<CertificateFormatTestData> { public: diff --git a/net/cert/x509_certificate_win.cc b/net/cert/x509_certificate_win.cc index 02e4df6..9c8901d 100644 --- a/net/cert/x509_certificate_win.cc +++ b/net/cert/x509_certificate_win.cc @@ -13,7 +13,6 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "crypto/capi_util.h" -#include "crypto/rsa_private_key.h" #include "crypto/scoped_capi_types.h" #include "net/base/net_errors.h" @@ -165,67 +164,6 @@ void X509Certificate::Initialize() { reinterpret_cast<char*>(serial_bytes.get()), serial->cbData); } -// static -X509Certificate* X509Certificate::CreateSelfSigned( - crypto::RSAPrivateKey* key, - const std::string& subject, - uint32 serial_number, - base::TimeDelta valid_duration) { - // Get the ASN.1 encoding of the certificate subject. - std::wstring w_subject = ASCIIToWide(subject); - DWORD encoded_subject_length = 0; - if (!CertStrToName( - X509_ASN_ENCODING, - w_subject.c_str(), - CERT_X500_NAME_STR, NULL, NULL, &encoded_subject_length, NULL)) { - return NULL; - } - - scoped_ptr<BYTE[]> encoded_subject(new BYTE[encoded_subject_length]); - if (!CertStrToName( - X509_ASN_ENCODING, - w_subject.c_str(), - CERT_X500_NAME_STR, NULL, - encoded_subject.get(), - &encoded_subject_length, NULL)) { - return NULL; - } - - CERT_NAME_BLOB subject_name; - memset(&subject_name, 0, sizeof(subject_name)); - subject_name.cbData = encoded_subject_length; - subject_name.pbData = encoded_subject.get(); - - CRYPT_ALGORITHM_IDENTIFIER sign_algo; - memset(&sign_algo, 0, sizeof(sign_algo)); - sign_algo.pszObjId = szOID_RSA_SHA1RSA; - - base::Time not_before = base::Time::Now(); - base::Time not_after = not_before + valid_duration; - base::Time::Exploded exploded; - - // Create the system time structs representing our exploded times. - not_before.UTCExplode(&exploded); - SYSTEMTIME start_time; - ExplodedTimeToSystemTime(exploded, &start_time); - not_after.UTCExplode(&exploded); - SYSTEMTIME end_time; - ExplodedTimeToSystemTime(exploded, &end_time); - - PCCERT_CONTEXT cert_handle = - CertCreateSelfSignCertificate(key->provider(), &subject_name, - CERT_CREATE_SELFSIGN_NO_KEY_INFO, NULL, - &sign_algo, &start_time, &end_time, NULL); - DCHECK(cert_handle) << "Failed to create self-signed certificate: " - << GetLastError(); - if (!cert_handle) - return NULL; - - X509Certificate* cert = CreateFromHandle(cert_handle, OSCertHandles()); - FreeOSCertHandle(cert_handle); - return cert; -} - void X509Certificate::GetSubjectAltName( std::vector<std::string>* dns_names, std::vector<std::string>* ip_addrs) const { diff --git a/net/cert/x509_util.h b/net/cert/x509_util.h index 50ffc7f..c618fe9 100644 --- a/net/cert/x509_util.h +++ b/net/cert/x509_util.h @@ -13,6 +13,7 @@ namespace crypto { class ECPrivateKey; +class RSAPrivateKey; } namespace net { @@ -44,6 +45,31 @@ NET_EXPORT_PRIVATE bool CreateDomainBoundCertEC( base::Time not_valid_after, std::string* der_cert); +// Create a self-signed certificate containing the public key in |key|. +// Subject, serial number and validity period are given as parameters. +// The certificate is signed by the private key in |key|. The hashing +// algorithm for the signature is SHA-1. +// +// |subject| is a distinguished name defined in RFC4514. +// +// An example: +// CN=Michael Wong,O=FooBar Corporation,DC=foobar,DC=com +// +// SECURITY WARNING +// +// Using self-signed certificates has the following security risks: +// 1. Encryption without authentication and thus vulnerable to +// man-in-the-middle attacks. +// 2. Self-signed certificates cannot be revoked. +// +// Use this certificate only after the above risks are acknowledged. +NET_EXPORT bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, + const std::string& subject, + uint32 serial_number, + base::Time not_valid_before, + base::Time not_valid_after, + std::string* der_cert); + // Comparator for use in STL algorithms that will sort client certificates by // order of preference. // Returns true if |a| is more preferable than |b|, allowing it to be used diff --git a/net/cert/x509_util_nss.cc b/net/cert/x509_util_nss.cc index 5666935..f8fbd6f 100644 --- a/net/cert/x509_util_nss.cc +++ b/net/cert/x509_util_nss.cc @@ -24,6 +24,7 @@ #include "crypto/ec_private_key.h" #include "crypto/nss_util.h" #include "crypto/nss_util_internal.h" +#include "crypto/rsa_private_key.h" #include "crypto/scoped_nss_types.h" #include "crypto/third_party/nss/chromium-nss.h" #include "net/cert/x509_certificate.h" @@ -182,80 +183,6 @@ bool SignCertificate( return true; } -bool CreateDomainBoundCertInternal( - SECKEYPublicKey* public_key, - SECKEYPrivateKey* private_key, - const std::string& domain, - uint32 serial_number, - base::Time not_valid_before, - base::Time not_valid_after, - std::string* der_cert) { - CERTCertificate* cert = CreateCertificate(public_key, - "CN=anonymous.invalid", - serial_number, - not_valid_before, - not_valid_after); - - if (!cert) - return false; - - // Create opaque handle used to add extensions later. - void* cert_handle; - if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { - LOG(ERROR) << "Unable to get opaque handle for adding extensions"; - CERT_DestroyCertificate(cert); - return false; - } - - // Create SECItem for IA5String encoding. - SECItem domain_string_item = { - siAsciiString, - (unsigned char*)domain.data(), - static_cast<unsigned>(domain.size()) - }; - - // IA5Encode and arena allocate SECItem - SECItem* asn1_domain_string = SEC_ASN1EncodeItem( - cert->arena, NULL, &domain_string_item, - SEC_ASN1_GET(SEC_IA5StringTemplate)); - if (asn1_domain_string == NULL) { - LOG(ERROR) << "Unable to get ASN1 encoding for domain in domain_bound_cert" - " extension"; - CERT_DestroyCertificate(cert); - return false; - } - - // Add the extension to the opaque handle - if (CERT_AddExtension( - cert_handle, - DomainBoundCertOIDWrapper::GetInstance()->domain_bound_cert_oid_tag(), - asn1_domain_string, PR_TRUE, PR_TRUE) != SECSuccess){ - LOG(ERROR) << "Unable to add domain bound cert extension to opaque handle"; - CERT_DestroyCertificate(cert); - return false; - } - - // Copy extension into x509 cert - if (CERT_FinishExtensions(cert_handle) != SECSuccess){ - LOG(ERROR) << "Unable to copy extension to X509 cert"; - CERT_DestroyCertificate(cert); - return false; - } - - if (!SignCertificate(cert, private_key)) { - CERT_DestroyCertificate(cert); - return false; - } - - DCHECK(cert->derCert.len); - // XXX copied from X509Certificate::GetDEREncoded - der_cert->clear(); - der_cert->append(reinterpret_cast<char*>(cert->derCert.data), - cert->derCert.len); - CERT_DestroyCertificate(cert); - return true; -} - #if defined(USE_NSS) || defined(OS_IOS) // Callback for CERT_DecodeCertPackage(), used in // CreateOSCertHandlesFromBytes(). @@ -312,27 +239,30 @@ CERTName* CreateCertNameFromEncoded(PLArenaPool* arena, namespace x509_util { -CERTCertificate* CreateSelfSignedCert( - SECKEYPublicKey* public_key, - SECKEYPrivateKey* private_key, - const std::string& subject, - uint32 serial_number, - base::Time not_valid_before, - base::Time not_valid_after) { - CERTCertificate* cert = CreateCertificate(public_key, +bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, + const std::string& subject, + uint32 serial_number, + base::Time not_valid_before, + base::Time not_valid_after, + std::string* der_cert) { + DCHECK(key); + CERTCertificate* cert = CreateCertificate(key->public_key(), subject, serial_number, not_valid_before, not_valid_after); if (!cert) - return NULL; + return false; - if (!SignCertificate(cert, private_key)) { + if (!SignCertificate(cert, key->key())) { CERT_DestroyCertificate(cert); - return NULL; + return false; } - return cert; + der_cert->assign(reinterpret_cast<char*>(cert->derCert.data), + cert->derCert.len); + CERT_DestroyCertificate(cert); + return true; } bool IsSupportedValidityRange(base::Time not_valid_before, @@ -348,21 +278,80 @@ bool IsSupportedValidityRange(base::Time not_valid_before, return true; } -bool CreateDomainBoundCertEC( - crypto::ECPrivateKey* key, - const std::string& domain, - uint32 serial_number, - base::Time not_valid_before, - base::Time not_valid_after, - std::string* der_cert) { +bool CreateDomainBoundCertEC(crypto::ECPrivateKey* key, + const std::string& domain, + uint32 serial_number, + base::Time not_valid_before, + base::Time not_valid_after, + std::string* der_cert) { DCHECK(key); - return CreateDomainBoundCertInternal(key->public_key(), - key->key(), - domain, - serial_number, - not_valid_before, - not_valid_after, - der_cert); + + CERTCertificate* cert = CreateCertificate(key->public_key(), + "CN=anonymous.invalid", + serial_number, + not_valid_before, + not_valid_after); + + if (!cert) + return false; + + // Create opaque handle used to add extensions later. + void* cert_handle; + if ((cert_handle = CERT_StartCertExtensions(cert)) == NULL) { + LOG(ERROR) << "Unable to get opaque handle for adding extensions"; + CERT_DestroyCertificate(cert); + return false; + } + + // Create SECItem for IA5String encoding. + SECItem domain_string_item = { + siAsciiString, + (unsigned char*)domain.data(), + static_cast<unsigned>(domain.size()) + }; + + // IA5Encode and arena allocate SECItem + SECItem* asn1_domain_string = SEC_ASN1EncodeItem( + cert->arena, NULL, &domain_string_item, + SEC_ASN1_GET(SEC_IA5StringTemplate)); + if (asn1_domain_string == NULL) { + LOG(ERROR) << "Unable to get ASN1 encoding for domain in domain_bound_cert" + " extension"; + CERT_DestroyCertificate(cert); + return false; + } + + // Add the extension to the opaque handle + if (CERT_AddExtension( + cert_handle, + DomainBoundCertOIDWrapper::GetInstance()->domain_bound_cert_oid_tag(), + asn1_domain_string, + PR_TRUE, + PR_TRUE) != SECSuccess){ + LOG(ERROR) << "Unable to add domain bound cert extension to opaque handle"; + CERT_DestroyCertificate(cert); + return false; + } + + // Copy extension into x509 cert + if (CERT_FinishExtensions(cert_handle) != SECSuccess){ + LOG(ERROR) << "Unable to copy extension to X509 cert"; + CERT_DestroyCertificate(cert); + return false; + } + + if (!SignCertificate(cert, key->key())) { + CERT_DestroyCertificate(cert); + return false; + } + + DCHECK(cert->derCert.len); + // XXX copied from X509Certificate::GetDEREncoded + der_cert->clear(); + der_cert->append(reinterpret_cast<char*>(cert->derCert.data), + cert->derCert.len); + CERT_DestroyCertificate(cert); + return true; } #if defined(USE_NSS) || defined(OS_IOS) diff --git a/net/cert/x509_util_nss.h b/net/cert/x509_util_nss.h index 5ad752e..493e661 100644 --- a/net/cert/x509_util_nss.h +++ b/net/cert/x509_util_nss.h @@ -19,25 +19,11 @@ typedef struct CERTNameStr CERTName; typedef struct PK11SlotInfoStr PK11SlotInfo; typedef struct PLArenaPool PLArenaPool; typedef struct SECItemStr SECItem; -typedef struct SECKEYPrivateKeyStr SECKEYPrivateKey; -typedef struct SECKEYPublicKeyStr SECKEYPublicKey; namespace net { namespace x509_util { -// Creates a self-signed certificate containing |public_key|. Subject, serial -// number and validity period are given as parameters. The certificate is -// signed by |private_key|. The hashing algorithm for the signature is SHA-1. -// |subject| is a distinguished name defined in RFC4514. -NET_EXPORT_PRIVATE CERTCertificate* CreateSelfSignedCert( - SECKEYPublicKey* public_key, - SECKEYPrivateKey* private_key, - const std::string& subject, - uint32 serial_number, - base::Time not_valid_before, - base::Time not_valid_after); - #if defined(USE_NSS) || defined(OS_IOS) // Parses the Principal attribute from |name| and outputs the result in // |principal|. diff --git a/net/cert/x509_util_openssl.cc b/net/cert/x509_util_openssl.cc index e98c2a0..e4dec99 100644 --- a/net/cert/x509_util_openssl.cc +++ b/net/cert/x509_util_openssl.cc @@ -59,6 +59,16 @@ bool CreateDomainBoundCertEC( return false; } +bool CreateSelfSignedCert(crypto::RSAPrivateKey* key, + const std::string& common_name, + uint32 serial_number, + base::Time not_valid_before, + base::Time not_valid_after, + std::string* der_encoded) { + NOTIMPLEMENTED(); + return false; +} + bool ParsePrincipalKeyAndValueByIndex(X509_NAME* name, int index, std::string* key, diff --git a/net/cert/x509_util_unittest.cc b/net/cert/x509_util_unittest.cc index ee42f1c..e0c1ec6 100644 --- a/net/cert/x509_util_unittest.cc +++ b/net/cert/x509_util_unittest.cc @@ -6,7 +6,10 @@ #include <algorithm> +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" #include "base/time.h" +#include "crypto/rsa_private_key.h" #include "net/cert/x509_certificate.h" #include "testing/gtest/include/gtest/gtest.h" @@ -49,6 +52,139 @@ TEST(X509UtilTest, SortClientCertificates) { ASSERT_FALSE(certs[5].get()); } +#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX) +// This test creates a self-signed cert from a private key and then verify the +// content of the certificate. +TEST(X509UtilTest, CreateSelfSigned) { + scoped_ptr<crypto::RSAPrivateKey> private_key( + crypto::RSAPrivateKey::Create(1024)); + + ASSERT_TRUE(private_key.get()); + + std::string der_cert; + ASSERT_TRUE(x509_util::CreateSelfSignedCert( + private_key.get(), + "CN=subject", + 1, + base::Time::Now(), + base::Time::Now() + base::TimeDelta::FromDays(1), + &der_cert)); + + scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes( + der_cert.data(), der_cert.size())); + ASSERT_TRUE(cert.get()); + + EXPECT_EQ("subject", cert->subject().GetDisplayName()); + EXPECT_FALSE(cert->HasExpired()); + + cert = NULL; + + const uint8 private_key_info[] = { + 0x30, 0x82, 0x02, 0x78, 0x02, 0x01, 0x00, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, + 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x04, 0x82, + 0x02, 0x62, 0x30, 0x82, 0x02, 0x5e, 0x02, 0x01, + 0x00, 0x02, 0x81, 0x81, 0x00, 0xb8, 0x7f, 0x2b, + 0x20, 0xdc, 0x7c, 0x9b, 0x0c, 0xdc, 0x51, 0x61, + 0x99, 0x0d, 0x36, 0x0f, 0xd4, 0x66, 0x88, 0x08, + 0x55, 0x84, 0xd5, 0x3a, 0xbf, 0x2b, 0xa4, 0x64, + 0x85, 0x7b, 0x0c, 0x04, 0x13, 0x3f, 0x8d, 0xf4, + 0xbc, 0x38, 0x0d, 0x49, 0xfe, 0x6b, 0xc4, 0x5a, + 0xb0, 0x40, 0x53, 0x3a, 0xd7, 0x66, 0x09, 0x0f, + 0x9e, 0x36, 0x74, 0x30, 0xda, 0x8a, 0x31, 0x4f, + 0x1f, 0x14, 0x50, 0xd7, 0xc7, 0x20, 0x94, 0x17, + 0xde, 0x4e, 0xb9, 0x57, 0x5e, 0x7e, 0x0a, 0xe5, + 0xb2, 0x65, 0x7a, 0x89, 0x4e, 0xb6, 0x47, 0xff, + 0x1c, 0xbd, 0xb7, 0x38, 0x13, 0xaf, 0x47, 0x85, + 0x84, 0x32, 0x33, 0xf3, 0x17, 0x49, 0xbf, 0xe9, + 0x96, 0xd0, 0xd6, 0x14, 0x6f, 0x13, 0x8d, 0xc5, + 0xfc, 0x2c, 0x72, 0xba, 0xac, 0xea, 0x7e, 0x18, + 0x53, 0x56, 0xa6, 0x83, 0xa2, 0xce, 0x93, 0x93, + 0xe7, 0x1f, 0x0f, 0xe6, 0x0f, 0x02, 0x03, 0x01, + 0x00, 0x01, 0x02, 0x81, 0x80, 0x03, 0x61, 0x89, + 0x37, 0xcb, 0xf2, 0x98, 0xa0, 0xce, 0xb4, 0xcb, + 0x16, 0x13, 0xf0, 0xe6, 0xaf, 0x5c, 0xc5, 0xa7, + 0x69, 0x71, 0xca, 0xba, 0x8d, 0xe0, 0x4d, 0xdd, + 0xed, 0xb8, 0x48, 0x8b, 0x16, 0x93, 0x36, 0x95, + 0xc2, 0x91, 0x40, 0x65, 0x17, 0xbd, 0x7f, 0xd6, + 0xad, 0x9e, 0x30, 0x28, 0x46, 0xe4, 0x3e, 0xcc, + 0x43, 0x78, 0xf9, 0xfe, 0x1f, 0x33, 0x23, 0x1e, + 0x31, 0x12, 0x9d, 0x3c, 0xa7, 0x08, 0x82, 0x7b, + 0x7d, 0x25, 0x4e, 0x5e, 0x19, 0xa8, 0x9b, 0xed, + 0x86, 0xb2, 0xcb, 0x3c, 0xfe, 0x4e, 0xa1, 0xfa, + 0x62, 0x87, 0x3a, 0x17, 0xf7, 0x60, 0xec, 0x38, + 0x29, 0xe8, 0x4f, 0x34, 0x9f, 0x76, 0x9d, 0xee, + 0xa3, 0xf6, 0x85, 0x6b, 0x84, 0x43, 0xc9, 0x1e, + 0x01, 0xff, 0xfd, 0xd0, 0x29, 0x4c, 0xfa, 0x8e, + 0x57, 0x0c, 0xc0, 0x71, 0xa5, 0xbb, 0x88, 0x46, + 0x29, 0x5c, 0xc0, 0x4f, 0x01, 0x02, 0x41, 0x00, + 0xf5, 0x83, 0xa4, 0x64, 0x4a, 0xf2, 0xdd, 0x8c, + 0x2c, 0xed, 0xa8, 0xd5, 0x60, 0x5a, 0xe4, 0xc7, + 0xcc, 0x61, 0xcd, 0x38, 0x42, 0x20, 0xd3, 0x82, + 0x18, 0xf2, 0x35, 0x00, 0x72, 0x2d, 0xf7, 0x89, + 0x80, 0x67, 0xb5, 0x93, 0x05, 0x5f, 0xdd, 0x42, + 0xba, 0x16, 0x1a, 0xea, 0x15, 0xc6, 0xf0, 0xb8, + 0x8c, 0xbc, 0xbf, 0x54, 0x9e, 0xf1, 0xc1, 0xb2, + 0xb3, 0x8b, 0xb6, 0x26, 0x02, 0x30, 0xc4, 0x81, + 0x02, 0x41, 0x00, 0xc0, 0x60, 0x62, 0x80, 0xe1, + 0x22, 0x78, 0xf6, 0x9d, 0x83, 0x18, 0xeb, 0x72, + 0x45, 0xd7, 0xc8, 0x01, 0x7f, 0xa9, 0xca, 0x8f, + 0x7d, 0xd6, 0xb8, 0x31, 0x2b, 0x84, 0x7f, 0x62, + 0xd9, 0xa9, 0x22, 0x17, 0x7d, 0x06, 0x35, 0x6c, + 0xf3, 0xc1, 0x94, 0x17, 0x85, 0x5a, 0xaf, 0x9c, + 0x5c, 0x09, 0x3c, 0xcf, 0x2f, 0x44, 0x9d, 0xb6, + 0x52, 0x68, 0x5f, 0xf9, 0x59, 0xc8, 0x84, 0x2b, + 0x39, 0x22, 0x8f, 0x02, 0x41, 0x00, 0xb2, 0x04, + 0xe2, 0x0e, 0x56, 0xca, 0x03, 0x1a, 0xc0, 0xf9, + 0x12, 0x92, 0xa5, 0x6b, 0x42, 0xb8, 0x1c, 0xda, + 0x4d, 0x93, 0x9d, 0x5f, 0x6f, 0xfd, 0xc5, 0x58, + 0xda, 0x55, 0x98, 0x74, 0xfc, 0x28, 0x17, 0x93, + 0x1b, 0x75, 0x9f, 0x50, 0x03, 0x7f, 0x7e, 0xae, + 0xc8, 0x95, 0x33, 0x75, 0x2c, 0xd6, 0xa4, 0x35, + 0xb8, 0x06, 0x03, 0xba, 0x08, 0x59, 0x2b, 0x17, + 0x02, 0xdc, 0x4c, 0x7a, 0x50, 0x01, 0x02, 0x41, + 0x00, 0x9d, 0xdb, 0x39, 0x59, 0x09, 0xe4, 0x30, + 0xa0, 0x24, 0xf5, 0xdb, 0x2f, 0xf0, 0x2f, 0xf1, + 0x75, 0x74, 0x0d, 0x5e, 0xb5, 0x11, 0x73, 0xb0, + 0x0a, 0xaa, 0x86, 0x4c, 0x0d, 0xff, 0x7e, 0x1d, + 0xb4, 0x14, 0xd4, 0x09, 0x91, 0x33, 0x5a, 0xfd, + 0xa0, 0x58, 0x80, 0x9b, 0xbe, 0x78, 0x2e, 0x69, + 0x82, 0x15, 0x7c, 0x72, 0xf0, 0x7b, 0x18, 0x39, + 0xff, 0x6e, 0xeb, 0xc6, 0x86, 0xf5, 0xb4, 0xc7, + 0x6f, 0x02, 0x41, 0x00, 0x8d, 0x1a, 0x37, 0x0f, + 0x76, 0xc4, 0x82, 0xfa, 0x5c, 0xc3, 0x79, 0x35, + 0x3e, 0x70, 0x8a, 0xbf, 0x27, 0x49, 0xb0, 0x99, + 0x63, 0xcb, 0x77, 0x5f, 0xa8, 0x82, 0x65, 0xf6, + 0x03, 0x52, 0x51, 0xf1, 0xae, 0x2e, 0x05, 0xb3, + 0xc6, 0xa4, 0x92, 0xd1, 0xce, 0x6c, 0x72, 0xfb, + 0x21, 0xb3, 0x02, 0x87, 0xe4, 0xfd, 0x61, 0xca, + 0x00, 0x42, 0x19, 0xf0, 0xda, 0x5a, 0x53, 0xe3, + 0xb1, 0xc5, 0x15, 0xf3 + }; + + std::vector<uint8> input; + input.resize(sizeof(private_key_info)); + memcpy(&input.front(), private_key_info, sizeof(private_key_info)); + + private_key.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(input)); + ASSERT_TRUE(private_key.get()); + + ASSERT_TRUE(x509_util::CreateSelfSignedCert( + private_key.get(), + "CN=subject", + 1, + base::Time::Now(), + base::Time::Now() + base::TimeDelta::FromDays(1), + &der_cert)); + + cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()); + ASSERT_TRUE(cert.get()); + + EXPECT_EQ("subject", cert->subject().GetDisplayName()); + EXPECT_FALSE(cert->HasExpired()); +} +#endif + } // namespace x509_util } // namespace net |