158005 - add new CRL decode and import functions . Benefits are :
authorjpierre%netscape.com
Fri, 19 Jul 2002 00:59:34 +0000
changeset 3335 817e42ba7d43b30c8b9ed82bdcfe0fdbf19aec1a
parent 3334 dac9dd3992c4bb2431ad7266d25684fde0911fad
child 3336 2a782e93cc0388c2613efa58cdf80fa734a455bd
push idunknown
push userunknown
push dateunknown
bugs158005
158005 - add new CRL decode and import functions . Benefits are : - ability to import to any slot - ability to specify decode options, such as "don't copy DER" - ability to specify import options, such as "don't do CRL checks" This patch also maps the existing functions SEC_NewCrl and CERT_ImportCRL to this new function, eliminating the code duplication that existed
security/nss/lib/certdb/cert.h
security/nss/lib/certdb/crl.c
security/nss/lib/certhigh/certhigh.c
security/nss/lib/nss/nss.def
security/nss/lib/pk11wrap/pk11cert.c
security/nss/lib/pk11wrap/pk11func.h
--- a/security/nss/lib/certdb/cert.h
+++ b/security/nss/lib/certdb/cert.h
@@ -384,16 +384,36 @@ CERT_DecodeDERCertificate (SECItem *derS
 **	"type" is this a CRL or KRL.
 */
 #define SEC_CRL_TYPE	1
 #define SEC_KRL_TYPE	0
 
 extern CERTSignedCrl *
 CERT_DecodeDERCrl (PRArenaPool *arena, SECItem *derSignedCrl,int type);
 
+/*
+ * same as CERT_DecodeDERCrl, plus allow options to be passed in
+ */
+
+CERTSignedCrl *
+CERT_DecodeDERCrlEx(PRArenaPool *narena, SECItem *derSignedCrl, int type,
+                          PRInt32 options);
+
+/* CRL options to pass */
+
+#define CRL_DECODE_DEFAULT_OPTIONS          0x00000000
+
+/* when CRL_DECODE_DONT_COPY_DER is set, the DER is not copied . The
+   application must then keep derSignedCrl until it destroys the
+   CRL . Ideally, it should allocate derSignedCrl in an arena
+   and pass that arena in as the first argument to CERT_DecodeDERCrlEx */
+
+#define CRL_DECODE_DONT_COPY_DER            0x00000001
+
+
 /* Validate CRL then import it to the dbase.  If there is already a CRL with the
  * same CA in the dbase, it will be replaced if derCRL is more up to date.  
  * If the process successes, a CRL will be returned.  Otherwise, a NULL will 
  * be returned. The caller should call PORT_GetError() for the exactly error 
  * code.
  */
 extern CERTSignedCrl *
 CERT_ImportCRL (CERTCertDBHandle *handle, SECItem *derCRL, char *url, 
--- a/security/nss/lib/certdb/crl.c
+++ b/security/nss/lib/certdb/crl.c
@@ -304,19 +304,21 @@ CERT_KeyFromDERCrl(PRArenaPool *arena, S
     key->len =  crlkey.derName.len;
     key->data = crlkey.derName.data;
 
     return(SECSuccess);
 }
 
 /*
  * take a DER CRL or KRL  and decode it into a CRL structure
+ * allow reusing the input DER without making a copy
  */
 CERTSignedCrl *
-CERT_DecodeDERCrl(PRArenaPool *narena, SECItem *derSignedCrl, int type)
+CERT_DecodeDERCrlEx(PRArenaPool *narena, SECItem *derSignedCrl, int type,
+                          PRInt32 options)
 {
     PRArenaPool *arena;
     CERTSignedCrl *crl;
     SECStatus rv;
 
     /* make a new arena */
     if (narena == NULL) {
     	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
@@ -330,31 +332,37 @@ CERT_DecodeDERCrl(PRArenaPool *narena, S
     /* allocate the CRL structure */
     crl = (CERTSignedCrl *)PORT_ArenaZAlloc(arena, sizeof(CERTSignedCrl));
     if ( !crl ) {
 	goto loser;
     }
     
     crl->arena = arena;
 
-    crl->derCrl = (SECItem *)PORT_ArenaZAlloc(arena,sizeof(SECItem));
-    if (crl->derCrl == NULL) {
-	goto loser;
-    }
-    rv = SECITEM_CopyItem(arena, crl->derCrl, derSignedCrl);
-    if (rv != SECSuccess) {
-	goto loser;
+    if (options & CRL_DECODE_DONT_COPY_DER) {
+        crl->derCrl = derSignedCrl; /* DER is not copied . The application
+                                       must keep derSignedCrl until it
+                                       destroys the CRL */
+    } else {
+        crl->derCrl = (SECItem *)PORT_ArenaZAlloc(arena,sizeof(SECItem));
+        if (crl->derCrl == NULL) {
+            goto loser;
+        }
+        rv = SECITEM_CopyItem(arena, crl->derCrl, derSignedCrl);
+        if (rv != SECSuccess) {
+            goto loser;
+        }
     }
 
     /* Save the arena in the inner crl for CRL extensions support */
     crl->crl.arena = arena;
 
     /* decode the CRL info */
     switch (type) {
-    case SEC_CRL_TYPE: 
+    case SEC_CRL_TYPE:
 	rv = SEC_ASN1DecodeItem
 	     (arena, crl, cert_SignedCrlTemplate, derSignedCrl);
 	if (rv != SECSuccess)
 	    break;
         /* check for critical extentions */
 	rv =  cert_check_crl_version (&crl->crl);
 	break;
 
@@ -380,16 +388,25 @@ loser:
     if ((narena == NULL) && arena ) {
 	PORT_FreeArena(arena, PR_FALSE);
     }
     
     return(0);
 }
 
 /*
+ * take a DER CRL or KRL  and decode it into a CRL structure
+ */
+CERTSignedCrl *
+CERT_DecodeDERCrl(PRArenaPool *narena, SECItem *derSignedCrl, int type)
+{
+    return CERT_DecodeDERCrlEx(narena, derSignedCrl, type, CRL_DECODE_DEFAULT_OPTIONS);
+}
+
+/*
  * Lookup a CRL in the databases. We mirror the same fast caching data base
  *  caching stuff used by certificates....?
  */
 CERTSignedCrl *
 SEC_FindCrlByKeyOnSlot(PK11SlotInfo *slot, SECItem *crlKey, int type)
 {
     CERTSignedCrl *crl = NULL;
     SECItem *derCrl;
@@ -435,18 +452,16 @@ CERTSignedCrl *
 crl_storeCRL (PK11SlotInfo *slot,char *url,
                   CERTSignedCrl *newCrl, SECItem *derCrl, int type)
 {
     CERTSignedCrl *oldCrl = NULL, *crl = NULL;
     CK_OBJECT_HANDLE crlHandle;
 
     oldCrl = SEC_FindCrlByKeyOnSlot(slot, &newCrl->crl.derName, type);
 
-
-
     /* if there is an old crl, make sure the one we are installing
      * is newer. If not, exit out, otherwise delete the old crl.
      */
     if (oldCrl != NULL) {
 	/* if it's already there, quietly continue */
 	if (SECITEM_CompareItem(newCrl->derCrl, oldCrl->derCrl) 
 						== SECEqual) {
 	    crl = newCrl;
@@ -512,46 +527,25 @@ SEC_FindCrlByName(CERTCertDBHandle *hand
  * create a new CRL from DER material.
  *
  * The signature on this CRL must be checked before you
  * load it. ???
  */
 CERTSignedCrl *
 SEC_NewCrl(CERTCertDBHandle *handle, char *url, SECItem *derCrl, int type)
 {
-    CERTSignedCrl *newCrl = NULL, *crl = NULL;
-    PK11SlotInfo *slot;
-
-    /* make this decode dates! */
-    newCrl = CERT_DecodeDERCrl(NULL, derCrl, type);
-    if (newCrl == NULL) {
-        if (type == SEC_CRL_TYPE) {
-            PORT_SetError(SEC_ERROR_CRL_INVALID);
-        } else {
-            PORT_SetError(SEC_ERROR_KRL_INVALID);
-        }
-        goto done;
-    }
-
-    slot = PK11_GetInternalKeySlot();
-    crl = crl_storeCRL(slot, url, newCrl, derCrl, type);
+    CERTSignedCrl* retCrl = NULL;
+    PK11SlotInfo* slot = PK11_GetInternalKeySlot();
+    retCrl = PK11_ImportCRL(slot, derCrl, url, type, NULL,
+        CRL_IMPORT_BYPASS_CHECKS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
     PK11_FreeSlot(slot);
 
-
-done:
-    if (crl == NULL) {
-	if (newCrl) {
-	    PORT_FreeArena(newCrl->arena, PR_FALSE);
-	}
-    }
-
-    return crl;
+    return retCrl;
 }
-
-
+    
 CERTSignedCrl *
 SEC_FindCrlByDERCert(CERTCertDBHandle *handle, SECItem *derCrl, int type)
 {
     PRArenaPool *arena;
     SECItem crlKey;
     SECStatus rv;
     CERTSignedCrl *crl = NULL;
     
--- a/security/nss/lib/certhigh/certhigh.c
+++ b/security/nss/lib/certhigh/certhigh.c
@@ -45,19 +45,16 @@
 #endif
 #include "nsspki.h"
 #include "pki.h"
 #include "pkit.h"
 #include "pkitm.h"
 #include "pki3hack.h"
 
 
-CERTSignedCrl * crl_storeCRL (PK11SlotInfo *slot,char *url,
-                  CERTSignedCrl *newCrl, SECItem *derCrl, int type);
-
 PRBool
 CERT_MatchNickname(char *name1, char *name2) {
     char *nickname1= NULL;
     char *nickname2 = NULL;
     char *token1;
     char *token2;
     char *token = NULL;
     int len;
@@ -492,17 +489,16 @@ CollectNicknames( NSSCertificate *c, voi
 }
 
 CERTCertNicknames *
 CERT_GetCertNicknames(CERTCertDBHandle *handle, int what, void *wincx)
 {
     PRArenaPool *arena;
     CERTCertNicknames *names;
     int i;
-    SECStatus rv;
     stringNode *node;
     
     arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
     if ( arena == NULL ) {
 	PORT_SetError(SEC_ERROR_NO_MEMORY);
 	return(NULL);
     }
     
@@ -781,72 +777,23 @@ CERT_FindCRLDistributionPoints (CERTCert
     return (CERT_DecodeCRLDistributionPoints (cert->arena,
 					      &encodedExtenValue));
 }
 
 /* From crl.c */
 CERTSignedCrl * CERT_ImportCRL
    (CERTCertDBHandle *handle, SECItem *derCRL, char *url, int type, void *wincx)
 {
-    CERTCertificate *caCert;
-    CERTSignedCrl *newCrl, *crl;
-    SECStatus rv;
-    PK11SlotInfo *slot;
-
-    newCrl = crl = NULL;
-
-    PORT_Assert (handle != NULL);
-    do {
-
-	newCrl = CERT_DecodeDERCrl(NULL, derCRL, type);
-	if (newCrl == NULL) {
-	    if (type == SEC_CRL_TYPE) {
-		/* only promote error when the error code is too generic */
-		if (PORT_GetError () == SEC_ERROR_BAD_DER)
-			PORT_SetError(SEC_ERROR_CRL_INVALID);
-	    } else {
-		PORT_SetError(SEC_ERROR_KRL_INVALID);
-	    }
-	    break;		
-	}
-    
-	caCert = CERT_FindCertByName (handle, &newCrl->crl.derName);
-	if (caCert == NULL) {
-	    PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);	    
-	    break;
-	}
+    CERTSignedCrl* retCrl = NULL;
+    PK11SlotInfo* slot = PK11_GetInternalKeySlot();
+    retCrl = PK11_ImportCRL(slot, derCRL, url, type, wincx,
+        CRL_IMPORT_DEFAULT_OPTIONS, NULL, CRL_DECODE_DEFAULT_OPTIONS);
+    PK11_FreeSlot(slot);
 
-	/* If caCert is a v3 certificate, make sure that it can be used for
-	   crl signing purpose */
-	rv = CERT_CheckCertUsage (caCert, KU_CRL_SIGN);
-	if (rv != SECSuccess) {
-	    break;
-	}
-
-	rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert,
-				   PR_Now(), wincx);
-	if (rv != SECSuccess) {
-	    if (type == SEC_CRL_TYPE) {
-		PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
-	    } else {
-		PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
-	    }
-	    break;
-	}
-
-	slot = PK11_GetInternalKeySlot();
-	crl = crl_storeCRL(slot, url, newCrl, derCRL, type);
-	PK11_FreeSlot(slot);
-
-    } while (0);
-
-    if (crl == NULL) {
-	SEC_DestroyCrl (newCrl);
-    }
-    return (crl);
+    return retCrl;
 }
 
 /* From certdb.c */
 static SECStatus
 cert_ImportCAChain(SECItem *certs, int numcerts, SECCertUsage certUsage, PRBool trusted)
 {
     SECStatus rv;
     SECItem *derCert;
--- a/security/nss/lib/nss/nss.def
+++ b/security/nss/lib/nss/nss.def
@@ -678,25 +678,27 @@ PK11_ImportCert;
 PORT_Strdup;
 SECMOD_CanDeleteInternalModule;
 ;+    local:
 ;+       *;
 ;+};
 ;+NSS_3.6 { 	# NSS 3.6 release
 ;+    global:
 CERT_AddOCSPAcceptableResponses;
+CERT_DecodeDERCrlEx;
 CERT_CreateOCSPCertID;
 CERT_CreateOCSPRequest;
 CERT_DecodeOCSPResponse;
 CERT_DestroyOCSPCertID;
 CERT_DestroyOCSPRequest;
 CERT_EncodeOCSPRequest;
 CERT_GetOCSPResponseStatus;
 CERT_GetOCSPStatusForCertID;
 CERT_VerifyCertChain;
 CERT_VerifyCertificate;
 CERT_VerifyCertificateNow;
 CERT_VerifyOCSPResponseSignature;
 PK11_GetPBEIV;
+PK11_ImportCRL;
 PK11_SaveContextAlloc;
 ;+    local:
 ;+       *;
 ;+};
--- a/security/nss/lib/pk11wrap/pk11cert.c
+++ b/security/nss/lib/pk11wrap/pk11cert.c
@@ -3250,17 +3250,16 @@ isOnList(CERTCertList *certList,NSSCerti
 }
 static PRStatus
 pk11ListCertCallback(NSSCertificate *c, void *arg)
 {
     struct listCertsStr *listCertP = (struct listCertsStr *)arg;
     CERTCertificate *newCert = NULL;
     PK11CertListType type = listCertP->type;
     CERTCertList *certList = listCertP->certList;
-    CERTCertTrust *trust;
     PRBool isUnique = PR_FALSE;
     PRBool isCA = PR_FALSE;
     char *nickname = NULL;
     unsigned int certType;
 
     if ((type == PK11CertListUnique) || (type == PK11CertListRootUnique)) {
 	isUnique = PR_TRUE;
     }
@@ -4002,8 +4001,74 @@ PK11_SaveSMimeProfile(PK11SlotInfo *slot
 
     if (free_slot) {
 	PK11_FreeSlot(free_slot);
     }
     return SECSuccess;
 }
 
 
+CERTSignedCrl * crl_storeCRL (PK11SlotInfo *slot,char *url,
+                  CERTSignedCrl *newCrl, SECItem *derCrl, int type);
+
+/* import the CRL into the token */
+
+CERTSignedCrl* PK11_ImportCRL(PK11SlotInfo * slot, SECItem *derCRL, char *url,
+    int type, void *wincx, PRInt32 importOptions, PRArenaPool* arena,
+    PRInt32 decodeoptions)
+{
+    CERTSignedCrl *newCrl, *crl;
+    SECStatus rv;
+
+    newCrl = crl = NULL;
+
+    do {
+        newCrl = CERT_DecodeDERCrlEx(arena, derCRL, type, decodeoptions);
+        if (newCrl == NULL) {
+            if (type == SEC_CRL_TYPE) {
+                /* only promote error when the error code is too generic */
+                if (PORT_GetError () == SEC_ERROR_BAD_DER)
+                    PORT_SetError(SEC_ERROR_CRL_INVALID);
+	        } else {
+                PORT_SetError(SEC_ERROR_KRL_INVALID);
+            }
+            break;		
+        }
+
+        if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){
+            CERTCertificate *caCert;
+            CERTCertDBHandle* handle = CERT_GetDefaultCertDB();
+            PR_ASSERT(handle != NULL);
+            caCert = CERT_FindCertByName (handle,
+                                          &newCrl->crl.derName);
+            if (caCert == NULL) {
+                PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);	    
+                break;
+            }
+
+            /* If caCert is a v3 certificate, make sure that it can be used for
+               crl signing purpose */
+            rv = CERT_CheckCertUsage (caCert, KU_CRL_SIGN);
+            if (rv != SECSuccess) {
+                break;
+            }
+
+            rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert,
+                                       PR_Now(), wincx);
+            if (rv != SECSuccess) {
+                if (type == SEC_CRL_TYPE) {
+                    PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
+                } else {
+                    PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
+                }
+                break;
+            }
+        }
+
+	crl = crl_storeCRL(slot, url, newCrl, derCRL, type);
+
+    } while (0);
+
+    if (crl == NULL) {
+	SEC_DestroyCrl (newCrl);
+    }
+    return (crl);
+}
--- a/security/nss/lib/pk11wrap/pk11func.h
+++ b/security/nss/lib/pk11wrap/pk11func.h
@@ -437,17 +437,21 @@ CK_OBJECT_HANDLE PK11_FindCertInSlot(PK1
 SECStatus PK11_TraverseCertsForNicknameInSlot(SECItem *nickname,
 	PK11SlotInfo *slot, SECStatus(*callback)(CERTCertificate *, void *),
 	void *arg);
 SECStatus PK11_TraverseCertsInSlot(PK11SlotInfo *slot,
        SECStatus(* callback)(CERTCertificate*, void *), void *arg);
 CERTCertList * PK11_ListCerts(PK11CertListType type, void *pwarg);
 CERTCertList * PK11_ListCertsInSlot(PK11SlotInfo *slot);
 SECStatus PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx);
-
+CERTSignedCrl* PK11_ImportCRL(PK11SlotInfo * slot, SECItem *derCRL, char *url,
+    int type, void *wincx, PRInt32 importOptions, PRArenaPool* arena, PRInt32 decodeOptions);
+/* import options */
+#define CRL_IMPORT_DEFAULT_OPTIONS 0x00000000
+#define CRL_IMPORT_BYPASS_CHECKS   0x00000001
 
 /**********************************************************************
  *                   Sign/Verify 
  **********************************************************************/
 int PK11_SignatureLen(SECKEYPrivateKey *key);
 PK11SlotInfo * PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key);
 SECStatus PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, SECItem *hash);
 SECStatus PK11_VerifyRecover(SECKEYPublicKey *key, SECItem *sig,