diff nss/lib/pk11wrap/pk11nobj.c @ 0:1e5118fa0cb1

This is NSS with a Cmake Buildsyste To compile a static NSS library for Windows we've used the Chromium-NSS fork and added a Cmake buildsystem to compile it statically for Windows. See README.chromium for chromium changes and README.trustbridge for our modifications.
author Andre Heinecke <andre.heinecke@intevation.de>
date Mon, 28 Jul 2014 10:47:06 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/nss/lib/pk11wrap/pk11nobj.c	Mon Jul 28 10:47:06 2014 +0200
@@ -0,0 +1,785 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/*
+ * This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects,
+ * etc).
+ */
+
+#include "secport.h"
+#include "seccomon.h"
+#include "secmod.h"
+#include "secmodi.h"
+#include "secmodti.h"
+#include "pkcs11.h"
+#include "pk11func.h"
+#include "cert.h"
+#include "certi.h" 
+#include "secitem.h"
+#include "sechash.h" 
+#include "secoid.h"
+
+#include "certdb.h" 
+#include "secerr.h"
+#include "sslerr.h"
+
+#include "pki3hack.h"
+#include "dev3hack.h" 
+
+#include "devm.h" 
+#include "pki.h"
+#include "pkim.h" 
+
+extern const NSSError NSS_ERROR_NOT_FOUND;
+
+CK_TRUST
+pk11_GetTrustField(PK11SlotInfo *slot, PLArenaPool *arena,
+                   CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type)
+{
+  CK_TRUST rv = 0;
+  SECItem item;
+
+  item.data = NULL;
+  item.len = 0;
+
+  if( SECSuccess == PK11_ReadAttribute(slot, id, type, arena, &item) ) {
+    PORT_Assert(item.len == sizeof(CK_TRUST));
+    PORT_Memcpy(&rv, item.data, sizeof(CK_TRUST));
+    /* Damn, is there an endian problem here? */
+    return rv;
+  }
+
+  return 0;
+}
+
+PRBool
+pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
+{
+  PLArenaPool *arena;
+
+  CK_ATTRIBUTE tobjTemplate[] = {
+    { CKA_CLASS, NULL, 0 },
+    { CKA_CERT_SHA1_HASH, NULL, 0 },
+  };
+
+  CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
+  CK_OBJECT_HANDLE tobjID;
+  unsigned char sha1_hash[SHA1_LENGTH];
+
+  CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth;
+
+  PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);
+
+  PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
+  PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash, 
+                SHA1_LENGTH);
+
+  tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, 
+                                     sizeof(tobjTemplate)/sizeof(tobjTemplate[0]));
+  if( CK_INVALID_HANDLE == tobjID ) {
+    return PR_FALSE;
+  }
+
+  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+  if( NULL == arena ) return PR_FALSE;
+
+  /* Unfortunately, it seems that PK11_GetAttributes doesn't deal
+   * well with nonexistent attributes.  I guess we have to check 
+   * the trust info fields one at a time.
+   */
+
+  /* We could verify CKA_CERT_HASH here */
+
+  /* We could verify CKA_EXPIRES here */
+
+
+  /* "Purpose" trust information */
+  serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
+  clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH);
+  codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
+  emailProtection = pk11_GetTrustField(slot, arena, tobjID, 
+						CKA_TRUST_EMAIL_PROTECTION);
+  /* Here's where the fun logic happens.  We have to map back from the 
+   * key usage, extended key usage, purpose, and possibly other trust values 
+   * into the old trust-flags bits.  */
+
+  /* First implementation: keep it simple for testing.  We can study what other
+   * mappings would be appropriate and add them later.. fgmr 20000724 */
+
+  if ( serverAuth ==  CKT_NSS_TRUSTED ) {
+    trust->sslFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
+  }
+
+  if ( serverAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
+    trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | 
+							CERTDB_NS_TRUSTED_CA;
+  }
+  if ( clientAuth == CKT_NSS_TRUSTED_DELEGATOR ) {
+    trust->sslFlags |=  CERTDB_TRUSTED_CLIENT_CA ;
+  }
+
+  if ( emailProtection == CKT_NSS_TRUSTED ) {
+    trust->emailFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
+  }
+
+  if ( emailProtection == CKT_NSS_TRUSTED_DELEGATOR ) {
+    trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
+  }
+
+  if( codeSigning == CKT_NSS_TRUSTED ) {
+    trust->objectSigningFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
+  }
+
+  if( codeSigning == CKT_NSS_TRUSTED_DELEGATOR ) {
+    trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
+  }
+
+  /* There's certainly a lot more logic that can go here.. */
+
+  PORT_FreeArena(arena, PR_FALSE);
+
+  return PR_TRUE;
+}
+
+static SECStatus
+pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg)
+{
+    SECItem derCrl;
+    CERTCrlHeadNode *head = (CERTCrlHeadNode *) arg;
+    CERTCrlNode *new_node = NULL;
+    CK_ATTRIBUTE fetchCrl[3] = {
+	 { CKA_VALUE, NULL, 0},
+	 { CKA_NETSCAPE_KRL, NULL, 0},
+	 { CKA_NETSCAPE_URL, NULL, 0},
+    };
+    const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
+    CK_RV crv;
+    SECStatus rv = SECFailure;
+
+    crv = PK11_GetAttributes(head->arena,slot,crlID,fetchCrl,fetchCrlSize);
+    if (CKR_OK != crv) {
+	PORT_SetError(PK11_MapError(crv));
+	goto loser;
+    }
+
+    if (!fetchCrl[1].pValue) {
+	PORT_SetError(SEC_ERROR_CRL_INVALID);
+	goto loser;
+    }
+
+    new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode));
+    if (new_node == NULL) {
+        goto loser;
+    }
+
+    if (*((CK_BBOOL *)fetchCrl[1].pValue))
+        new_node->type = SEC_KRL_TYPE;
+    else
+        new_node->type = SEC_CRL_TYPE;
+
+    derCrl.type = siBuffer;
+    derCrl.data = (unsigned char *)fetchCrl[0].pValue;
+    derCrl.len = fetchCrl[0].ulValueLen;
+    new_node->crl=CERT_DecodeDERCrl(head->arena,&derCrl,new_node->type);
+    if (new_node->crl == NULL) {
+	goto loser;
+    }
+
+    if (fetchCrl[2].pValue) {
+        int nnlen = fetchCrl[2].ulValueLen;
+        new_node->crl->url  = (char *)PORT_ArenaAlloc(head->arena, nnlen+1);
+        if ( !new_node->crl->url ) {
+            goto loser;
+        }
+        PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
+        new_node->crl->url[nnlen] = 0;
+    } else {
+        new_node->crl->url = NULL;
+    }
+
+
+    new_node->next = NULL;
+    if (head->last) {
+        head->last->next = new_node;
+        head->last = new_node;
+    } else {
+        head->first = head->last = new_node;
+    }
+    rv = SECSuccess;
+
+loser:
+    return(rv);
+}
+
+/*
+ * Return a list of all the CRLs .
+ * CRLs are allocated in the list's arena.
+ */
+SECStatus
+PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) {
+    pk11TraverseSlot creater;
+    CK_ATTRIBUTE theTemplate[2];
+    CK_ATTRIBUTE *attrs;
+    CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL;
+    CK_BBOOL isKrl = CK_FALSE;
+
+    attrs = theTemplate;
+    PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); attrs++;
+    if (type != -1) {
+	isKrl = (CK_BBOOL) (type == SEC_KRL_TYPE);
+        PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl)); attrs++;
+    }
+
+    creater.callback = pk11_CollectCrls;
+    creater.callbackArg = (void *) nodes;
+    creater.findTemplate = theTemplate;
+    creater.templateCount = (attrs - theTemplate);
+
+    return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
+}
+
+struct crlOptionsStr {
+    CERTCrlHeadNode* head;
+    PRInt32 decodeOptions;
+};
+
+typedef struct crlOptionsStr crlOptions;
+
+static SECStatus
+pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
+                          void *arg)
+{
+    SECItem* derCrl = NULL;
+    crlOptions* options = (crlOptions*) arg;
+    CERTCrlHeadNode *head = options->head;
+    CERTCrlNode *new_node = NULL;
+    CK_ATTRIBUTE fetchCrl[3] = {
+	 { CKA_VALUE, NULL, 0},
+	 { CKA_NETSCAPE_KRL, NULL, 0},
+	 { CKA_NETSCAPE_URL, NULL, 0},
+    };
+    const int fetchCrlSize = sizeof(fetchCrl)/sizeof(fetchCrl[2]);
+    CK_RV crv;
+    SECStatus rv = SECFailure;
+    PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
+                                  successfully */
+    int i;
+
+    crv = PK11_GetAttributes(NULL,slot,crlID,fetchCrl,fetchCrlSize);
+    if (CKR_OK != crv) {
+	PORT_SetError(PK11_MapError(crv));
+	goto loser;
+    }
+
+    if (!fetchCrl[1].pValue) {
+        /* reject KRLs */
+	PORT_SetError(SEC_ERROR_CRL_INVALID);
+	goto loser;
+    }
+
+    new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
+                                              sizeof(CERTCrlNode));
+    if (new_node == NULL) {
+        goto loser;
+    }
+
+    new_node->type = SEC_CRL_TYPE;
+
+    derCrl = SECITEM_AllocItem(NULL, NULL, 0);
+    if (!derCrl) {
+        goto loser;
+    }
+    derCrl->type = siBuffer;
+    derCrl->data = (unsigned char *)fetchCrl[0].pValue;
+    derCrl->len = fetchCrl[0].ulValueLen;
+    new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl,new_node->type,
+                                               options->decodeOptions);
+    if (new_node->crl == NULL) {
+	goto loser;
+    }    
+    adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
+                          we won't need to free it upon exit */
+
+    if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
+        /* copy the URL if there is one */
+        int nnlen = fetchCrl[2].ulValueLen;
+        new_node->crl->url  = (char *)PORT_ArenaAlloc(new_node->crl->arena,
+                                                      nnlen+1);
+        if ( !new_node->crl->url ) {
+            goto loser;
+        }
+        PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
+        new_node->crl->url[nnlen] = 0;
+    } else {
+        new_node->crl->url = NULL;
+    }
+
+    new_node->next = NULL;
+    if (head->last) {
+        head->last->next = new_node;
+        head->last = new_node;
+    } else {
+        head->first = head->last = new_node;
+    }
+    rv = SECSuccess;
+    new_node->crl->slot = PK11_ReferenceSlot(slot);
+    new_node->crl->pkcs11ID = crlID;
+
+loser:
+    /* free attributes that weren't adopted by the CRL */
+    for (i=1;i<fetchCrlSize;i++) {
+        if (fetchCrl[i].pValue) {
+            PORT_Free(fetchCrl[i].pValue);
+        }
+    }
+    /* free the DER if the CRL object didn't adopt it */
+    if (fetchCrl[0].pValue && PR_FALSE == adopted) {
+        PORT_Free(fetchCrl[0].pValue);
+    }
+    if (derCrl && !adopted) {
+        /* clear the data fields, which we already took care of above */
+        derCrl->data = NULL;
+        derCrl->len = 0;
+        /* free the memory for the SECItem structure itself */
+        SECITEM_FreeItem(derCrl, PR_TRUE);
+    }
+    return(rv);
+}
+
+/*
+ * Return a list of CRLs matching specified issuer and type
+ * CRLs are not allocated in the list's arena, but rather in their own,
+ * arena, so that they can be used individually in the CRL cache .
+ * CRLs are always partially decoded for efficiency.
+ */
+SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem* issuer,
+                            void *wincx)
+{
+    pk11TraverseSlot creater;
+    CK_ATTRIBUTE theTemplate[2];
+    CK_ATTRIBUTE *attrs;
+    CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL;
+    crlOptions options;
+
+    attrs = theTemplate;
+    PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); attrs++;
+
+    options.head = nodes;
+
+    /* - do a partial decoding - we don't need to decode the entries while
+       fetching
+       - don't copy the DER for optimal performance - CRL can be very large
+       - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
+       - keep bad CRL objects. The CRL cache is interested in them, for
+         security purposes. Bad CRL objects are a sign of something amiss.
+    */
+
+    options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
+                            CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
+    if (issuer)
+    {
+        PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); attrs++;
+    }
+
+    creater.callback = pk11_RetrieveCrlsCallback;
+    creater.callbackArg = (void *) &options;
+    creater.findTemplate = theTemplate;
+    creater.templateCount = (attrs - theTemplate);
+
+    return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
+}
+
+/*
+ * return the crl associated with a derSubjectName 
+ */
+SECItem *
+PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
+					 SECItem *name, int type, char **pUrl)
+{
+    NSSCRL **crls, **crlp, *crl = NULL;
+    NSSDER subject;
+    SECItem *rvItem;
+    NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
+    char * url = NULL;
+
+    PORT_SetError(0);
+    NSSITEM_FROM_SECITEM(&subject, name);
+    if (*slot) {
+	nssCryptokiObject **instances;
+	nssPKIObjectCollection *collection;
+	nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
+	NSSToken *token = PK11Slot_GetNSSToken(*slot);
+	collection = nssCRLCollection_Create(td, NULL);
+	if (!collection) {
+	    goto loser;
+	}
+	instances = nssToken_FindCRLsBySubject(token, NULL, &subject, 
+	                                       tokenOnly, 0, NULL);
+	nssPKIObjectCollection_AddInstances(collection, instances, 0);
+	nss_ZFreeIf(instances);
+	crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
+	nssPKIObjectCollection_Destroy(collection);
+    } else {
+	crls = nssTrustDomain_FindCRLsBySubject(td, &subject);
+    }
+    if ((!crls) || (*crls == NULL)) {
+	if (crls) {
+	    nssCRLArray_Destroy(crls);
+	}
+	if (NSS_GetError() == NSS_ERROR_NOT_FOUND) {
+	    PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
+	}
+	goto loser;
+    }
+    for (crlp = crls; *crlp; crlp++) {
+	if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) ||
+	    ((*crlp)->isKRL && type != SEC_CRL_TYPE)) 
+	{
+	    crl = nssCRL_AddRef(*crlp);
+	    break;
+	}
+    }
+    nssCRLArray_Destroy(crls);
+    if (!crl) { 
+	/* CRL collection was found, but no interesting CRL's were on it.
+	 * Not an error */
+	PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
+	goto loser;
+    }
+    if (crl->url) {
+	url = PORT_Strdup(crl->url);
+	if (!url) {
+	    goto loser;
+	}
+    }
+    rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size);
+    if (!rvItem) {
+	goto loser;
+    }
+    memcpy(rvItem->data, crl->encoding.data, crl->encoding.size);
+    *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot);
+    *crlHandle = crl->object.instances[0]->handle;
+    *pUrl = url;
+    nssCRL_Destroy(crl);
+    return rvItem;
+
+loser:
+    if (url)
+    	PORT_Free(url);
+    if (crl)
+	nssCRL_Destroy(crl);
+    if (PORT_GetError() == 0) {
+	PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
+    }
+    return NULL;
+}
+
+CK_OBJECT_HANDLE
+PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, 
+							char *url, int type)
+{
+    NSSItem derCRL, derSubject;
+    NSSToken *token = PK11Slot_GetNSSToken(slot);
+    nssCryptokiObject *object;
+    PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE;
+    CK_OBJECT_HANDLE rvH;
+
+    NSSITEM_FROM_SECITEM(&derSubject, name);
+    NSSITEM_FROM_SECITEM(&derCRL, crl);
+
+    object = nssToken_ImportCRL(token, NULL, 
+                                &derSubject, &derCRL, isKRL, url, PR_TRUE);
+
+    if (object) {
+	rvH = object->handle;
+	nssCryptokiObject_Destroy(object);
+    } else {
+	rvH = CK_INVALID_HANDLE;
+        PORT_SetError(SEC_ERROR_CRL_IMPORT_FAILED);
+    }
+    return rvH;
+}
+
+
+/*
+ * delete a crl.
+ */
+SECStatus
+SEC_DeletePermCRL(CERTSignedCrl *crl)
+{
+    PRStatus status;
+    NSSToken *token;
+    nssCryptokiObject *object;
+    PK11SlotInfo *slot = crl->slot;
+
+    if (slot == NULL) {
+        PORT_Assert(slot);
+	/* shouldn't happen */
+	PORT_SetError( SEC_ERROR_CRL_INVALID);
+	return SECFailure;
+    }
+    token = PK11Slot_GetNSSToken(slot);
+
+    object = nss_ZNEW(NULL, nssCryptokiObject);
+    if (!object) {
+        return SECFailure;
+    }
+    object->token = nssToken_AddRef(token);
+    object->handle = crl->pkcs11ID;
+    object->isTokenObject = PR_TRUE;
+
+    status = nssToken_DeleteStoredObject(object);
+
+    nssCryptokiObject_Destroy(object);
+    return (status == PR_SUCCESS) ? SECSuccess : SECFailure;
+}
+
+/*
+ * return the certificate associated with a derCert 
+ */
+SECItem *
+PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
+				 SECItem *name, SECItem **profileTime)
+{
+    CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
+    CK_ATTRIBUTE theTemplate[] = {
+	{ CKA_SUBJECT, NULL, 0 },
+	{ CKA_CLASS, NULL, 0 },
+	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
+    };
+    CK_ATTRIBUTE smimeData[] =  {
+	{ CKA_SUBJECT, NULL, 0 },
+	{ CKA_VALUE, NULL, 0 },
+    };
+    /* if you change the array, change the variable below as well */
+    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
+    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
+    CK_ATTRIBUTE *attrs = theTemplate;
+    CK_RV crv;
+    SECItem *emailProfile = NULL;
+
+    if (!emailAddr || !emailAddr[0]) {
+	PORT_SetError(SEC_ERROR_INVALID_ARGS);
+	return NULL;
+    }
+
+    PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); attrs++;
+    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
+    PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr)); 
+								    attrs++;
+
+    if (*slot) {
+    	smimeh = pk11_FindObjectByTemplate(*slot,theTemplate,tsize);
+    } else {
+	PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
+							PR_FALSE,PR_TRUE,NULL);
+	PK11SlotListElement *le;
+
+	if (!list) {
+	    return NULL;
+	}
+	/* loop through all the slots */
+	for (le = list->head; le; le = le->next) {
+	    smimeh = pk11_FindObjectByTemplate(le->slot,theTemplate,tsize);
+	    if (smimeh != CK_INVALID_HANDLE) {
+		*slot = PK11_ReferenceSlot(le->slot);
+		break;
+	    }
+	}
+	PK11_FreeSlotList(list);
+    }
+    
+    if (smimeh == CK_INVALID_HANDLE) {
+	PORT_SetError(SEC_ERROR_NO_KRL);
+	return NULL;
+    }
+
+    if (profileTime) {
+    	PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0);
+    } 
+    
+    crv = PK11_GetAttributes(NULL,*slot,smimeh,smimeData,2);
+    if (crv != CKR_OK) {
+	PORT_SetError(PK11_MapError (crv));
+	goto loser;
+    }
+
+    if (!profileTime) {
+	SECItem profileSubject;
+
+	profileSubject.data = (unsigned char*) smimeData[0].pValue;
+	profileSubject.len = smimeData[0].ulValueLen;
+	if (!SECITEM_ItemsAreEqual(&profileSubject,name)) {
+	    goto loser;
+	}
+    }
+
+    emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
+    if (emailProfile == NULL) {
+	goto loser;
+    }
+
+    emailProfile->data = (unsigned char*) smimeData[1].pValue;
+    emailProfile->len = smimeData[1].ulValueLen;
+
+    if (profileTime) {
+	*profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));    
+	if (*profileTime) {
+	    (*profileTime)->data = (unsigned char*) smimeData[0].pValue;
+	    (*profileTime)->len = smimeData[0].ulValueLen;
+	}
+    }
+
+loser:
+    if (emailProfile == NULL) {
+	if (smimeData[1].pValue) {
+	    PORT_Free(smimeData[1].pValue);
+	}
+    }
+    if (profileTime == NULL || *profileTime == NULL) {
+	if (smimeData[0].pValue) {
+	    PORT_Free(smimeData[0].pValue);
+	}
+    }
+    return emailProfile;
+}
+
+
+SECStatus
+PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
+				 SECItem *emailProfile,  SECItem *profileTime)
+{
+    CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
+    CK_BBOOL ck_true = CK_TRUE;
+    CK_ATTRIBUTE theTemplate[] = {
+	{ CKA_CLASS, NULL, 0 },
+	{ CKA_TOKEN, NULL, 0 },
+	{ CKA_SUBJECT, NULL, 0 },
+	{ CKA_NETSCAPE_EMAIL, NULL, 0 },
+	{ CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 },
+	{ CKA_VALUE, NULL, 0 }
+    };
+    /* if you change the array, change the variable below as well */
+    int realSize = 0;
+    CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
+    CK_ATTRIBUTE *attrs = theTemplate;
+    CK_SESSION_HANDLE rwsession;
+    PK11SlotInfo *free_slot = NULL;
+    CK_RV crv;
+#ifdef DEBUG
+    int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
+#endif
+
+    PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); attrs++;
+    PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); attrs++;
+    PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); attrs++;
+    PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, 
+				emailAddr, PORT_Strlen(emailAddr)+1); attrs++;
+    if (profileTime) {
+	PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data,
+	                                            profileTime->len); attrs++;
+	PK11_SETATTRS(attrs, CKA_VALUE,emailProfile->data,
+	                                            emailProfile->len); attrs++;
+    }
+    realSize = attrs - theTemplate;
+    PORT_Assert (realSize <= tsize);
+
+    if (slot == NULL) {
+	free_slot = slot = PK11_GetInternalKeySlot();
+	/* we need to free the key slot in the end!!! */
+    }
+
+    rwsession = PK11_GetRWSession(slot);
+    if (rwsession == CK_INVALID_SESSION) {
+	PORT_SetError(SEC_ERROR_READ_ONLY);
+	if (free_slot) {
+	    PK11_FreeSlot(free_slot);
+	}
+	return SECFailure;
+    }
+
+    crv = PK11_GETTAB(slot)->
+                        C_CreateObject(rwsession,theTemplate,realSize,&smimeh);
+    if (crv != CKR_OK) {
+        PORT_SetError( PK11_MapError(crv) );
+    }
+
+    PK11_RestoreROSession(slot,rwsession);
+
+    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, PLArenaPool* arena,
+    PRInt32 decodeoptions)
+{
+    CERTSignedCrl *newCrl, *crl;
+    SECStatus rv;
+    CERTCertificate *caCert = NULL;
+
+    newCrl = crl = NULL;
+
+    do {
+        newCrl = CERT_DecodeDERCrlWithFlags(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)){
+            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);
+    }
+    if (caCert) {
+        CERT_DestroyCertificate(caCert);
+    }
+    return (crl);
+}
This site is hosted by Intevation GmbH (Datenschutzerklärung und Impressum | Privacy Policy and Imprint)