summaryrefslogtreecommitdiffstats
path: root/net/cert
diff options
context:
space:
mode:
Diffstat (limited to 'net/cert')
-rw-r--r--net/cert/x509_certificate.h27
-rw-r--r--net/cert/x509_certificate_ios.cc12
-rw-r--r--net/cert/x509_certificate_mac.cc139
-rw-r--r--net/cert/x509_certificate_nss.cc25
-rw-r--r--net/cert/x509_certificate_openssl.cc11
-rw-r--r--net/cert/x509_certificate_unittest.cc126
-rw-r--r--net/cert/x509_certificate_win.cc62
-rw-r--r--net/cert/x509_util.h26
-rw-r--r--net/cert/x509_util_nss.cc189
-rw-r--r--net/cert/x509_util_nss.h14
-rw-r--r--net/cert/x509_util_openssl.cc10
-rw-r--r--net/cert/x509_util_unittest.cc136
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