diff options
Diffstat (limited to 'security/nss/lib/pk11wrap/pk11cert.c')
-rw-r--r-- | security/nss/lib/pk11wrap/pk11cert.c | 2413 |
1 files changed, 0 insertions, 2413 deletions
diff --git a/security/nss/lib/pk11wrap/pk11cert.c b/security/nss/lib/pk11wrap/pk11cert.c deleted file mode 100644 index 5304b1248..000000000 --- a/security/nss/lib/pk11wrap/pk11cert.c +++ /dev/null @@ -1,2413 +0,0 @@ -/* - * The contents of this file are subject to the Mozilla Public - * License Version 1.1 (the "License"); you may not use this file - * except in compliance with the License. You may obtain a copy of - * the License at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS - * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or - * implied. See the License for the specific language governing - * rights and limitations under the License. - * - * The Original Code is the Netscape security libraries. - * - * The Initial Developer of the Original Code is Netscape - * Communications Corporation. Portions created by Netscape are - * Copyright (C) 1994-2000 Netscape Communications Corporation. All - * Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License Version 2 or later (the - * "GPL"), in which case the provisions of the GPL are applicable - * instead of those above. If you wish to allow use of your - * version of this file only under the terms of the GPL and not to - * allow others to use your version of this file under the MPL, - * indicate your decision by deleting the provisions above and - * replace them with the notice and other provisions required by - * the GPL. If you do not delete the provisions above, a recipient - * may use your version of this file under either the MPL or the - * GPL. - */ -/* - * This file implements the Symkey wrapper and the PKCS context - * Interfaces. - */ -#include "seccomon.h" -#include "secmod.h" -#include "prlock.h" -#include "secmodi.h" -#include "pkcs11.h" -#include "pk11func.h" -#include "cert.h" -#include "secitem.h" -#include "key.h" -#include "hasht.h" -#include "secoid.h" -#include "pkcs7t.h" -#include "cmsreclist.h" - -#include "certdb.h" -#include "secerr.h" -#include "sslerr.h" - -#define PK11_SEARCH_CHUNKSIZE 10 - -CK_OBJECT_HANDLE -pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx); - -/* - * build a cert nickname based on the token name and the label of the - * certificate If the label in NULL, build a label based on the ID. - */ -static int toHex(int x) { return (x < 10) ? (x+'0') : (x+'a'-10); } -#define MAX_CERT_ID 4 -#define DEFAULT_STRING "Cert ID " -static char * -pk11_buildNickname(PK11SlotInfo *slot,CK_ATTRIBUTE *cert_label, - CK_ATTRIBUTE *key_label, CK_ATTRIBUTE *cert_id) -{ - int prefixLen = PORT_Strlen(slot->token_name); - int suffixLen = 0; - char *suffix = NULL; - char buildNew[sizeof(DEFAULT_STRING)+MAX_CERT_ID*2]; - char *next,*nickname; - - if (slot->isInternal) { - return NULL; - } - - if ((cert_label) && (cert_label->pValue)) { - suffixLen = cert_label->ulValueLen; - suffix = (char*)cert_label->pValue; - } else if (key_label && (key_label->pValue)) { - suffixLen = key_label->ulValueLen; - suffix = (char*)key_label->pValue; - } else if ((cert_id) && cert_id->pValue) { - int i,first = cert_id->ulValueLen - MAX_CERT_ID; - int offset = sizeof(DEFAULT_STRING); - char *idValue = (char *)cert_id->pValue; - - PORT_Memcpy(buildNew,DEFAULT_STRING,sizeof(DEFAULT_STRING)-1); - next = buildNew + offset; - if (first < 0) first = 0; - for (i=first; i < (int) cert_id->ulValueLen; i++) { - *next++ = toHex((idValue[i] >> 4) & 0xf); - *next++ = toHex(idValue[i] & 0xf); - } - *next++ = 0; - suffix = buildNew; - suffixLen = PORT_Strlen(buildNew); - } else { - PORT_SetError( SEC_ERROR_LIBRARY_FAILURE ); - return NULL; - } - - next = nickname = (char *)PORT_Alloc(prefixLen+1+suffixLen+1); - if (nickname == NULL) return NULL; - - PORT_Memcpy(next,slot->token_name,prefixLen); - next += prefixLen; - *next++ = ':'; - PORT_Memcpy(next,suffix,suffixLen); - next += suffixLen; - *next++ = 0; - return nickname; -} - -/* - * return the object handle that matches the template - */ -CK_OBJECT_HANDLE -pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize) -{ - CK_OBJECT_HANDLE object; - CK_RV crv; - CK_ULONG objectCount; - - /* - * issue the find - */ - PK11_EnterSlotMonitor(slot); - crv=PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, theTemplate, tsize); - if (crv != CKR_OK) { - PK11_ExitSlotMonitor(slot); - PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; - } - - crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount); - PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); - PK11_ExitSlotMonitor(slot); - if ((crv != CKR_OK) || (objectCount < 1)) { - /* shouldn't use SSL_ERROR... here */ - PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) : - SSL_ERROR_NO_CERTIFICATE); - return CK_INVALID_KEY; - } - - /* blow up if the PKCS #11 module returns us and invalid object handle */ - PORT_Assert(object != CK_INVALID_KEY); - return object; -} - -/* - * return all the object handles that matches the template - */ -CK_OBJECT_HANDLE * -pk11_FindObjectsByTemplate(PK11SlotInfo *slot, - CK_ATTRIBUTE *findTemplate,int findCount,int *object_count) { - CK_OBJECT_HANDLE *objID = NULL; - CK_ULONG returned_count = 0; - CK_RV crv; - - - PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, findTemplate, - findCount); - if (crv != CKR_OK) { - PK11_ExitSlotMonitor(slot); - PORT_SetError( PK11_MapError(crv) ); - *object_count = -1; - return NULL; - } - - - /* - * collect all the Matching Objects - */ - do { - CK_OBJECT_HANDLE *oldObjID = objID; - - if (objID == NULL) { - objID = (CK_OBJECT_HANDLE *) PORT_Alloc(sizeof(CK_OBJECT_HANDLE)* - (*object_count+ PK11_SEARCH_CHUNKSIZE)); - } else { - objID = (CK_OBJECT_HANDLE *) PORT_Realloc(objID, - sizeof(CK_OBJECT_HANDLE)*(*object_count+PK11_SEARCH_CHUNKSIZE)); - } - - if (objID == NULL) { - if (oldObjID) PORT_Free(oldObjID); - break; - } - crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, - &objID[*object_count],PK11_SEARCH_CHUNKSIZE,&returned_count); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - PORT_Free(objID); - objID = NULL; - break; - } - *object_count += returned_count; - } while (returned_count == PK11_SEARCH_CHUNKSIZE); - - PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); - PK11_ExitSlotMonitor(slot); - - if (objID && (*object_count == 0)) { - PORT_Free(objID); - return NULL; - } - if (objID == NULL) *object_count = -1; - return objID; -} -/* - * given a PKCS #11 object, match it's peer based on the KeyID. searchID - * is typically a privateKey or a certificate while the peer is the opposite - */ -CK_OBJECT_HANDLE -PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID, - CK_OBJECT_CLASS matchclass) -{ - CK_ATTRIBUTE theTemplate[] = { - { CKA_ID, NULL, 0 }, - { CKA_CLASS, NULL, 0 } - }; - /* if you change the array, change the variable below as well */ - CK_ATTRIBUTE *keyclass = &theTemplate[1]; - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - /* if you change the array, change the variable below as well */ - CK_OBJECT_HANDLE peerID; - CK_OBJECT_HANDLE parent; - PRArenaPool *arena; - CK_RV crv; - - /* now we need to create space for the public key */ - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) return CK_INVALID_KEY; - - crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize); - if (crv != CKR_OK) { - PORT_FreeArena(arena,PR_FALSE); - PORT_SetError( PK11_MapError(crv) ); - return CK_INVALID_KEY; - } - - /* - * issue the find - */ - parent = *(CK_OBJECT_CLASS *)(keyclass->pValue); - *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass; - - peerID = pk11_FindObjectByTemplate(slot,theTemplate,tsize); - PORT_FreeArena(arena,PR_FALSE); - - return peerID; -} - -PRBool -PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert, - CK_OBJECT_HANDLE certID) -{ - CK_OBJECT_CLASS theClass; - - if (slot == NULL) return PR_FALSE; - if (cert == NULL) return PR_FALSE; - - theClass = CKO_PRIVATE_KEY; - if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) { - theClass = CKO_PUBLIC_KEY; - } - if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_KEY) { - return PR_TRUE; - } - - if (theClass == CKO_PUBLIC_KEY) { - SECKEYPublicKey *pubKey= CERT_ExtractPublicKey(cert); - CK_ATTRIBUTE theTemplate; - - if (pubKey == NULL) { - return PR_FALSE; - } - - PK11_SETATTRS(&theTemplate,0,NULL,0); - switch (pubKey->keyType) { - case rsaKey: - PK11_SETATTRS(&theTemplate,CKA_MODULUS, pubKey->u.rsa.modulus.data, - pubKey->u.rsa.modulus.len); - break; - case dsaKey: - PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dsa.publicValue.data, - pubKey->u.dsa.publicValue.len); - case dhKey: - PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dh.publicValue.data, - pubKey->u.dh.publicValue.len); - break; - } - - if (theTemplate.ulValueLen == 0) { - SECKEY_DestroyPublicKey(pubKey); - return PR_FALSE; - } - pk11_SignedToUnsigned(&theTemplate); - if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_KEY) { - SECKEY_DestroyPublicKey(pubKey); - return PR_TRUE; - } - SECKEY_DestroyPublicKey(pubKey); - } - return PR_FALSE; -} - -/* - * Check out if a cert has ID of zero. This is a magic ID that tells - * NSS that this cert may be an automagically trusted cert. - * The Cert has to be self signed as well. That check is done elsewhere. - * - */ -PRBool -pk11_isID0(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID) -{ - CK_ATTRIBUTE keyID = {CKA_ID, NULL, 0}; - PRBool isZero = PR_FALSE; - int i; - CK_RV crv; - - - crv = PK11_GetAttributes(NULL,slot,certID,&keyID,1); - if (crv != CKR_OK) { - return isZero; - } - - if (keyID.ulValueLen != 0) { - char *value = (char *)keyID.pValue; - isZero = PR_TRUE; /* ID exists, may be zero */ - for (i=0; i < (int) keyID.ulValueLen; i++) { - if (value[i] != 0) { - isZero = PR_FALSE; /* nope */ - break; - } - } - } - PORT_Free(keyID.pValue); - return isZero; - -} - -CERTCertificate -*pk11_fastCert(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, - CK_ATTRIBUTE *privateLabel, char **nickptr) -{ - CK_ATTRIBUTE certTemp[] = { - { CKA_ID, NULL, 0 }, - { CKA_VALUE, NULL, 0 }, - { CKA_LABEL, NULL, 0 } - }; - CK_ATTRIBUTE *id = &certTemp[0]; - CK_ATTRIBUTE *certDER = &certTemp[1]; - CK_ATTRIBUTE *label = &certTemp[2]; - SECItem derCert; - int csize = sizeof(certTemp)/sizeof(certTemp[0]); - PRArenaPool *arena; - char *nickname; - CERTCertificate *cert; - CK_RV crv; - - arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); - if (arena == NULL) return NULL; - /* - * grab the der encoding - */ - crv = PK11_GetAttributes(arena,slot,certID,certTemp,csize); - if (crv != CKR_OK) { - PORT_FreeArena(arena,PR_FALSE); - PORT_SetError( PK11_MapError(crv) ); - return NULL; - } - - /* - * build a certificate out of it - */ - derCert.data = (unsigned char*)certDER->pValue; - derCert.len = certDER->ulValueLen; - - /* figure out the nickname.... */ - nickname = pk11_buildNickname(slot,label,privateLabel,id); - cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert, nickname, - PR_FALSE, PR_TRUE); - if (nickptr) { - *nickptr = nickname; - } else { - if (nickname) PORT_Free(nickname); - } - PORT_FreeArena(arena,PR_FALSE); - return cert; -} - -/* - * Build an CERTCertificate structure from a PKCS#11 object ID.... certID - * Must be a CertObject. This code does not explicitly checks that. - */ -CERTCertificate * -PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID, - CK_ATTRIBUTE *privateLabel) -{ - char * nickname = NULL; - CERTCertificate *cert = NULL; - CERTCertTrust *trust; - PRBool isFortezzaRootCA = PR_FALSE; - PRBool swapNickname = PR_FALSE; - - cert = pk11_fastCert(slot,certID,privateLabel, &nickname); - if (cert == NULL) goto loser; - - if (nickname) { - if (cert->nickname != NULL) { - cert->dbnickname = cert->nickname; - } - cert->nickname = PORT_ArenaStrdup(cert->arena,nickname); - PORT_Free(nickname); - nickname = NULL; - swapNickname = PR_TRUE; - } - - /* remember where this cert came from.... If we have just looked - * it up from the database and it already has a slot, don't add a new - * one. */ - if (cert->slot == NULL) { - cert->slot = PK11_ReferenceSlot(slot); - cert->pkcs11ID = certID; - cert->ownSlot = PR_TRUE; - } - - if (cert->trust == NULL) { - unsigned int type; - - trust = - (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust)); - if (trust == NULL) goto loser; - - PORT_Memset(trust,0, sizeof(CERTCertTrust)); - cert->trust = trust; - /* build some cert trust flags */ - if (CERT_IsCACert(cert, &type)) { - unsigned int trustflags = CERTDB_VALID_CA; - - /* Allow PKCS #11 modules to give us trusted CA's. We only accept - * valid CA's which are self-signed here. They must have an object - * ID of '0'. */ - if (pk11_isID0(slot,certID) && - SECITEM_CompareItem(&cert->derSubject,&cert->derIssuer) - == SECEqual) { - trustflags |= CERTDB_TRUSTED_CA; - /* is the slot a fortezza card? allow the user or - * admin to turn on objectSigning, but don't turn - * full trust on explicitly */ - if (PK11_DoesMechanism(slot,CKM_KEA_KEY_DERIVE)) { - trust->objectSigningFlags |= CERTDB_VALID_CA; - isFortezzaRootCA = PR_TRUE; - } - } - if ((type & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) { - trust->sslFlags |= trustflags; - } - if ((type & NS_CERT_TYPE_EMAIL_CA) == NS_CERT_TYPE_EMAIL_CA) { - trust->emailFlags |= trustflags; - } - if ((type & NS_CERT_TYPE_OBJECT_SIGNING_CA) - == NS_CERT_TYPE_OBJECT_SIGNING_CA) { - trust->objectSigningFlags |= trustflags; - } - } - } else { - trust = cert->trust; - } - - if (PK11_IsUserCert(slot,cert,certID)) { - trust->sslFlags |= CERTDB_USER; - trust->emailFlags |= CERTDB_USER; - /* trust->objectSigningFlags |= CERTDB_USER; */ - } - - - /* if fortezza, write the root cert to the DB */ - if ((isFortezzaRootCA) && (!cert->isperm)) { - char *name = NULL; - if (swapNickname) { - nickname = cert->nickname; - cert->nickname = cert->dbnickname; - } - if (cert->nickname) { - name = PORT_Strdup(cert->nickname); - } - if (name == NULL) name = CERT_MakeCANickname(cert); - CERT_AddTempCertToPerm(cert,name,cert->trust); - if (name) PORT_Free(name); - if (swapNickname) { - if (cert->nickname != NULL) { - cert->dbnickname = cert->nickname; - } - cert->nickname = PORT_ArenaStrdup(cert->arena,nickname); - } - - } - - return cert; - -loser: - if (nickname) PORT_Free(nickname); - if (cert) CERT_DestroyCertificate(cert); - return NULL; -} - - -/* - * Build get a certificate from a private key - */ -CERTCertificate * -PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey) -{ - PK11SlotInfo *slot = privKey->pkcs11Slot; - CK_OBJECT_HANDLE certID = - PK11_MatchItem(slot,privKey->pkcs11ID,CKO_CERTIFICATE); - SECStatus rv; - CERTCertificate *cert; - - if (certID == CK_INVALID_KEY) { - /* couldn't find it on the card, look in our data base */ - SECItem derSubject; - - rv = PK11_ReadAttribute(slot, privKey->pkcs11ID, CKA_SUBJECT, NULL, - &derSubject); - if (rv != SECSuccess) { - PORT_SetError(SSL_ERROR_NO_CERTIFICATE); - return NULL; - } - - cert = CERT_FindCertByName(CERT_GetDefaultCertDB(),&derSubject); - PORT_Free(derSubject.data); - return cert; - } - cert = PK11_MakeCertFromHandle(slot,certID,NULL); - return (cert); - -} - -/* - * destroy a private key if there are no matching certs. - * this function also frees the privKey structure. - */ -SECStatus -PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey) -{ - CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey); - - /* found a cert matching the private key?. */ - if (cert != NULL) { - /* yes, don't delete the key */ - CERT_DestroyCertificate(cert); - SECKEY_DestroyPrivateKey(privKey); - return SECWouldBlock; - } - /* now, then it's safe for the key to go away */ - PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID); - SECKEY_DestroyPrivateKey(privKey); - return SECSuccess; -} - - -/* - * delete a cert and it's private key (if no other certs are pointing to the - * private key. - */ -SECStatus -PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx) -{ - SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert,wincx); - CK_OBJECT_HANDLE pubKey; - PK11SlotInfo *slot = NULL; - - pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx); - if (privKey) { - PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID); - PK11_DeleteTokenPrivateKey(privKey); - } - if ((pubKey != CK_INVALID_KEY) && (slot != NULL)) { - PK11_DestroyTokenObject(slot,pubKey); - PK11_FreeSlot(slot); - } - return SECSuccess; -} - -/* - * count the number of objects that match the template. - */ -int -PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, - int templateCount) -{ - CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE]; - int object_count = 0; - CK_ULONG returned_count = 0; - CK_RV crv; - - PK11_EnterSlotMonitor(slot); - crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, - findTemplate, templateCount); - if (crv != CKR_OK) { - PK11_ExitSlotMonitor(slot); - PORT_SetError( PK11_MapError(crv) ); - return 0; - } - - /* - * collect all the Matching Objects - */ - do { - crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, - objID,PK11_SEARCH_CHUNKSIZE,&returned_count); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - break; - } - object_count += returned_count; - } while (returned_count == PK11_SEARCH_CHUNKSIZE); - - PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); - PK11_ExitSlotMonitor(slot); - return object_count; -} - -/* - * cert callback structure - */ -typedef struct pk11DoCertCallbackStr { - SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *); - SECStatus(* noslotcallback)(CERTCertificate*, void *); - void *callbackArg; -} pk11DoCertCallback; - -/* - * callback to map object handles to certificate structures. - */ -SECStatus -pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg) -{ - CERTCertificate *cert; - pk11DoCertCallback *certcb = (pk11DoCertCallback *) arg; - - cert = PK11_MakeCertFromHandle(slot, certID, NULL); - - if (cert == NULL) { - return SECFailure; - } - - if (certcb ) { - if (certcb->callback) { - (*certcb->callback)(slot, cert, certcb->callbackArg); - } - if (certcb->noslotcallback) { - (*certcb->noslotcallback)(cert, certcb->callbackArg); - } - } - - CERT_DestroyCertificate(cert); - - return SECSuccess; -} - - -/* - * key call back structure. - */ -typedef struct pk11KeyCallbackStr { - SECStatus (* callback)(SECKEYPrivateKey *,void *); - void *callbackArg; - void *wincx; -} pk11KeyCallback; - -/* - * callback to map Object Handles to Private Keys; - */ -SECStatus -pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg) -{ - SECStatus rv = SECSuccess; - SECKEYPrivateKey *privKey; - pk11KeyCallback *keycb = (pk11KeyCallback *) arg; - - privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx); - - if (privKey == NULL) { - return SECFailure; - } - - if (keycb && (keycb->callback)) { - rv = (*keycb->callback)(privKey,keycb->callbackArg); - } - - SECKEY_DestroyPrivateKey(privKey); - return rv; -} - - -/* Traverse slots callback */ -typedef struct pk11TraverseSlotStr { - SECStatus (*callback)(PK11SlotInfo *,CK_OBJECT_HANDLE, void *); - void *callbackArg; - CK_ATTRIBUTE *findTemplate; - int templateCount; -} pk11TraverseSlotCert; - -/* - * Extract all the certs on a card from a slot. - */ -SECStatus -PK11_TraverseSlot(PK11SlotInfo *slot, void *arg) -{ - int i; - CK_OBJECT_HANDLE *objID = NULL; - int object_count = 0; - CK_ULONG returned_count = 0; - pk11TraverseSlotCert *slotcb = (pk11TraverseSlotCert *) arg; - - objID = pk11_FindObjectsByTemplate(slot,slotcb->findTemplate, - slotcb->templateCount,&object_count); - - /*Actually this isn't a failure... there just were no objs to be found*/ - if (object_count == 0) { - return SECSuccess; - } - - if (objID == NULL) { - return SECFailure; - } - - for (i=0; i < object_count; i++) { - (*slotcb->callback)(slot,objID[i],slotcb->callbackArg); - } - PORT_Free(objID); - return SECSuccess; -} - -typedef struct pk11CertCallbackStr { - SECStatus(* callback)(CERTCertificate*,SECItem *,void *); - void *callbackArg; -} pk11CertCallback; - -static SECStatus -pk11_SaveCert(PK11SlotInfo *slot, CERTCertificate *cert, void *arg) -{ - pk11CertCallback *certcb = (pk11CertCallback *)arg; - SECStatus rv = SECSuccess; - - if (slot->cert_count == slot->array_size) return CKR_OK; - - slot->cert_array[slot->cert_count] = CERT_DupCertificate(cert); - if (slot->cert_array[slot->cert_count] == NULL) { - return SECFailure; - } - /* now the slot has a hold of the cert, free the slot's element in the - * cert.. */ - if (cert->ownSlot && (slot == cert->slot)) { - PK11_FreeSlot(cert->slot); - cert->ownSlot = PR_FALSE; - } - slot->cert_count++; - - if (certcb->callback) { - rv = (*certcb->callback)(cert, NULL, certcb->callbackArg); - } - return rv; -} - - -/* free the slots */ -void -PK11_FreeSlotCerts(PK11SlotInfo *slot) -{ - int i; - - if (slot->cert_array) { - for (i=0; i < slot->cert_count; i++) { - /* if we point the cert on our array, the cert doesn't have a - * reference to use (otherwise you would never be able to free - * a slot :) */ - if ((slot->cert_array[i]->slot == slot) && - (!slot->cert_array[i]->ownSlot)) { - slot->cert_array[i]->slot = NULL; - } - CERT_DestroyCertificate(slot->cert_array[i]); - } - PORT_Free(slot->cert_array); - slot->cert_array = NULL; - slot->cert_count = 0; - } - return; -} - -/* - * Update PQG parameters for all the certs on a slot. - */ -static SECStatus -pk11_UpdateSlotPQG(PK11SlotInfo *slot) -{ - int i, tag; - CERTCertificate * cert; - SECOidData *oid; - SECStatus rv1 = SECSuccess; - SECStatus rv2 = SECSuccess; - - if (slot->cert_array) { - for (i=0; i < slot->cert_count; i++) { - - cert = slot->cert_array[i]; - - oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm); - - if (oid != NULL) { - tag = oid->offset; - - /* Check if cert has a DSA or Fortezza public key */ - if ( (tag == SEC_OID_MISSI_KEA_DSS_OLD) || - (tag == SEC_OID_MISSI_DSS_OLD) || - (tag == SEC_OID_MISSI_KEA_DSS) || - (tag == SEC_OID_MISSI_DSS) || - (tag == SEC_OID_ANSIX9_DSA_SIGNATURE) || - (tag == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) || - (tag == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) { - - /* update PQG parameters */ - - rv1 = SECKEY_UpdateCertPQG(cert); - if (rv1 == SECFailure) { - rv2 = rv1; - } - } - } /* end of if oid != NULL */ - } /* end of for loop */ - } - return rv2; -} - - -/* - * Extract all the certs on a card from a slot. - */ -static SECStatus -pk11_ExtractCertsFromSlot(PK11SlotInfo *slot, void *arg) -{ - pk11TraverseSlotCert *slotcb = (pk11TraverseSlotCert *) arg; - int object_count; - SECStatus rv; - - rv = SECSuccess; - - PK11_FreeSlotCerts(slot); - - object_count = PK11_NumberObjectsFor(slot,slotcb->findTemplate, - slotcb->templateCount); - - /*Actually this isn't a failure... there just were no certs to be found*/ - if (object_count == 0) { - return SECSuccess; - } - - slot->cert_array = (CERTCertificate **) - PORT_Alloc(sizeof(CERTCertificate *)*object_count); - if (slot->cert_array == NULL) { - return SECFailure; - } - slot->cert_count = 0; - slot->array_size = object_count; - PK11_TraverseSlot(slot,arg); - - /* Update the PQG parameters for the extracted certs. */ - rv = pk11_UpdateSlotPQG(slot); - - return rv; -} - -/* - * read all the certs from a slot - */ -SECStatus -PK11_ReadSlotCerts(PK11SlotInfo *slot) -{ - - /* build slot list */ - pk11CertCallback caller; - pk11DoCertCallback saver; - pk11TraverseSlotCert creater; - CK_ATTRIBUTE theTemplate; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - - PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - - caller.callback = NULL; - caller.callbackArg = NULL; - saver.callback = pk11_SaveCert; - saver.noslotcallback = NULL; - saver.callbackArg = (void *) & caller; - creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & saver; - creater.findTemplate = &theTemplate; - creater.templateCount = 1; - - return pk11_ExtractCertsFromSlot(slot, &creater); -} - -/* - * Extract all the certs on a card from a slot. - */ -static SECStatus -pk11_TraverseAllSlots(PRBool loadCerts, - SECStatus (*callback)(PK11SlotInfo *,void *),void *arg,void *wincx) { - - PK11SlotList *list; - PK11SlotListElement *le; - SECStatus rv; - - /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,loadCerts,wincx); - if (list == NULL) return SECFailure; - - /* look at each slot and authenticate as necessary */ - for (le = list->head ; le; le = le->next) { - /* don't nab internal slots */ - if ((!loadCerts) && le->slot->isInternal == PR_TRUE) { - continue; - } - if (loadCerts || !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, loadCerts, wincx); - if (rv != SECSuccess) continue; - } - (*callback)(le->slot,arg); - } - - PK11_FreeSlotList(list); - - return SECSuccess; -} - -/* - * Extract all the certs on a card from a slot. - */ -SECStatus -PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *), - void *arg, void *wincx) { - pk11CertCallback caller; - pk11DoCertCallback saver; - pk11TraverseSlotCert creater; - CK_ATTRIBUTE theTemplate; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - - PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass)); - - caller.callback = callback; - caller.callbackArg = arg; - saver.callback = pk11_SaveCert; - saver.noslotcallback = NULL; - saver.callbackArg = (void *) & caller; - creater.callback = pk11_DoCerts; - creater.callbackArg = (void *) & saver; - creater.findTemplate = &theTemplate; - creater.templateCount = 1; - - return pk11_TraverseAllSlots(PR_FALSE, pk11_ExtractCertsFromSlot, - &creater, wincx); -} - -CK_OBJECT_HANDLE * -PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, - CK_OBJECT_CLASS objclass, int *returnCount, void *wincx) { - char *tokenName; - char *delimit; - PK11SlotInfo *slot; - CK_OBJECT_HANDLE *objID; - CK_ATTRIBUTE findTemplate[] = { - { CKA_LABEL, NULL, 0}, - { CKA_CLASS, NULL, 0}, - }; - int findCount = sizeof(findTemplate)/sizeof(findTemplate[0]); - SECStatus rv; - PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass)); - - *slotptr = slot = NULL; - *returnCount = 0; - /* first find the slot associated with this nickname */ - if ((delimit = PORT_Strchr(nickname,':')) != NULL) { - int len = delimit - nickname; - tokenName = (char*)PORT_Alloc(len+1); - PORT_Memcpy(tokenName,nickname,len); - tokenName[len] = 0; - - slot = *slotptr = PK11_FindSlotByName(tokenName); - PORT_Free(tokenName); - /* if we couldn't find a slot, assume the nickname is an internal cert - * with no proceding slot name */ - if (slot == NULL) { - slot = *slotptr = PK11_GetInternalKeySlot(); - } else { - nickname = delimit+1; - } - } else { - *slotptr = slot = PK11_GetInternalKeySlot(); - } - if (slot == NULL) { - return CK_INVALID_KEY; - } - - if (!PK11_IsFriendly(slot)) { - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - PK11_FreeSlot(slot); - *slotptr = NULL; - return CK_INVALID_KEY; - } - } - - findTemplate[0].pValue = nickname; - findTemplate[0].ulValueLen = PORT_Strlen(nickname); - objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,returnCount); - if (objID == NULL) { - /* PKCS #11 isn't clear on whether or not the NULL is - * stored in the template.... try the find again with the - * full null terminated string. */ - findTemplate[0].ulValueLen += 1; - objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount, - returnCount); - if (objID == NULL) { - /* Well that's the best we can do. It's just not here */ - /* what about faked nicknames? */ - PK11_FreeSlot(slot); - *slotptr = NULL; - *returnCount = 0; - } - } - - return objID; -} - - -CERTCertificate * -PK11_FindCertFromNickname(char *nickname, void *wincx) { - PK11SlotInfo *slot; - int count=0; - CK_OBJECT_HANDLE *certID = PK11_FindObjectsFromNickname(nickname,&slot, - CKO_CERTIFICATE, &count, wincx); - CERTCertificate *cert; - - if (certID == CK_INVALID_KEY) return NULL; - cert = PK11_MakeCertFromHandle(slot,certID[0],NULL); - PK11_FreeSlot(slot); - PORT_Free(certID); - return cert; -} - -CERTCertList * -PK11_FindCertsFromNickname(char *nickname, void *wincx) { - PK11SlotInfo *slot; - int i,count = 0; - CK_OBJECT_HANDLE *certID = PK11_FindObjectsFromNickname(nickname,&slot, - CKO_CERTIFICATE, &count, wincx); - CERTCertList *certList = NULL; - - if (certID == NULL) return NULL; - - certList= CERT_NewCertList(); - - for (i=0; i < count; i++) { - CERTCertificate *cert = PK11_MakeCertFromHandle(slot,certID[i],NULL); - - if (cert) CERT_AddCertToListTail(certList,cert); - } - - if (CERT_LIST_HEAD(certList) == NULL) { - CERT_DestroyCertList(certList); - certList = NULL; - } - PK11_FreeSlot(slot); - PORT_Free(certID); - return certList; -} - -/* - * extract a key ID for a certificate... - * NOTE: We call this function from PKCS11.c If we ever use - * pkcs11 to extract the public key (we currently do not), this will break. - */ -SECItem * -PK11_GetPubIndexKeyID(CERTCertificate *cert) { - SECKEYPublicKey *pubk; - SECItem *newItem = NULL; - - pubk = CERT_ExtractPublicKey(cert); - if (pubk == NULL) return NULL; - - switch (pubk->keyType) { - case rsaKey: - newItem = SECITEM_DupItem(&pubk->u.rsa.modulus); - break; - case dsaKey: - newItem = SECITEM_DupItem(&pubk->u.dsa.publicValue); - break; - case dhKey: - newItem = SECITEM_DupItem(&pubk->u.dh.publicValue); - case fortezzaKey: - default: - newItem = NULL; /* Fortezza Fix later... */ - } - SECKEY_DestroyPublicKey(pubk); - /* make hash of it */ - return newItem; -} - -/* - * generate a CKA_ID from a certificate. - */ -SECItem * -pk11_mkcertKeyID(CERTCertificate *cert) { - SECItem *pubKeyData = PK11_GetPubIndexKeyID(cert) ; - SECItem *certCKA_ID; - - if (pubKeyData == NULL) return NULL; - - certCKA_ID = PK11_MakeIDFromPubKey(pubKeyData); - SECITEM_FreeItem(pubKeyData,PR_TRUE); - return certCKA_ID; -} - - -/* - * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated - * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make - * smart cards happy. - */ -SECItem * -PK11_MakeIDFromPubKey(SECItem *pubKeyData) { - PK11Context *context; - SECItem *certCKA_ID; - SECStatus rv; - - context = PK11_CreateDigestContext(SEC_OID_SHA1); - if (context == NULL) { - return NULL; - } - - rv = PK11_DigestBegin(context); - if (rv == SECSuccess) { - rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len); - } - if (rv != SECSuccess) { - PK11_DestroyContext(context,PR_TRUE); - return NULL; - } - - certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem)); - if (certCKA_ID == NULL) { - PK11_DestroyContext(context,PR_TRUE); - return NULL; - } - - certCKA_ID->len = SHA1_LENGTH; - certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len); - if (certCKA_ID->data == NULL) { - PORT_Free(certCKA_ID); - PK11_DestroyContext(context,PR_TRUE); - return NULL; - } - - rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len, - SHA1_LENGTH); - PK11_DestroyContext(context,PR_TRUE); - if (rv != SECSuccess) { - SECITEM_FreeItem(certCKA_ID,PR_TRUE); - return NULL; - } - - return certCKA_ID; -} - -/* - * Write the cert into the token. - */ -SECStatus -PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, - CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) { - int len = 0; - SECItem *keyID = pk11_mkcertKeyID(cert); - CK_ATTRIBUTE keyAttrs[] = { - { CKA_LABEL, NULL, 0}, - { CKA_SUBJECT, NULL, 0}, - }; - CK_OBJECT_CLASS certc = CKO_CERTIFICATE; - CK_CERTIFICATE_TYPE certType = CKC_X_509; - CK_OBJECT_HANDLE certID; - CK_SESSION_HANDLE rwsession; - CK_BBOOL cktrue = CK_TRUE; - SECStatus rv = SECFailure; - CK_ATTRIBUTE certAttrs[] = { - { CKA_ID, NULL, 0 }, - { CKA_LABEL, NULL, 0}, - { CKA_CLASS, NULL, 0}, - { CKA_TOKEN, NULL, 0}, - { CKA_CERTIFICATE_TYPE, NULL, 0}, - { CKA_SUBJECT, NULL, 0}, - { CKA_ISSUER, NULL, 0}, - { CKA_SERIAL_NUMBER, NULL, 0}, - { CKA_VALUE, NULL, 0}, - { CKA_NETSCAPE_TRUST, NULL, 0}, - }; - int certCount = sizeof(certAttrs)/sizeof(certAttrs[0]), keyCount = 2; - CK_ATTRIBUTE *attrs; - CK_RV crv; - SECCertUsage *certUsage = NULL; - - if (keyID == NULL) { - PORT_SetError(SEC_ERROR_ADDING_CERT); - return rv; - } - - len = ((nickname) ? PORT_Strlen(nickname) : 0); - - attrs = certAttrs; - PK11_SETATTRS(attrs,CKA_ID, keyID->data, keyID->len); attrs++; - if(nickname) { - PK11_SETATTRS(attrs,CKA_LABEL, nickname, len ); attrs++; - } - PK11_SETATTRS(attrs,CKA_CLASS, &certc, sizeof(certc) ); attrs++; - PK11_SETATTRS(attrs,CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++; - PK11_SETATTRS(attrs,CKA_CERTIFICATE_TYPE, &certType, - sizeof(certType)); attrs++; - PK11_SETATTRS(attrs,CKA_SUBJECT, cert->derSubject.data, - cert->derSubject.len ); attrs++; - PK11_SETATTRS(attrs,CKA_ISSUER, cert->derIssuer.data, - cert->derIssuer.len ); attrs++; - PK11_SETATTRS(attrs,CKA_SERIAL_NUMBER, cert->serialNumber.data, - cert->serialNumber.len); attrs++; - PK11_SETATTRS(attrs,CKA_VALUE, cert->derCert.data, cert->derCert.len); - if(includeTrust && PK11_IsInternal(slot)) { - attrs++; - certUsage = (SECCertUsage*)PORT_Alloc(sizeof(SECCertUsage)); - if(!certUsage) { - SECITEM_FreeItem(keyID,PR_TRUE); - PORT_SetError(SEC_ERROR_NO_MEMORY); - return rv; - } - *certUsage = certUsageUserCertImport; - PK11_SETATTRS(attrs,CKA_NETSCAPE_TRUST, certUsage, sizeof(SECCertUsage)); - } else { - certCount--; - } - - attrs = keyAttrs; - if(nickname) { - PK11_SETATTRS(attrs,CKA_LABEL, nickname, len ); attrs++; - } - PK11_SETATTRS(attrs,CKA_SUBJECT, cert->derSubject.data, - cert->derSubject.len ); - - if(!nickname) { - certCount--; - keyCount--; - } - - rwsession = PK11_GetRWSession(slot); - crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession,key,keyAttrs, - keyCount); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - goto done; - } - - crv = PK11_GETTAB(slot)-> - C_CreateObject(rwsession,certAttrs,certCount,&certID); - if (crv == CKR_OK) { - rv = SECSuccess; - } else { - PORT_SetError( PK11_MapError(crv) ); - } - -done: - SECITEM_FreeItem(keyID,PR_TRUE); - PK11_RestoreROSession(slot,rwsession); - if(certUsage) { - PORT_Free(certUsage); - } - return rv; - -} - -/* - * get a certificate handle, look at the cached handle first.. - */ -CK_OBJECT_HANDLE -pk11_getcerthandle(PK11SlotInfo *slot, CERTCertificate *cert, - CK_ATTRIBUTE *theTemplate,int tsize) -{ - CK_OBJECT_HANDLE certh; - - if (cert->slot == slot) { - certh = cert->pkcs11ID; - if (certh == CK_INVALID_KEY) { - certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize); - cert->pkcs11ID = certh; - } - } else { - certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize); - } - return certh; -} - -/* - * return the private key From a given Cert - */ -SECKEYPrivateKey * -PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert, - void *wincx) { - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_VALUE, NULL, 0 }, - { CKA_CLASS, NULL, 0 } - }; - /* if you change the array, change the variable below as well */ - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - CK_OBJECT_HANDLE certh; - CK_OBJECT_HANDLE keyh; - CK_ATTRIBUTE *attrs = theTemplate; - SECStatus rv; - - PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, - cert->derCert.len); attrs++; - PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); - - /* - * issue the find - */ - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - return NULL; - } - - certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { - return NULL; - } - keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY); - if (keyh == CK_INVALID_KEY) { return NULL; } - return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx); -} - - -/* - * return the private key with the given ID - */ -static CK_OBJECT_HANDLE -pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID) { - CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY; - CK_ATTRIBUTE theTemplate[] = { - { CKA_ID, NULL, 0 }, - { CKA_CLASS, NULL, 0 }, - }; - /* if you change the array, change the variable below as well */ - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - CK_ATTRIBUTE *attrs = theTemplate; - - PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++; - PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey)); - - return pk11_FindObjectByTemplate(slot,theTemplate,tsize); -} - -/* - * import a cert for a private key we have already generated. Set the label - * on both to be the nickname. This is for the Key Gen, orphaned key case. - */ -PK11SlotInfo * -PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, - void *wincx) { - PK11SlotList *list; - PK11SlotListElement *le; - SECItem *keyID; - CK_OBJECT_HANDLE key; - PK11SlotInfo *slot = NULL; - SECStatus rv; - - keyID = pk11_mkcertKeyID(cert); - /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); - if ((keyID == NULL) || (list == NULL)) { - if (keyID) SECITEM_FreeItem(keyID,PR_TRUE); - if (list) PK11_FreeSlotList(list); - return NULL; - } - - /* Look for the slot that holds the Key */ - for (le = list->head ; le; le = le->next) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - - key = pk11_FindPrivateKeyFromCertID(le->slot,keyID); - if (key != CK_INVALID_KEY) { - slot = PK11_ReferenceSlot(le->slot); - if (keyPtr) *keyPtr = key; - break; - } - } - - SECITEM_FreeItem(keyID,PR_TRUE); - PK11_FreeSlotList(list); - return slot; - -} - -PK11SlotInfo * -PK11_ImportCertForKey(CERTCertificate *cert, char *nickname,void *wincx) { - PK11SlotInfo *slot = NULL; - CK_OBJECT_HANDLE key; - - slot = PK11_KeyForCertExists(cert,&key,wincx); - - if (slot) { - if (PK11_ImportCert(slot,cert,key,nickname,PR_FALSE) != SECSuccess) { - PK11_FreeSlot(slot); - slot = NULL; - } - } else { - PORT_SetError(SEC_ERROR_ADDING_CERT); - } - - return slot; -} - -static CK_OBJECT_HANDLE -pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, - CK_ATTRIBUTE *searchTemplate, int count, void *wincx) { - PK11SlotList *list; - PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - PK11SlotInfo *slot = NULL; - SECStatus rv; - - *slotPtr = NULL; - - /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); - if (list == NULL) { - if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; - } - - - /* Look for the slot that holds the Key */ - for (le = list->head ; le; le = le->next) { - if (!PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - } - - certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { - slot = PK11_ReferenceSlot(le->slot); - break; - } - } - - PK11_FreeSlotList(list); - - if (slot == NULL) { - return CK_INVALID_KEY; - } - *slotPtr = slot; - return certHandle; -} - - -/* - * We're looking for a cert which we have the private key for that's on the - * list of recipients. This searches one slot. - * this is the new version for NSS SMIME code - * this stuff should REALLY be in the SMIME code, but some things in here are not public - * (they should be!) - */ -static CK_OBJECT_HANDLE -pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipientlist, int *rlIndex) -{ - CK_OBJECT_HANDLE certHandle; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_OBJECT_CLASS peerClass ; - CK_ATTRIBUTE searchTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_ISSUER, NULL, 0 }, - { CKA_SERIAL_NUMBER, NULL, 0} - }; - int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE); - NSSCMSRecipient *ri = NULL; - CK_ATTRIBUTE *attrs; - int i; - - peerClass = CKO_PRIVATE_KEY; - if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) { - peerClass = CKO_PUBLIC_KEY; - } - - for (i=0; (ri = recipientlist[i]) != NULL; i++) { - /* XXXXX fixme - not yet implemented! */ - if (ri->kind == RLSubjKeyID) - continue; - - attrs = searchTemplate; - - PK11_SETATTRS(attrs, CKA_CLASS, &certClass,sizeof(certClass)); attrs++; - PK11_SETATTRS(attrs, CKA_ISSUER, ri->id.issuerAndSN->derIssuer.data, - ri->id.issuerAndSN->derIssuer.len); attrs++; - PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, - ri->id.issuerAndSN->serialNumber.data,ri->id.issuerAndSN->serialNumber.len); - - certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { - CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL); - if (PK11_IsUserCert(slot,cert,certHandle)) { - /* we've found a cert handle, now let's see if there is a key - * associated with it... */ - ri->slot = PK11_ReferenceSlot(slot); - *rlIndex = i; - - CERT_DestroyCertificate(cert); - return certHandle; - } - CERT_DestroyCertificate(cert); - } - } - *rlIndex = -1; - return CK_INVALID_KEY; -} - -/* - * This function is the same as above, but it searches all the slots. - * this is the new version for NSS SMIME code - * this stuff should REALLY be in the SMIME code, but some things in here are not public - * (they should be!) - */ -static CK_OBJECT_HANDLE -pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *wincx, int *rlIndex) -{ - PK11SlotList *list; - PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - PK11SlotInfo *slot = NULL; - SECStatus rv; - - /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); - if (list == NULL) { - if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; - } - - /* Look for the slot that holds the Key */ - for (le = list->head ; le; le = le->next) { - if ( !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - } - - certHandle = pk11_FindCertObjectByRecipientNew(le->slot, recipientlist, rlIndex); - if (certHandle != CK_INVALID_KEY) - break; - } - - PK11_FreeSlotList(list); - - return (le == NULL) ? CK_INVALID_KEY : certHandle; -} - -/* - * We're looking for a cert which we have the private key for that's on the - * list of recipients. This searches one slot. - */ -static CK_OBJECT_HANDLE -pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, - SEC_PKCS7RecipientInfo **recipientArray,SEC_PKCS7RecipientInfo **rip) -{ - CK_OBJECT_HANDLE certHandle; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_OBJECT_CLASS peerClass ; - CK_ATTRIBUTE searchTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_ISSUER, NULL, 0 }, - { CKA_SERIAL_NUMBER, NULL, 0} - }; - int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE); - SEC_PKCS7RecipientInfo *ri = NULL; - CK_ATTRIBUTE *attrs; - int i; - - - peerClass = CKO_PRIVATE_KEY; - if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) { - peerClass = CKO_PUBLIC_KEY; - } - - for (i=0; (ri = recipientArray[i]) != NULL; i++) { - attrs = searchTemplate; - - PK11_SETATTRS(attrs, CKA_CLASS, &certClass,sizeof(certClass)); attrs++; - PK11_SETATTRS(attrs, CKA_ISSUER, ri->issuerAndSN->derIssuer.data, - ri->issuerAndSN->derIssuer.len); attrs++; - PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, - ri->issuerAndSN->serialNumber.data,ri->issuerAndSN->serialNumber.len); - - certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count); - if (certHandle != CK_INVALID_KEY) { - CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL); - if (PK11_IsUserCert(slot,cert,certHandle)) { - /* we've found a cert handle, now let's see if there is a key - * associated with it... */ - *rip = ri; - - CERT_DestroyCertificate(cert); - return certHandle; - } - CERT_DestroyCertificate(cert); - } - } - *rip = NULL; - return CK_INVALID_KEY; -} - -/* - * This function is the same as above, but it searches all the slots. - */ -static CK_OBJECT_HANDLE -pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, - SEC_PKCS7RecipientInfo **recipientArray,SEC_PKCS7RecipientInfo **rip, - void *wincx) { - PK11SlotList *list; - PK11SlotListElement *le; - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - PK11SlotInfo *slot = NULL; - SECStatus rv; - - *slotPtr = NULL; - - /* get them all! */ - list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx); - if (list == NULL) { - if (list) PK11_FreeSlotList(list); - return CK_INVALID_KEY; - } - - *rip = NULL; - - /* Look for the slot that holds the Key */ - for (le = list->head ; le; le = le->next) { - if ( !PK11_IsFriendly(le->slot)) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - } - - certHandle = pk11_FindCertObjectByRecipient(le->slot, - recipientArray,rip); - if (certHandle != CK_INVALID_KEY) { - slot = PK11_ReferenceSlot(le->slot); - break; - } - } - - PK11_FreeSlotList(list); - - if (slot == NULL) { - return CK_INVALID_KEY; - } - *slotPtr = slot; - return certHandle; -} - -/* - * We need to invert the search logic for PKCS 7 because if we search for - * each cert on the list over all the slots, we wind up with lots of spurious - * password prompts. This way we get only one password prompt per slot, at - * the max, and most of the time we can find the cert, and only prompt for - * the key... - */ -CERTCertificate * -PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, - SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip, - SECKEYPrivateKey**privKey, void *wincx) -{ - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY; - PK11SlotInfo *slot = NULL; - CERTCertificate *cert = NULL; - SECStatus rv; - - *privKey = NULL; - certHandle = pk11_AllFindCertObjectByRecipient(slotPtr,array,rip,wincx); - if (certHandle == CK_INVALID_KEY) { - return NULL; - } - - rv = PK11_Authenticate(*slotPtr,PR_TRUE,wincx); - if (rv != SECSuccess) { - PK11_FreeSlot(*slotPtr); - *slotPtr = NULL; - return NULL; - } - - keyHandle = PK11_MatchItem(*slotPtr,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { - PK11_FreeSlot(*slotPtr); - *slotPtr = NULL; - return NULL; - } - - *privKey = PK11_MakePrivKey(*slotPtr, nullKey, PR_TRUE, keyHandle, wincx); - if (*privKey == NULL) { - PK11_FreeSlot(*slotPtr); - *slotPtr = NULL; - return NULL; - } - cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL); - if (cert == NULL) { - PK11_FreeSlot(*slotPtr); - SECKEY_DestroyPrivateKey(*privKey); - *slotPtr = NULL; - *privKey = NULL; - return NULL; - } - return cert; -} - -/* - * This is the new version of the above function for NSS SMIME code - * this stuff should REALLY be in the SMIME code, but some things in here are not public - * (they should be!) - */ -int -PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx) -{ - CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY; - CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY; - SECStatus rv; - NSSCMSRecipient *rl; - int rlIndex; - - certHandle = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex); - if (certHandle == CK_INVALID_KEY) { - return NULL; - } - - rl = recipientlist[rlIndex]; - - /* at this point, rl->slot is set */ - - /* authenticate to the token */ - if (PK11_Authenticate(rl->slot, PR_TRUE, wincx) != SECSuccess) { - PK11_FreeSlot(rl->slot); - rl->slot = NULL; - return -1; - } - - /* try to get a private key handle for the cert we found */ - keyHandle = PK11_MatchItem(rl->slot, certHandle, CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { - PK11_FreeSlot(rl->slot); - rl->slot = NULL; - return -1; - } - - /* make a private key out of the handle */ - rl->privkey = PK11_MakePrivKey(rl->slot, nullKey, PR_TRUE, keyHandle, wincx); - if (rl->privkey == NULL) { - PK11_FreeSlot(rl->slot); - rl->slot = NULL; - return -1; - } - /* make a cert from the cert handle */ - rl->cert = PK11_MakeCertFromHandle(rl->slot, certHandle, NULL); - if (rl->cert == NULL) { - PK11_FreeSlot(rl->slot); - SECKEY_DestroyPrivateKey(rl->privkey); - rl->slot = NULL; - rl->privkey = NULL; - return NULL; - } - return rlIndex; -} - -CERTCertificate * -PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN, - void *wincx) -{ - CK_OBJECT_HANDLE certHandle; - CERTCertificate *cert = NULL; - CK_ATTRIBUTE searchTemplate[] = { - { CKA_ISSUER, NULL, 0 }, - { CKA_SERIAL_NUMBER, NULL, 0} - }; - int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE); - CK_ATTRIBUTE *attrs = searchTemplate; - - PK11_SETATTRS(attrs, CKA_ISSUER, issuerSN->derIssuer.data, - issuerSN->derIssuer.len); attrs++; - PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, issuerSN->serialNumber.data, - issuerSN->serialNumber.len); - - certHandle = pk11_FindCertObjectByTemplate - (slotPtr,searchTemplate,count,wincx); - if (certHandle == CK_INVALID_KEY) { - return NULL; - } - cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL); - if (cert == NULL) { - PK11_FreeSlot(*slotPtr); - return NULL; - } - return cert; -} - -CK_OBJECT_HANDLE -PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot) -{ - CK_OBJECT_HANDLE certHandle; - CK_ATTRIBUTE searchTemplate = { CKA_VALUE, NULL, 0 }; - - PK11_SETATTRS(&searchTemplate, CKA_VALUE, cert->derCert.data, - cert->derCert.len); - - if (cert->slot) { - certHandle = pk11_getcerthandle(cert->slot,cert,&searchTemplate,1); - if (certHandle != CK_INVALID_KEY) { - *pSlot = PK11_ReferenceSlot(cert->slot); - return certHandle; - } - } - - certHandle = pk11_FindCertObjectByTemplate(pSlot,&searchTemplate,1,wincx); - if (certHandle != CK_INVALID_KEY) { - if (cert->slot == NULL) { - cert->slot = PK11_ReferenceSlot(*pSlot); - cert->pkcs11ID = certHandle; - cert->ownSlot = PR_FALSE; - } - } - - return(certHandle); -} - -SECKEYPrivateKey * -PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx) -{ - CK_OBJECT_HANDLE certHandle; - CK_OBJECT_HANDLE keyHandle; - PK11SlotInfo *slot = NULL; - SECKEYPrivateKey *privKey; - SECStatus rv; - - certHandle = PK11_FindObjectForCert(cert, wincx, &slot); - if (certHandle == CK_INVALID_KEY) { - return NULL; - } - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - PK11_FreeSlot(slot); - return NULL; - } - keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY); - if (keyHandle == CK_INVALID_KEY) { - PK11_FreeSlot(slot); - return NULL; - } - privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); - PK11_FreeSlot(slot); - return privKey; -} - -CK_OBJECT_HANDLE -pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx) -{ - CK_OBJECT_HANDLE certHandle; - CK_OBJECT_HANDLE keyHandle; - - certHandle = PK11_FindObjectForCert(cert, wincx, slot); - if (certHandle == CK_INVALID_KEY) { - return CK_INVALID_KEY; - } - keyHandle = PK11_MatchItem(*slot,certHandle,CKO_PUBLIC_KEY); - if (keyHandle == CK_INVALID_KEY) { - PK11_FreeSlot(*slot); - return CK_INVALID_KEY; - } - return keyHandle; -} - -SECKEYPrivateKey * -PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx) -{ - CK_OBJECT_HANDLE keyHandle; - SECKEYPrivateKey *privKey; - - keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID); - if (keyHandle == CK_INVALID_KEY) { - return NULL; - } - privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx); - return privKey; -} - -/* - * find the number of certs in the slot with the same subject name - */ -int -PK11_NumberCertsForCertSubject(CERTCertificate *cert) -{ - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - - if ((cert->slot == NULL) || (cert->slot->isInternal)) { - return 0; - } - - return PK11_NumberObjectsFor(cert->slot,theTemplate,templateSize); -} - -/* - * Walk all the certs with the same subject - */ -SECStatus -PK11_TraverseCertsForSubject(CERTCertificate *cert, - SECStatus(* callback)(CERTCertificate*, void *), void *arg) -{ - if(!cert) { - return SECFailure; - } - - return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg); -} - -SECStatus -PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot, - SECStatus(* callback)(CERTCertificate*, void *), void *arg) -{ - pk11DoCertCallback caller; - pk11TraverseSlotCert callarg; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_SUBJECT, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len); - - if ((slot == NULL) || (slot->isInternal)) { - return SECSuccess; - } - caller.noslotcallback = callback; - caller.callback = NULL; - caller.callbackArg = arg; - callarg.callback = pk11_DoCerts; - callarg.callbackArg = (void *) & caller; - callarg.findTemplate = theTemplate; - callarg.templateCount = templateSize; - - return PK11_TraverseSlot(slot, &callarg); -} - -SECStatus -PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot, - SECStatus(* callback)(CERTCertificate*, void *), void *arg) -{ - pk11DoCertCallback caller; - pk11TraverseSlotCert callarg; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - { CKA_LABEL, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - if(!nickname) { - return SECSuccess; - } - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - PK11_SETATTRS(attr,CKA_LABEL,nickname->data,nickname->len); - - if ((slot == NULL) || (slot->isInternal)) { - return SECSuccess; - } - - caller.noslotcallback = callback; - caller.callback = NULL; - caller.callbackArg = arg; - callarg.callback = pk11_DoCerts; - callarg.callbackArg = (void *) & caller; - callarg.findTemplate = theTemplate; - callarg.templateCount = templateSize; - - return PK11_TraverseSlot(slot, &callarg); -} - -SECStatus -PK11_TraverseCertsInSlot(PK11SlotInfo *slot, - SECStatus(* callback)(CERTCertificate*, void *), void *arg) -{ - pk11DoCertCallback caller; - pk11TraverseSlotCert callarg; - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_CLASS, NULL, 0 }, - }; - CK_ATTRIBUTE *attr = theTemplate; - int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]); - - PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++; - - if (slot == NULL) { - return SECSuccess; - } - - caller.noslotcallback = callback; - caller.callback = NULL; - caller.callbackArg = arg; - callarg.callback = pk11_DoCerts; - callarg.callbackArg = (void *) & caller; - callarg.findTemplate = theTemplate; - callarg.templateCount = templateSize; - - return PK11_TraverseSlot(slot, &callarg); -} - -/* - * return the certificate associated with a derCert - */ -CERTCertificate * -PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert, - void *wincx) -{ - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_VALUE, NULL, 0 }, - { CKA_CLASS, NULL, 0 } - }; - /* if you change the array, change the variable below as well */ - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - CK_OBJECT_HANDLE certh; - CK_ATTRIBUTE *attrs = theTemplate; - SECStatus rv; - - PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, - cert->derCert.len); attrs++; - PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); - - /* - * issue the find - */ - if ( !PK11_IsFriendly(slot)) { - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) return NULL; - } - - certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { - return NULL; - } - return PK11_MakeCertFromHandle(slot, certh, NULL); -} - -/* - * return the certificate associated with a derCert - */ -CERTCertificate * -PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, - CERTCertificate *cert, - char *nickname, void *wincx) -{ - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_SUBJECT, NULL, 0 }, - { CKA_LABEL, NULL, 0 }, - { CKA_CLASS, NULL, 0 } - }; - /* if you change the array, change the variable below as well */ - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - CK_OBJECT_HANDLE certh; - CK_ATTRIBUTE *attrs = theTemplate; - SECStatus rv; - - PK11_SETATTRS(attrs, CKA_SUBJECT, cert->derSubject.data, - cert->derSubject.len); attrs++; - PK11_SETATTRS(attrs, CKA_LABEL, nickname, PORT_Strlen(nickname)); - PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); - - /* - * issue the find - */ - if ( !PK11_IsFriendly(slot)) { - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) return NULL; - } - - certh = pk11_getcerthandle(slot,cert,theTemplate,tsize); - if (certh == CK_INVALID_KEY) { - return NULL; - } - - return PK11_MakeCertFromHandle(slot, certh, NULL); -} - -/* - * import a cert for a private key we have already generated. Set the label - * on both to be the nickname. - */ -static CK_OBJECT_HANDLE -pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, - void *wincx) -{ - SECItem *keyID; - CK_OBJECT_HANDLE key; - SECStatus rv; - - if((slot == NULL) || (cert == NULL)) { - return CK_INVALID_KEY; - } - - keyID = pk11_mkcertKeyID(cert); - if(keyID == NULL) { - return CK_INVALID_KEY; - } - - key = CK_INVALID_KEY; - - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) goto loser; - - key = pk11_FindPrivateKeyFromCertID(slot, keyID); - -loser: - SECITEM_ZfreeItem(keyID, PR_TRUE); - return key; -} - -SECKEYPrivateKey * -PK11_FindKeyByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, - void *wincx) -{ - CK_OBJECT_HANDLE keyHandle; - - if((slot == NULL) || (cert == NULL)) { - return NULL; - } - - keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); - if (keyHandle == CK_INVALID_KEY) { - return NULL; - } - - return PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,wincx); -} - -SECStatus -PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, - char *nickname, - PRBool addCertUsage,void *wincx) -{ - CK_OBJECT_HANDLE keyHandle; - - if((slot == NULL) || (cert == NULL) || (nickname == NULL)) { - return SECFailure; - } - - keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx); - if (keyHandle == CK_INVALID_KEY) { - return SECFailure; - } - - return PK11_ImportCert(slot, cert, keyHandle, nickname, addCertUsage); -} - - -/* remove when the real version comes out */ -#define SEC_OID_MISSI_KEA 300 /* until we have v3 stuff merged */ -PRBool -KEAPQGCompare(CERTCertificate *server,CERTCertificate *cert) { - - if ( SECKEY_KEAParamCompare(server,cert) == SECEqual ) { - return PR_TRUE; - } else { - return PR_FALSE; - } -} - -PRBool -PK11_FortezzaHasKEA(CERTCertificate *cert) { - /* look at the subject and see if it is a KEA for MISSI key */ - SECOidData *oid; - - if ((cert->trust == NULL) || - ((cert->trust->sslFlags & CERTDB_USER) != CERTDB_USER)) { - return PR_FALSE; - } - - oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm); - - - return (PRBool)((oid->offset == SEC_OID_MISSI_KEA_DSS_OLD) || - (oid->offset == SEC_OID_MISSI_KEA_DSS) || - (oid->offset == SEC_OID_MISSI_KEA)) ; -} - -/* - * Find a kea cert on this slot that matches the domain of it's peer - */ -static CERTCertificate -*pk11_GetKEAMate(PK11SlotInfo *slot,CERTCertificate *peer) -{ - int i; - CERTCertificate *returnedCert = NULL; - - for (i=0; i < slot->cert_count; i++) { - CERTCertificate *cert = slot->cert_array[i]; - - if (PK11_FortezzaHasKEA(cert) && KEAPQGCompare(peer,cert)) { - returnedCert = CERT_DupCertificate(cert); - break; - } - } - return returnedCert; -} - -/* - * The following is a FORTEZZA only Certificate request. We call this when we - * are doing a non-client auth SSL connection. We are only interested in the - * fortezza slots, and we are only interested in certs that share the same root - * key as the server. - */ -CERTCertificate * -PK11_FindBestKEAMatch(CERTCertificate *server, void *wincx) -{ - PK11SlotList *keaList = PK11_GetAllTokens(CKM_KEA_KEY_DERIVE, - PR_FALSE,PR_TRUE,wincx); - PK11SlotListElement *le; - CERTCertificate *returnedCert = NULL; - SECStatus rv; - - /* loop through all the fortezza tokens */ - for (le = keaList->head; le; le = le->next) { - rv = PK11_Authenticate(le->slot, PR_TRUE, wincx); - if (rv != SECSuccess) continue; - if (le->slot->session == CK_INVALID_SESSION) { - continue; - } - returnedCert = pk11_GetKEAMate(le->slot,server); - if (returnedCert) break; - } - PK11_FreeSlotList(keaList); - - return returnedCert; -} - -/* - * find a matched pair of kea certs to key exchange parameters from one - * fortezza card to another as necessary. - */ -SECStatus -PK11_GetKEAMatchedCerts(PK11SlotInfo *slot1, PK11SlotInfo *slot2, - CERTCertificate **cert1, CERTCertificate **cert2) -{ - PK11SlotList *keaList = PK11_GetAllTokens(CKM_KEA_KEY_DERIVE, - PR_FALSE,PR_TRUE,NULL); - CERTCertificate *returnedCert = NULL; - int i; - - for (i=0; i < slot1->cert_count; i++) { - CERTCertificate *cert = slot1->cert_array[i]; - - if (PK11_FortezzaHasKEA(cert)) { - returnedCert = pk11_GetKEAMate(slot2,cert); - if (returnedCert != NULL) { - *cert2 = returnedCert; - *cert1 = CERT_DupCertificate(cert); - return SECSuccess; - } - } - } - return SECFailure; -} - -SECOidTag -PK11_FortezzaMapSig(SECOidTag algTag) -{ - switch (algTag) { - case SEC_OID_MISSI_KEA_DSS: - case SEC_OID_MISSI_DSS: - case SEC_OID_MISSI_DSS_OLD: - case SEC_OID_MISSI_KEA_DSS_OLD: - case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST: - return SEC_OID_ANSIX9_DSA_SIGNATURE; - default: - break; - } - return algTag; -} - -/* - * return the private key From a given Cert - */ -CK_OBJECT_HANDLE -PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx) -{ - CK_OBJECT_CLASS certClass = CKO_CERTIFICATE; - CK_ATTRIBUTE theTemplate[] = { - { CKA_VALUE, NULL, 0 }, - { CKA_CLASS, NULL, 0 } - }; - /* if you change the array, change the variable below as well */ - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - CK_ATTRIBUTE *attrs = theTemplate; - SECStatus rv; - - PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, - cert->derCert.len); attrs++; - PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); - - /* - * issue the find - */ - rv = PK11_Authenticate(slot, PR_TRUE, wincx); - if (rv != SECSuccess) { - return CK_INVALID_KEY; - } - - return pk11_getcerthandle(slot,cert,theTemplate,tsize); -} - -SECItem * -PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx) -{ - CK_OBJECT_HANDLE handle; - PK11SlotInfo *slot = NULL; - CK_ATTRIBUTE theTemplate[] = { - { CKA_ID, NULL, 0 }, - }; - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - SECItem *item = NULL; - CK_RV crv; - - handle = PK11_FindObjectForCert(cert,wincx,&slot); - if (handle == CK_INVALID_KEY) { - goto loser; - } - - - crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - goto loser; - } - - item = PORT_ZNew(SECItem); - if (item) { - item->data = theTemplate[0].pValue; - item->len = theTemplate[0].ulValueLen; - } - - -loser: - PK11_FreeSlot(slot); - return item; -} - -SECItem * -PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx) -{ - CK_ATTRIBUTE theTemplate[] = { - { CKA_ID, NULL, 0 }, - }; - int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); - SECItem *item = NULL; - CK_RV crv; - - crv = PK11_GetAttributes(NULL,key->pkcs11Slot,key->pkcs11ID, - theTemplate,tsize); - if (crv != CKR_OK) { - PORT_SetError( PK11_MapError(crv) ); - goto loser; - } - - item = PORT_ZNew(SECItem); - if (item) { - item->data = theTemplate[0].pValue; - item->len = theTemplate[0].ulValueLen; - } - - -loser: - return item; -} |