From 424642319b55c57e0c8e5af4a1c0cbf677fa39d4 Mon Sep 17 00:00:00 2001 From: "bzbarsky@mit.edu" Date: Thu, 23 Aug 2007 11:59:12 -0700 Subject: [PATCH] Make it possible to fastload NSSCertificates. Bug 388128, r=kaie, sr=brendan, a=bzbarsky --- security/manager/ssl/src/nsNSSCertificate.cpp | 131 +++++++++++++++++- security/manager/ssl/src/nsNSSCertificate.h | 17 ++- security/manager/ssl/src/nsNSSModule.cpp | 8 ++ 3 files changed, 149 insertions(+), 7 deletions(-) diff --git a/security/manager/ssl/src/nsNSSCertificate.cpp b/security/manager/ssl/src/nsNSSCertificate.cpp index 093ce472fe5..e7311699e56 100644 --- a/security/manager/ssl/src/nsNSSCertificate.cpp +++ b/security/manager/ssl/src/nsNSSCertificate.cpp @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -68,6 +69,9 @@ #include "nsUnicharUtils.h" #include "nsThreadUtils.h" #include "nsCertVerificationThread.h" +#include "nsIObjectOutputStream.h" +#include "nsIObjectInputStream.h" +#include "nsIProgrammingLanguage.h" #include "nspr.h" extern "C" { @@ -104,25 +108,38 @@ NS_IMPL_THREADSAFE_ISUPPORTS4(nsNSSCertificate, nsIX509Cert, nsNSSCertificate* nsNSSCertificate::ConstructFromDER(char *certDER, int derLen) +{ + nsNSSCertificate* newObject = new nsNSSCertificate(); + if (!newObject->InitFromDER(certDER, derLen)) { + delete newObject; + newObject = nsnull; + } + + return newObject; +} + +PRBool +nsNSSCertificate::InitFromDER(char *certDER, int derLen) { nsNSSShutDownPreventionLock locker; + if (isAlreadyShutDown()) + return PR_FALSE; if (!certDER || !derLen) - return nsnull; + return PR_FALSE; CERTCertificate *aCert = CERT_DecodeCertFromPackage(certDER, derLen); if (!aCert) - return nsnull; + return PR_FALSE; if(aCert->dbhandle == nsnull) { aCert->dbhandle = CERT_GetDefaultCertDB(); } - nsNSSCertificate *newObject = new nsNSSCertificate(aCert); - CERT_DestroyCertificate(aCert); - return newObject; + mCert = aCert; + return PR_TRUE; } nsNSSCertificate::nsNSSCertificate(CERTCertificate *cert) : @@ -138,6 +155,13 @@ nsNSSCertificate::nsNSSCertificate(CERTCertificate *cert) : mCert = CERT_DupCertificate(cert); } +nsNSSCertificate::nsNSSCertificate() : + mCert(nsnull), + mPermDelete(PR_FALSE), + mCertType(CERT_TYPE_NOT_YET_INITIALIZED) +{ +} + nsNSSCertificate::~nsNSSCertificate() { nsNSSShutDownPreventionLock locker; @@ -1470,3 +1494,100 @@ nsNSSCertListEnumerator::GetNext(nsISupports **_retval) CERT_RemoveCertListNode(node); return NS_OK; } + +NS_IMETHODIMP +nsNSSCertificate::Write(nsIObjectOutputStream* aStream) +{ + NS_ENSURE_STATE(mCert); + nsresult rv = aStream->Write32(mCert->derCert.len); + if (NS_FAILED(rv)) { + return rv; + } + + return aStream->WriteByteArray(mCert->derCert.data, mCert->derCert.len); +} + +NS_IMETHODIMP +nsNSSCertificate::Read(nsIObjectInputStream* aStream) +{ + NS_ENSURE_STATE(!mCert); + + PRUint32 len; + nsresult rv = aStream->Read32(&len); + if (NS_FAILED(rv)) { + return rv; + } + + nsXPIDLCString str; + rv = aStream->ReadBytes(len, getter_Copies(str)); + if (NS_FAILED(rv)) { + return rv; + } + + if (!InitFromDER(const_cast(str.get()), len)) { + return NS_ERROR_UNEXPECTED; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsNSSCertificate::GetInterfaces(PRUint32 *count, nsIID * **array) +{ + *count = 0; + *array = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSCertificate::GetHelperForLanguage(PRUint32 language, nsISupports **_retval) +{ + *_retval = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSCertificate::GetContractID(char * *aContractID) +{ + *aContractID = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSCertificate::GetClassDescription(char * *aClassDescription) +{ + *aClassDescription = nsnull; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSCertificate::GetClassID(nsCID * *aClassID) +{ + *aClassID = (nsCID*) nsMemory::Alloc(sizeof(nsCID)); + if (!*aClassID) + return NS_ERROR_OUT_OF_MEMORY; + return GetClassIDNoAlloc(*aClassID); +} + +NS_IMETHODIMP +nsNSSCertificate::GetImplementationLanguage(PRUint32 *aImplementationLanguage) +{ + *aImplementationLanguage = nsIProgrammingLanguage::CPLUSPLUS; + return NS_OK; +} + +NS_IMETHODIMP +nsNSSCertificate::GetFlags(PRUint32 *aFlags) +{ + *aFlags = nsIClassInfo::THREADSAFE; + return NS_OK; +} + +static NS_DEFINE_CID(kNSSCertificateCID, NS_X509CERT_CID); + +NS_IMETHODIMP +nsNSSCertificate::GetClassIDNoAlloc(nsCID *aClassIDNoAlloc) +{ + *aClassIDNoAlloc = kNSSCertificateCID; + return NS_OK; +} diff --git a/security/manager/ssl/src/nsNSSCertificate.h b/security/manager/ssl/src/nsNSSCertificate.h index 0b89911005d..88d5cdf8103 100644 --- a/security/manager/ssl/src/nsNSSCertificate.h +++ b/security/manager/ssl/src/nsNSSCertificate.h @@ -1,3 +1,4 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * @@ -49,6 +50,8 @@ #include "nsISMimeCert.h" #include "nsNSSShutDown.h" #include "nsISimpleEnumerator.h" +#include "nsISerializable.h" +#include "nsIClassInfo.h" #include "nsNSSCertHeader.h" @@ -60,6 +63,8 @@ class nsNSSCertificate : public nsIX509Cert, public nsIX509Cert2, public nsIX509Cert3, public nsISMimeCert, + public nsISerializable, + public nsIClassInfo, public nsNSSShutDownObject { public: @@ -68,8 +73,11 @@ public: NS_DECL_NSIX509CERT2 NS_DECL_NSIX509CERT3 NS_DECL_NSISMIMECERT + NS_DECL_NSISERIALIZABLE + NS_DECL_NSICLASSINFO nsNSSCertificate(CERTCertificate *cert); + nsNSSCertificate(); /* from a request? */ virtual ~nsNSSCertificate(); nsresult FormatUIStrings(const nsAutoString &nickname, nsAutoString &nickWithSerial, nsAutoString &details); @@ -88,6 +96,7 @@ private: nsresult GetSortableDate(PRTime aTime, nsAString &_aSortableDate); virtual void virtualDestroyNSSReference(); void destructorSafeDestroyNSSReference(); + PRBool InitFromDER(char* certDER, int derLen); // return false on failure }; class nsNSSCertList: public nsIX509CertList @@ -127,7 +136,11 @@ private: (dest)[2] = (((src) >> 8) & 0xff); \ (dest)[3] = ((src) & 0xff); - - +#define NS_X509CERT_CID { /* 660a3226-915c-4ffb-bb20-8985a632df05 */ \ + 0x660a3226, \ + 0x915c, \ + 0x4ffb, \ + { 0xbb, 0x20, 0x89, 0x85, 0xa6, 0x32, 0xdf, 0x05 } \ + } #endif /* _NS_NSSCERTIFICATE_H_ */ diff --git a/security/manager/ssl/src/nsNSSModule.cpp b/security/manager/ssl/src/nsNSSModule.cpp index cf45dfbdc83..fcf44340134 100644 --- a/security/manager/ssl/src/nsNSSModule.cpp +++ b/security/manager/ssl/src/nsNSSModule.cpp @@ -170,6 +170,7 @@ NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsSecretDecoderRing) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsPK11TokenDB) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsPKCS11ModuleDB) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR_INIT(PR_FALSE, PSMContentListener, init) +NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsNSSCertificate) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsNSSCertificateDB) NS_NSS_GENERIC_FACTORY_CONSTRUCTOR(PR_FALSE, nsNSSCertCache) #ifdef MOZ_XUL @@ -298,6 +299,13 @@ static const nsModuleComponentInfo components[] = PSMContentListenerConstructor }, + { + "X509 Certificate", + NS_X509CERT_CID, + nsnull, + nsNSSCertificateConstructor + }, + { "X509 Certificate Database", NS_X509CERTDB_CID,