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

Unified 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: Changed ObCertOIDWrapper from a Singleton to a LeakySingleton to avoid a runtime error. 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 side-by-side diff with in-line comments
Download patch
Index: net/base/x509_certificate_nss.cc
diff --git a/net/base/x509_certificate_nss.cc b/net/base/x509_certificate_nss.cc
index 7224020cb44e528318c204f10f3d6e70ff0dced2..f35c7a2426abf4915440d112ba416520b40327d9 100644
--- a/net/base/x509_certificate_nss.cc
+++ b/net/base/x509_certificate_nss.cc
@@ -18,6 +18,7 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
+#include "base/memory/singleton.h"
#include "base/pickle.h"
#include "base/time.h"
#include "crypto/nss_util.h"
@@ -31,6 +32,48 @@ namespace net {
namespace {
+class ObCertOIDWrapper {
+ public:
+ static ObCertOIDWrapper* GetInstance() {
+ return Singleton<ObCertOIDWrapper,
+ LeakySingletonTraits<ObCertOIDWrapper> >::get();
+ }
wtc 2011/08/23 01:32:21 I would format this method as follows: static O
mdietz 2011/08/23 20:52:56 Done.
+
+ SECOidTag ob_cert_oid_tag() const {
+ return ob_cert_oid_tag_;
+ }
+
+ private:
+ SECOidTag ob_cert_oid_tag_;
+
+ ObCertOIDWrapper();
+
+ friend struct DefaultSingletonTraits<ObCertOIDWrapper>;
+
+ DISALLOW_COPY_AND_ASSIGN(ObCertOIDWrapper);
+};
wtc 2011/08/23 01:32:21 Please fix the indentation in this class. "public
mdietz 2011/08/23 20:52:56 Done.
+
+ObCertOIDWrapper::ObCertOIDWrapper()
+ : ob_cert_oid_tag_(SEC_OID_UNKNOWN) {
wtc 2011/08/23 01:32:21 The Style Guide recommends indenting the colon of
mdietz 2011/08/23 20:52:56 Done.
+ // 1.3.6.1.4.1.11129.2.1.6
+ // (iso.org.dod.internet.private.enterprises.google.googleSecurity.
+ // certificateExtensions.originBoundCertificate)
+ static const uint8 kObCertOID[] = {
+ 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, 0x79, 0x02, 0x01, 0x06
+ };
+ SECOidData oid_data;
+ memset(&oid_data, 0, sizeof(oid_data));
+ oid_data.oid.data = const_cast<uint8*>(kObCertOID);
+ oid_data.oid.len = sizeof(kObCertOID);
+ oid_data.offset = SEC_OID_UNKNOWN;
+ oid_data.desc = "Origin Bound Certificate";
+ oid_data.mechanism = CKM_INVALID_MECHANISM;
+ oid_data.supportedExtension = SUPPORTED_CERT_EXTENSION;
+ ob_cert_oid_tag_ = SECOID_AddEntry(&oid_data);
+ if (ob_cert_oid_tag_ == SEC_OID_UNKNOWN)
+ LOG(ERROR) << "OB_CERT OID tag creation failed";
+}
+
class ScopedCERTCertificatePolicies {
public:
explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies)
@@ -623,14 +666,16 @@ void X509Certificate::Initialize() {
serial_number_ = serial_number_.substr(1, serial_number_.size() - 1);
}
-// static
-X509Certificate* X509Certificate::CreateSelfSigned(
+// Creates a Certificate object that may be passed to the SignCertificate
+// method to generate an X509 certificate.
+// Returns NULL if an error is encountered in the certificate creation
+// process.
+// Caller responsible for freeing returned certificate object.
+static CERTCertificate* CreateCertificate(
crypto::RSAPrivateKey* key,
const std::string& subject,
uint32 serial_number,
base::TimeDelta valid_duration) {
- DCHECK(key);
-
// Create info about public key.
CERTSubjectPublicKeyInfo* spki =
SECKEY_CreateSubjectPublicKeyInfo(key->public_key());
@@ -668,12 +713,24 @@ X509Certificate* X509Certificate::CreateSelfSigned(
CERT_DestroyValidity(validity);
CERT_DestroyCertificateRequest(cert_request);
- if (!cert)
- return NULL;
-
- // Sign the cert here. The logic of this method references SignCert() in NSS
- // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert.
+ return cert;
+}
+// Signs a certificate object, with |key| generating a new X509Certificate
+// and destroying the passed certificate object (even when NULL is returned).
+// The logic of this method references SignCert() in NSS utility certutil:
+// http://mxr.mozilla.org/security/ident?i=SignCert.
+// Returns NULL if an error is encountered in the certificate signing
+// process.
+// Caller responsible for freeing returned X509Certificate object.
+//
+// TODO: change this function to return
+// a success/failure status, and not create an X509Certificate
+// object, and not destroy |cert| on failure. Let the caller
+// create the X509Certificate object and destroy |cert|.
+static X509Certificate* SignCertificate(
+ CERTCertificate* cert,
+ crypto::RSAPrivateKey* key) {
// |arena| is used to encode the cert.
PRArenaPool* arena = cert->arena;
SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->key()->keyType,
@@ -722,11 +779,91 @@ X509Certificate* X509Certificate::CreateSelfSigned(
// Save the signed result to the cert.
cert->derCert = *result;
- X509Certificate* x509_cert = CreateFromHandle(cert, OSCertHandles());
+ X509Certificate* x509_cert =
+ X509Certificate::CreateFromHandle(cert, X509Certificate::OSCertHandles());
wtc 2011/08/23 01:32:21 Nit: indent this line by four spaces.
mdietz 2011/08/23 20:52:56 Done.
CERT_DestroyCertificate(cert);
return x509_cert;
}
+X509Certificate* X509Certificate::CreateSelfSigned(
wtc 2011/08/23 01:32:21 Resurrect the "// static" comment for this method
mdietz 2011/08/23 20:52:56 Done.
+ crypto::RSAPrivateKey* key,
+ const std::string& subject,
+ uint32 serial_number,
+ base::TimeDelta valid_duration) {
+ DCHECK(key);
+
+ CERTCertificate* cert = CreateCertificate(key,
+ subject,
+ serial_number,
+ valid_duration);
+
+ if(!cert)
wtc 2011/08/23 01:32:21 Add a space after "if" here and on line 820 below.
mdietz 2011/08/23 20:52:56 Done.
+ return NULL;
+
+ X509Certificate* x509_cert = SignCertificate(cert, key);
+
+ return x509_cert;
+}
+
+X509Certificate* X509Certificate::CreateOriginBound(
+ crypto::RSAPrivateKey* key,
+ const std::string& origin,
+ uint32 serial_number,
+ base::TimeDelta valid_duration) {
+ DCHECK(key);
+
+ CERTCertificate* cert = CreateCertificate(key,
+ "CN=anonymous.invalid",
+ serial_number,
+ valid_duration);
+
+ if(!cert)
+ return NULL;
+
+ // 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";
+ return NULL;
+ }
+
+ // Create SECItem for IA5String encoding.
+ SECItem origin_string_item = {
+ siAsciiString,
+ (unsigned char*)origin.data(),
+ origin.size()
+ };
+
+ // IA5Encode and arena allocate SECItem
+ SECItem* asn1_origin_string = SEC_ASN1EncodeItem(
+ cert->arena, NULL, &origin_string_item,
+ SEC_ASN1_GET(SEC_IA5StringTemplate));
+ if (asn1_origin_string == NULL) {
+ LOG(ERROR) << "Unable to get ASN1 encoding for origin in ob_cert extension";
+ return NULL;
+ }
+
+ // Add the extension to the opaque handle
+ if (CERT_AddExtension(cert_handle,
+ ObCertOIDWrapper::GetInstance()->ob_cert_oid_tag(),
+ asn1_origin_string,
+ PR_TRUE, PR_TRUE)
+ != SECSuccess){
wtc 2011/08/23 01:32:21 Nit: move this to the previous line.
mdietz 2011/08/23 20:52:56 Done.
+ LOG(ERROR) << "Unable to add origin bound cert extension to opaque handle";
+ return NULL;
+ }
+
+ // Copy extension into x509 cert
+ if (CERT_FinishExtensions(cert_handle) != SECSuccess){
+ LOG(ERROR) << "Unable to copy extension to X509 cert";
+ return NULL;
+ }
+
+ X509Certificate* x509_cert = SignCertificate(cert, key);
+
+ return x509_cert;
+}
+
void X509Certificate::GetSubjectAltName(
std::vector<std::string>* dns_names,
std::vector<std::string>* ip_addrs) const {

Powered by Google App Engine
This is Rietveld 408576698