pk11cert.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:69k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. /*
  34.  * This file implements the Symkey wrapper and the PKCS context
  35.  * Interfaces.
  36.  */
  37. #include "seccomon.h"
  38. #include "secmod.h"
  39. #include "prlock.h"
  40. #include "secmodi.h"
  41. #include "pkcs11.h"
  42. #include "pk11func.h"
  43. #include "cert.h"
  44. #include "secitem.h"
  45. #include "key.h"
  46. #include "hasht.h"
  47. #include "secoid.h"
  48. #include "pkcs7t.h"
  49. #include "cmsreclist.h"
  50. #include "certdb.h"
  51. #include "secerr.h"
  52. #include "sslerr.h"
  53. #define NSSCKT_H /* we included pkcs11t.h, so block ckt.h from including nssckt.h */
  54. #include "ckt.h"
  55. #define PK11_SEARCH_CHUNKSIZE 10
  56. CK_OBJECT_HANDLE
  57. pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx);
  58. /*
  59.  * build a cert nickname based on the token name and the label of the 
  60.  * certificate If the label in NULL, build a label based on the ID.
  61.  */
  62. static int toHex(int x) { return (x < 10) ? (x+'0') : (x+'a'-10); }
  63. #define MAX_CERT_ID 4
  64. #define DEFAULT_STRING "Cert ID "
  65. static char *
  66. pk11_buildNickname(PK11SlotInfo *slot,CK_ATTRIBUTE *cert_label,
  67. CK_ATTRIBUTE *key_label, CK_ATTRIBUTE *cert_id)
  68. {
  69.     int prefixLen = PORT_Strlen(slot->token_name);
  70.     int suffixLen = 0;
  71.     char *suffix = NULL;
  72.     char buildNew[sizeof(DEFAULT_STRING)+MAX_CERT_ID*2];
  73.     char *next,*nickname;
  74.     if (slot->isInternal) {
  75. return NULL;
  76.     }
  77.     if ((cert_label) && (cert_label->pValue)) {
  78. suffixLen = cert_label->ulValueLen;
  79. suffix = (char*)cert_label->pValue;
  80.     } else if (key_label && (key_label->pValue)) {
  81. suffixLen = key_label->ulValueLen;
  82. suffix = (char*)key_label->pValue;
  83.     } else if ((cert_id) && cert_id->pValue) {
  84. int i,first = cert_id->ulValueLen - MAX_CERT_ID;
  85. int offset = sizeof(DEFAULT_STRING);
  86. char *idValue = (char *)cert_id->pValue;
  87. PORT_Memcpy(buildNew,DEFAULT_STRING,sizeof(DEFAULT_STRING)-1);
  88. next = buildNew + offset;
  89. if (first < 0) first = 0;
  90. for (i=first; i < (int) cert_id->ulValueLen; i++) {
  91. *next++ = toHex((idValue[i] >> 4) & 0xf);
  92. *next++ = toHex(idValue[i] & 0xf);
  93. }
  94. *next++ = 0;
  95. suffix = buildNew;
  96. suffixLen = PORT_Strlen(buildNew);
  97.     } else {
  98. PORT_SetError( SEC_ERROR_LIBRARY_FAILURE );
  99. return NULL;
  100.     }
  101.     next = nickname = (char *)PORT_Alloc(prefixLen+1+suffixLen+1);
  102.     if (nickname == NULL) return NULL;
  103.     PORT_Memcpy(next,slot->token_name,prefixLen);
  104.     next += prefixLen;
  105.     *next++ = ':';
  106.     PORT_Memcpy(next,suffix,suffixLen);
  107.     next += suffixLen;
  108.     *next++ = 0;
  109.     return nickname;
  110. }
  111. /*
  112.  * return the object handle that matches the template
  113.  */
  114. CK_OBJECT_HANDLE
  115. pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize)
  116. {
  117.     CK_OBJECT_HANDLE object;
  118.     CK_RV crv;
  119.     CK_ULONG objectCount;
  120.     /*
  121.      * issue the find
  122.      */
  123.     PK11_EnterSlotMonitor(slot);
  124.     crv=PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, theTemplate, tsize);
  125.     if (crv != CKR_OK) {
  126.         PK11_ExitSlotMonitor(slot);
  127. PORT_SetError( PK11_MapError(crv) );
  128. return CK_INVALID_KEY;
  129.     }
  130.     crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount);
  131.     PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
  132.     PK11_ExitSlotMonitor(slot);
  133.     if ((crv != CKR_OK) || (objectCount < 1)) {
  134. /* shouldn't use SSL_ERROR... here */
  135. PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) :
  136.   SSL_ERROR_NO_CERTIFICATE);
  137. return CK_INVALID_KEY;
  138.     }
  139.     /* blow up if the PKCS #11 module returns us and invalid object handle */
  140.     PORT_Assert(object != CK_INVALID_KEY);
  141.     return object;
  142. /*
  143.  * return all the object handles that matches the template
  144.  */
  145. CK_OBJECT_HANDLE *
  146. pk11_FindObjectsByTemplate(PK11SlotInfo *slot,
  147. CK_ATTRIBUTE *findTemplate,int findCount,int *object_count) {
  148.     CK_OBJECT_HANDLE *objID = NULL;
  149.     CK_ULONG returned_count = 0;
  150.     CK_RV crv;
  151.     PK11_EnterSlotMonitor(slot);
  152.     crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, findTemplate, 
  153. findCount);
  154.     if (crv != CKR_OK) {
  155. PK11_ExitSlotMonitor(slot);
  156. PORT_SetError( PK11_MapError(crv) );
  157. *object_count = -1;
  158. return NULL;
  159.     }
  160.     /*
  161.      * collect all the Matching Objects
  162.      */
  163.     do {
  164. CK_OBJECT_HANDLE *oldObjID = objID;
  165. if (objID == NULL) {
  166.          objID = (CK_OBJECT_HANDLE *) PORT_Alloc(sizeof(CK_OBJECT_HANDLE)*
  167. (*object_count+ PK11_SEARCH_CHUNKSIZE));
  168. } else {
  169.          objID = (CK_OBJECT_HANDLE *) PORT_Realloc(objID,
  170. sizeof(CK_OBJECT_HANDLE)*(*object_count+PK11_SEARCH_CHUNKSIZE));
  171. }
  172. if (objID == NULL) {
  173.     if (oldObjID) PORT_Free(oldObjID);
  174.     break;
  175. }
  176.      crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,
  177. &objID[*object_count],PK11_SEARCH_CHUNKSIZE,&returned_count);
  178. if (crv != CKR_OK) {
  179.     PORT_SetError( PK11_MapError(crv) );
  180.     PORT_Free(objID);
  181.     objID = NULL;
  182.     break;
  183.      }
  184. *object_count += returned_count;
  185.     } while (returned_count == PK11_SEARCH_CHUNKSIZE);
  186.     PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
  187.     PK11_ExitSlotMonitor(slot);
  188.     if (objID && (*object_count == 0)) {
  189. PORT_Free(objID);
  190. return NULL;
  191.     }
  192.     if (objID == NULL) *object_count = -1;
  193.     return objID;
  194. }
  195. /*
  196.  * given a PKCS #11 object, match it's peer based on the KeyID. searchID
  197.  * is typically a privateKey or a certificate while the peer is the opposite
  198.  */
  199. CK_OBJECT_HANDLE
  200. PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
  201.   CK_OBJECT_CLASS matchclass)
  202. {
  203.     CK_ATTRIBUTE theTemplate[] = {
  204. { CKA_ID, NULL, 0 },
  205. { CKA_CLASS, NULL, 0 }
  206.     };
  207.     /* if you change the array, change the variable below as well */
  208.     CK_ATTRIBUTE *keyclass = &theTemplate[1];
  209.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  210.     /* if you change the array, change the variable below as well */
  211.     CK_OBJECT_HANDLE peerID;
  212.     CK_OBJECT_HANDLE parent;
  213.     PRArenaPool *arena;
  214.     CK_RV crv;
  215.     /* now we need to create space for the public key */
  216.     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
  217.     if (arena == NULL) return CK_INVALID_KEY;
  218.     crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize);
  219.     if (crv != CKR_OK) {
  220. PORT_FreeArena(arena,PR_FALSE);
  221. PORT_SetError( PK11_MapError(crv) );
  222. return CK_INVALID_KEY;
  223.     }
  224.     /*
  225.      * issue the find
  226.      */
  227.     parent = *(CK_OBJECT_CLASS *)(keyclass->pValue);
  228.     *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass;
  229.     peerID = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
  230.     PORT_FreeArena(arena,PR_FALSE);
  231.     return peerID;
  232. }
  233. PRBool
  234. PK11_IsUserCert(PK11SlotInfo *slot, CERTCertificate *cert,
  235. CK_OBJECT_HANDLE certID)
  236. {
  237.     CK_OBJECT_CLASS theClass;
  238.     if (slot == NULL) return PR_FALSE;
  239.     if (cert == NULL) return PR_FALSE;
  240.     theClass = CKO_PRIVATE_KEY;
  241.     if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) {
  242. theClass = CKO_PUBLIC_KEY;
  243.     }
  244.     if (PK11_MatchItem(slot, certID , theClass) != CK_INVALID_KEY) {
  245. return PR_TRUE;
  246.     }
  247.    if (theClass == CKO_PUBLIC_KEY) {
  248. SECKEYPublicKey *pubKey= CERT_ExtractPublicKey(cert);
  249. CK_ATTRIBUTE theTemplate;
  250. if (pubKey == NULL) {
  251.    return PR_FALSE;
  252. }
  253. PK11_SETATTRS(&theTemplate,0,NULL,0);
  254. switch (pubKey->keyType) {
  255. case rsaKey:
  256.     PK11_SETATTRS(&theTemplate,CKA_MODULUS, pubKey->u.rsa.modulus.data,
  257. pubKey->u.rsa.modulus.len);
  258.     break;
  259. case dsaKey:
  260.     PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dsa.publicValue.data,
  261. pubKey->u.dsa.publicValue.len);
  262. case dhKey:
  263.     PK11_SETATTRS(&theTemplate,CKA_VALUE, pubKey->u.dh.publicValue.data,
  264. pubKey->u.dh.publicValue.len);
  265.     break;
  266. }
  267. if (theTemplate.ulValueLen == 0) {
  268.     SECKEY_DestroyPublicKey(pubKey);
  269.     return PR_FALSE;
  270. }
  271. pk11_SignedToUnsigned(&theTemplate);
  272. if (pk11_FindObjectByTemplate(slot,&theTemplate,1) != CK_INVALID_KEY) {
  273.     SECKEY_DestroyPublicKey(pubKey);
  274.     return PR_TRUE;
  275. }
  276. SECKEY_DestroyPublicKey(pubKey);
  277.     }
  278.     return PR_FALSE;
  279. }
  280. /*
  281.  * Check out if a cert has ID of zero. This is a magic ID that tells
  282.  * NSS that this cert may be an automagically trusted cert.
  283.  * The Cert has to be self signed as well. That check is done elsewhere.
  284.  *  
  285.  */
  286. PRBool
  287. pk11_isID0(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID)
  288. {
  289.     CK_ATTRIBUTE keyID = {CKA_ID, NULL, 0};
  290.     PRBool isZero = PR_FALSE;
  291.     int i;
  292.     CK_RV crv;
  293.     crv = PK11_GetAttributes(NULL,slot,certID,&keyID,1);
  294.     if (crv != CKR_OK) {
  295. return isZero;
  296.     }
  297.     if (keyID.ulValueLen != 0) {
  298. char *value = (char *)keyID.pValue;
  299. isZero = PR_TRUE; /* ID exists, may be zero */
  300. for (i=0; i < (int) keyID.ulValueLen; i++) {
  301.     if (value[i] != 0) {
  302. isZero = PR_FALSE; /* nope */
  303. break;
  304.     }
  305. }
  306.     }
  307.     PORT_Free(keyID.pValue);
  308.     return isZero;
  309. }
  310.      
  311. CERTCertificate
  312. *pk11_fastCert(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, 
  313. CK_ATTRIBUTE *privateLabel, char **nickptr)
  314. {
  315.     CK_ATTRIBUTE certTemp[] = {
  316. { CKA_ID, NULL, 0 },
  317. { CKA_VALUE, NULL, 0 },
  318. { CKA_LABEL, NULL, 0 }
  319.     };
  320.     CK_ATTRIBUTE *id = &certTemp[0];
  321.     CK_ATTRIBUTE *certDER = &certTemp[1];
  322.     CK_ATTRIBUTE *label = &certTemp[2];
  323.     SECItem derCert;
  324.     int csize = sizeof(certTemp)/sizeof(certTemp[0]);
  325.     PRArenaPool *arena;
  326.     char *nickname;
  327.     CERTCertificate *cert;
  328.     CK_RV crv;
  329.     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
  330.     if (arena == NULL) return NULL;
  331.     /*
  332.      * grab the der encoding
  333.      */
  334.     crv = PK11_GetAttributes(arena,slot,certID,certTemp,csize);
  335.     if (crv != CKR_OK) {
  336. PORT_FreeArena(arena,PR_FALSE);
  337. PORT_SetError( PK11_MapError(crv) );
  338. return NULL;
  339.     }
  340.     /*
  341.      * build a certificate out of it
  342.      */
  343.     derCert.data = (unsigned char*)certDER->pValue;
  344.     derCert.len = certDER->ulValueLen;
  345.     /* figure out the nickname.... */
  346.     nickname = pk11_buildNickname(slot,label,privateLabel,id);
  347.     cert = CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &derCert, nickname,
  348. PR_FALSE, PR_TRUE);
  349.     if (nickptr) {
  350. *nickptr = nickname;
  351.     } else {
  352. if (nickname) PORT_Free(nickname);
  353.     }
  354.     PORT_FreeArena(arena,PR_FALSE);
  355.     return cert;
  356. }
  357. CK_TRUST
  358. pk11_GetTrustField(PK11SlotInfo *slot, PRArenaPool *arena, 
  359.                    CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type)
  360. {
  361.   CK_TRUST rv = 0;
  362.   SECItem item;
  363.   item.data = NULL;
  364.   item.len = 0;
  365.   if( SECSuccess == PK11_ReadAttribute(slot, id, type, arena, &item) ) {
  366.     PORT_Assert(item.len == sizeof(CK_TRUST));
  367.     PORT_Memcpy(&rv, item.data, sizeof(CK_TRUST));
  368.     /* Damn, is there an endian problem here? */
  369.     return rv;
  370.   }
  371.   return 0;
  372. }
  373. PRBool
  374. pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
  375. {
  376.   PRArenaPool *arena;
  377.   CK_ATTRIBUTE tobjTemplate[] = {
  378.     { CKA_CLASS, NULL, 0 },
  379.     { CKA_CERT_SHA1_HASH, NULL, 0 },
  380.   };
  381.   CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
  382.   CK_OBJECT_HANDLE tobjID;
  383.   unsigned char sha1_hash[SHA1_LENGTH];
  384.   CK_TRUST digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment,
  385.     keyAgreement, keyCertSign, crlSign, serverAuth, clientAuth, codeSigning,
  386.     emailProtection, ipsecEndSystem, ipsecTunnel, ipsecUser, timeStamping;
  387.   SECItem item;
  388.   PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);
  389.   PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
  390.   PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash, 
  391.                 SHA1_LENGTH);
  392.   tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate, 
  393.                                      sizeof(tobjTemplate)/sizeof(tobjTemplate[0]));
  394.   if( CK_INVALID_KEY == tobjID ) {
  395.     return PR_FALSE;
  396.   }
  397.   arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  398.   if( NULL == arena ) return PR_FALSE;
  399.   /* Unfortunately, it seems that PK11_GetAttributes doesn't deal
  400.    * well with nonexistant attributes.  I guess we have to check 
  401.    * the trust info fields one at a time.
  402.    */
  403.   /* We could verify CKA_CERT_HASH here */
  404.   /* We could verify CKA_EXPIRES here */
  405.   /* "Usage" trust information */
  406.   /* digitalSignature = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DIGITAL_SIGNATURE); */
  407.   /* nonRepudiation   = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_NON_REPUDIATION); */
  408.   /* keyEncipherment  = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_ENCIPHERMENT); */
  409.   /* dataEncipherment = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_DATA_ENCIPHERMENT); */
  410.   /* keyAgreement     = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_AGREEMENT); */
  411.   /* keyCertSign      = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_KEY_CERT_SIGN); */
  412.   /* crlSign          = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CRL_SIGN); */
  413.   /* "Purpose" trust information */
  414.   serverAuth       = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
  415.   /* clientAuth       = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH); */
  416.   codeSigning      = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
  417.   emailProtection  = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_EMAIL_PROTECTION);
  418.   /* ipsecEndSystem   = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_END_SYSTEM); */
  419.   /* ipsecTunnel      = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_TUNNEL); */
  420.   /* ipsecUser        = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_IPSEC_USER); */
  421.   /* timeStamping     = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_TIME_STAMPING); */
  422.   /* Here's where the fun logic happens.  We have to map back from the key usage,
  423.    * extended key usage, purpose, and possibly other trust values into the old
  424.    * trust-flags bits.
  425.    */
  426.   /* First implementation: keep it simple for testing.  We can study what other
  427.    * mappings would be appropriate and add them later.. fgmr 20000724 */
  428.   if( serverAuth & CKT_NETSCAPE_TRUSTED ) {
  429.     trust->sslFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
  430.   }
  431.   if( serverAuth & CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
  432.     trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  433.   }
  434.   if( emailProtection & CKT_NETSCAPE_TRUSTED ) {
  435.     trust->emailFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
  436.   }
  437.   if( emailProtection & CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
  438.     trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  439.   }
  440.   if( codeSigning & CKT_NETSCAPE_TRUSTED ) {
  441.     trust->objectSigningFlags |= CERTDB_VALID_PEER | CERTDB_TRUSTED;
  442.   }
  443.   if( codeSigning & CKT_NETSCAPE_TRUSTED_DELEGATOR ) {
  444.     trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
  445.   }
  446.   /* There's certainly a lot more logic that can go here.. */
  447.   return PR_TRUE;
  448. }
  449. /*
  450.  * Build an CERTCertificate structure from a PKCS#11 object ID.... certID
  451.  * Must be a CertObject. This code does not explicitly checks that.
  452.  */
  453. CERTCertificate *
  454. PK11_MakeCertFromHandle(PK11SlotInfo *slot,CK_OBJECT_HANDLE certID,
  455. CK_ATTRIBUTE *privateLabel)
  456. {
  457.     char * nickname = NULL;
  458.     CERTCertificate *cert = NULL;
  459.     CERTCertTrust *trust;
  460.     PRBool isFortezzaRootCA = PR_FALSE;
  461.     PRBool swapNickname = PR_FALSE;
  462.     cert = pk11_fastCert(slot,certID,privateLabel, &nickname);
  463.     if (cert == NULL) goto loser;
  464.     if (nickname) {
  465. if (cert->nickname != NULL) {
  466. cert->dbnickname = cert->nickname;
  467. cert->nickname = PORT_ArenaStrdup(cert->arena,nickname);
  468. PORT_Free(nickname);
  469. nickname = NULL;
  470. swapNickname = PR_TRUE;
  471.     }
  472.     /* remember where this cert came from.... If we have just looked
  473.      * it up from the database and it already has a slot, don't add a new
  474.      * one. */
  475.     if (cert->slot == NULL) {
  476. cert->slot = PK11_ReferenceSlot(slot);
  477. cert->pkcs11ID = certID;
  478. cert->ownSlot = PR_TRUE;
  479.     }
  480.     if (cert->trust == NULL) {
  481. unsigned int type;
  482. trust = 
  483.   (CERTCertTrust*)PORT_ArenaAlloc(cert->arena, sizeof(CERTCertTrust));
  484. if (trust == NULL) goto loser;
  485. PORT_Memset(trust,0, sizeof(CERTCertTrust));
  486. cert->trust = trust;
  487. /* build some cert trust flags */
  488.     /* First, see if there's a trust object for this cert. */
  489.     /* For the first implementation, we'll just check this slot
  490.      * and worry about overriding trust info later. */
  491.     if( pk11_HandleTrustObject(slot, cert, trust) ) {
  492.       ;
  493.     } else
  494. if (CERT_IsCACert(cert, &type)) {
  495.     unsigned int trustflags = CERTDB_VALID_CA;
  496.    
  497.     /* Allow PKCS #11 modules to give us trusted CA's. We only accept
  498.      * valid CA's which are self-signed here. They must have an object
  499.      * ID of '0'.  */ 
  500.     if (pk11_isID0(slot,certID) && 
  501. SECITEM_CompareItem(&cert->derSubject,&cert->derIssuer)
  502.    == SECEqual) {
  503. trustflags |= CERTDB_TRUSTED_CA;
  504. /* is the slot a fortezza card? allow the user or
  505.  * admin to turn on objectSigning, but don't turn
  506.  * full trust on explicitly */
  507. if (PK11_DoesMechanism(slot,CKM_KEA_KEY_DERIVE)) {
  508.     trust->objectSigningFlags |= CERTDB_VALID_CA;
  509.     isFortezzaRootCA = PR_TRUE;
  510. }
  511.     }
  512.     if ((type & NS_CERT_TYPE_SSL_CA) == NS_CERT_TYPE_SSL_CA) {
  513. trust->sslFlags |= trustflags;
  514.     }
  515.     if ((type & NS_CERT_TYPE_EMAIL_CA) == NS_CERT_TYPE_EMAIL_CA) {
  516. trust->emailFlags |= trustflags;
  517.     }
  518.     if ((type & NS_CERT_TYPE_OBJECT_SIGNING_CA) 
  519. == NS_CERT_TYPE_OBJECT_SIGNING_CA) {
  520. trust->objectSigningFlags |= trustflags;
  521.     }
  522. }
  523.     } else  {
  524. trust = cert->trust;
  525.     }
  526.     if (PK11_IsUserCert(slot,cert,certID)) {
  527. trust->sslFlags |= CERTDB_USER;
  528. trust->emailFlags |= CERTDB_USER;
  529. /*    trust->objectSigningFlags |= CERTDB_USER; */
  530.     }
  531.     /* if fortezza, write the root cert to the DB */
  532.     if ((isFortezzaRootCA) && (!cert->isperm)) {
  533. char *name = NULL;
  534. if (swapNickname) {
  535.     nickname = cert->nickname;
  536.     cert->nickname = cert->dbnickname;
  537. }
  538. if (cert->nickname) {
  539.      name = PORT_Strdup(cert->nickname);
  540. }
  541. if (name == NULL) name = CERT_MakeCANickname(cert);
  542. CERT_AddTempCertToPerm(cert,name,cert->trust);
  543. if (name) PORT_Free(name);
  544. if (swapNickname) {
  545.     if (cert->nickname != NULL) {
  546. cert->dbnickname = cert->nickname;
  547.     }
  548.     cert->nickname = PORT_ArenaStrdup(cert->arena,nickname);
  549. }
  550.     }
  551.     return cert;
  552. loser:
  553.     if (nickname) PORT_Free(nickname);
  554.     if (cert) CERT_DestroyCertificate(cert);
  555.     return NULL;
  556. }
  557. /*
  558.  * Build get a certificate from a private key
  559.  */
  560. CERTCertificate *
  561. PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey)
  562. {
  563.     PK11SlotInfo *slot = privKey->pkcs11Slot;
  564.     CK_OBJECT_HANDLE certID = 
  565. PK11_MatchItem(slot,privKey->pkcs11ID,CKO_CERTIFICATE);
  566.     SECStatus rv;
  567.     CERTCertificate *cert;
  568.     if (certID == CK_INVALID_KEY) {
  569. /* couldn't find it on the card, look in our data base */
  570. SECItem derSubject;
  571. rv = PK11_ReadAttribute(slot, privKey->pkcs11ID, CKA_SUBJECT, NULL,
  572. &derSubject);
  573. if (rv != SECSuccess) {
  574.     PORT_SetError(SSL_ERROR_NO_CERTIFICATE);
  575.     return NULL;
  576. }
  577. cert = CERT_FindCertByName(CERT_GetDefaultCertDB(),&derSubject);
  578. PORT_Free(derSubject.data);
  579. return cert;
  580.     }
  581.     cert = PK11_MakeCertFromHandle(slot,certID,NULL);
  582.     return (cert);
  583. }
  584. /*
  585.  * destroy a private key if there are no matching certs.
  586.  * this function also frees the privKey structure.
  587.  */
  588. SECStatus
  589. PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey)
  590. {
  591.     CERTCertificate *cert=PK11_GetCertFromPrivateKey(privKey);
  592.     /* found a cert matching the private key?. */
  593.     if (cert != NULL) {
  594. /* yes, don't delete the key */
  595.         CERT_DestroyCertificate(cert);
  596. SECKEY_DestroyPrivateKey(privKey);
  597. return SECWouldBlock;
  598.     }
  599.     /* now, then it's safe for the key to go away */
  600.     PK11_DestroyTokenObject(privKey->pkcs11Slot,privKey->pkcs11ID);
  601.     SECKEY_DestroyPrivateKey(privKey);
  602.     return SECSuccess;
  603. }
  604. /*
  605.  * delete a cert and it's private key (if no other certs are pointing to the
  606.  * private key.
  607.  */
  608. SECStatus
  609. PK11_DeleteTokenCertAndKey(CERTCertificate *cert,void *wincx)
  610. {
  611.     SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(cert,wincx);
  612.     CK_OBJECT_HANDLE pubKey;
  613.     PK11SlotInfo *slot = NULL;
  614.     pubKey = pk11_FindPubKeyByAnyCert(cert, &slot, wincx);
  615.     if (privKey) {
  616.      PK11_DestroyTokenObject(cert->slot,cert->pkcs11ID);
  617. PK11_DeleteTokenPrivateKey(privKey);
  618.     }
  619.     if ((pubKey != CK_INVALID_KEY) && (slot != NULL)) { 
  620.      PK11_DestroyTokenObject(slot,pubKey);
  621.         PK11_FreeSlot(slot);
  622.     }
  623.     return SECSuccess;
  624. }
  625. /*
  626.  * count the number of objects that match the template.
  627.  */
  628. int
  629. PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, 
  630. int templateCount)
  631. {
  632.     CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE];
  633.     int object_count = 0;
  634.     CK_ULONG returned_count = 0;
  635.     CK_RV crv;
  636.     PK11_EnterSlotMonitor(slot);
  637.     crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
  638. findTemplate, templateCount);
  639.     if (crv != CKR_OK) {
  640.         PK11_ExitSlotMonitor(slot);
  641. PORT_SetError( PK11_MapError(crv) );
  642. return 0;
  643.     }
  644.     /*
  645.      * collect all the Matching Objects
  646.      */
  647.     do {
  648.      crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,
  649. objID,PK11_SEARCH_CHUNKSIZE,&returned_count);
  650. if (crv != CKR_OK) {
  651.     PORT_SetError( PK11_MapError(crv) );
  652.     break;
  653.      }
  654. object_count += returned_count;
  655.     } while (returned_count == PK11_SEARCH_CHUNKSIZE);
  656.     PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
  657.     PK11_ExitSlotMonitor(slot);
  658.     return object_count;
  659. }
  660. /*
  661.  * cert callback structure
  662.  */
  663. typedef struct pk11DoCertCallbackStr {
  664. SECStatus(* callback)(PK11SlotInfo *slot, CERTCertificate*, void *);
  665. SECStatus(* noslotcallback)(CERTCertificate*, void *);
  666. void *callbackArg;
  667. } pk11DoCertCallback;
  668. /*
  669.  * callback to map object handles to certificate structures.
  670.  */
  671. SECStatus
  672. pk11_DoCerts(PK11SlotInfo *slot, CK_OBJECT_HANDLE certID, void *arg)
  673. {
  674.     CERTCertificate *cert;
  675.     pk11DoCertCallback *certcb = (pk11DoCertCallback *) arg;
  676.     cert = PK11_MakeCertFromHandle(slot, certID, NULL);
  677.     if (cert == NULL) {
  678. return SECFailure;
  679.     }
  680.     if (certcb ) {
  681. if (certcb->callback) {
  682.     (*certcb->callback)(slot, cert, certcb->callbackArg);
  683. }
  684. if (certcb->noslotcallback) {
  685.     (*certcb->noslotcallback)(cert, certcb->callbackArg);
  686. }
  687.     }
  688.     CERT_DestroyCertificate(cert);
  689.     
  690.     return SECSuccess;
  691. }
  692. /*
  693.  * key call back structure.
  694.  */
  695. typedef struct pk11KeyCallbackStr {
  696. SECStatus (* callback)(SECKEYPrivateKey *,void *);
  697. void *callbackArg;
  698. void *wincx;
  699. } pk11KeyCallback;
  700. /*
  701.  * callback to map Object Handles to Private Keys;
  702.  */
  703. SECStatus
  704. pk11_DoKeys(PK11SlotInfo *slot, CK_OBJECT_HANDLE keyHandle, void *arg)
  705. {
  706.     SECStatus rv = SECSuccess;
  707.     SECKEYPrivateKey *privKey;
  708.     pk11KeyCallback *keycb = (pk11KeyCallback *) arg;
  709.     privKey = PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,keycb->wincx);
  710.     if (privKey == NULL) {
  711. return SECFailure;
  712.     }
  713.     if (keycb && (keycb->callback)) {
  714. rv = (*keycb->callback)(privKey,keycb->callbackArg);
  715.     }
  716.     SECKEY_DestroyPrivateKey(privKey);     
  717.     return rv;
  718. }
  719. /* Traverse slots callback */
  720. typedef struct pk11TraverseSlotStr {
  721.     SECStatus (*callback)(PK11SlotInfo *,CK_OBJECT_HANDLE, void *);
  722.     void *callbackArg;
  723.     CK_ATTRIBUTE *findTemplate;
  724.     int templateCount;
  725. } pk11TraverseSlotCert;
  726. /*
  727.  * Extract all the certs on a card from a slot.
  728.  */
  729. SECStatus
  730. PK11_TraverseSlot(PK11SlotInfo *slot, void *arg)
  731. {
  732.     int i;
  733.     CK_OBJECT_HANDLE *objID = NULL;
  734.     int object_count = 0;
  735.     CK_ULONG returned_count = 0;
  736.     pk11TraverseSlotCert *slotcb = (pk11TraverseSlotCert *) arg;
  737.     objID = pk11_FindObjectsByTemplate(slot,slotcb->findTemplate,
  738. slotcb->templateCount,&object_count);
  739.     /*Actually this isn't a failure... there just were no objs to be found*/
  740.     if (object_count == 0) {
  741. return SECSuccess;
  742.     }
  743.     if (objID == NULL) {
  744. return SECFailure;
  745.     }
  746.     for (i=0; i < object_count; i++) {
  747. (*slotcb->callback)(slot,objID[i],slotcb->callbackArg);
  748.     }
  749.     PORT_Free(objID);
  750.     return SECSuccess;
  751. }
  752. typedef struct pk11CertCallbackStr {
  753. SECStatus(* callback)(CERTCertificate*,SECItem *,void *);
  754. void *callbackArg;
  755. } pk11CertCallback;
  756. static SECStatus
  757. pk11_SaveCert(PK11SlotInfo *slot, CERTCertificate *cert, void *arg)
  758. {
  759.     pk11CertCallback *certcb = (pk11CertCallback *)arg;
  760.     SECStatus rv = SECSuccess;
  761.     if (slot->cert_count == slot->array_size) return CKR_OK;
  762.     slot->cert_array[slot->cert_count] = CERT_DupCertificate(cert);
  763.     if (slot->cert_array[slot->cert_count] == NULL) {
  764. return SECFailure;
  765.     }
  766.     /* now the slot has a hold of the cert, free the slot's element in the
  767.      * cert.. */
  768.     if (cert->ownSlot && (slot == cert->slot)) {
  769.         PK11_FreeSlot(cert->slot);
  770. cert->ownSlot = PR_FALSE;
  771.     }
  772.     slot->cert_count++;
  773.     if (certcb->callback) {
  774. rv = (*certcb->callback)(cert, NULL, certcb->callbackArg);
  775.     }
  776.     return rv;
  777. }
  778. /* free the slots */
  779. void
  780. PK11_FreeSlotCerts(PK11SlotInfo *slot)
  781. {
  782.     int i;
  783.     if (slot->cert_array) {
  784. for (i=0; i < slot->cert_count; i++) {
  785.     /* if we point the cert on our array, the cert doesn't have a
  786.      * reference to use (otherwise you would never be able to free
  787.      * a slot :) */
  788.     if ((slot->cert_array[i]->slot == slot) && 
  789. (!slot->cert_array[i]->ownSlot)) {
  790.  slot->cert_array[i]->slot = NULL;
  791.     }
  792.     CERT_DestroyCertificate(slot->cert_array[i]);
  793. }
  794. PORT_Free(slot->cert_array);
  795. slot->cert_array = NULL;
  796. slot->cert_count = 0;
  797.     }
  798.     return;
  799. }
  800. /*
  801.  *  Update PQG parameters for all the certs on a slot.
  802.  */
  803. static SECStatus
  804. pk11_UpdateSlotPQG(PK11SlotInfo *slot)
  805. {
  806.     int i, tag;
  807.     CERTCertificate * cert;
  808.     SECOidData *oid;
  809.     SECStatus rv1 = SECSuccess;
  810.     SECStatus rv2 = SECSuccess;
  811.     if (slot->cert_array) {
  812. for (i=0; i < slot->cert_count; i++) {
  813.             cert = slot->cert_array[i];
  814.             oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm);
  815.             
  816.     if (oid != NULL) {  
  817.         tag = oid->offset;
  818.              
  819.                 /* Check if cert has a DSA or Fortezza public key */
  820.         if ( (tag == SEC_OID_MISSI_KEA_DSS_OLD) ||
  821.              (tag == SEC_OID_MISSI_DSS_OLD) ||
  822.                      (tag == SEC_OID_MISSI_KEA_DSS) ||
  823.                      (tag == SEC_OID_MISSI_DSS) ||               
  824.                      (tag == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
  825.                      (tag == SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST) ||
  826.                      (tag == SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST) ) {
  827.                     /* update PQG parameters */
  828.                     
  829.                     rv1 = SECKEY_UpdateCertPQG(cert);
  830.                     if (rv1 == SECFailure) {
  831.                         rv2 = rv1;
  832.                     }      
  833.         }
  834.     }     /* end of if oid != NULL */ 
  835.         }      /* end of for loop */
  836.     }
  837.     return rv2;
  838. }
  839. /*
  840.  * Extract all the certs on a card from a slot.
  841.  */
  842. static SECStatus
  843. pk11_ExtractCertsFromSlot(PK11SlotInfo *slot, void *arg)
  844. {
  845.     pk11TraverseSlotCert *slotcb = (pk11TraverseSlotCert *) arg;
  846.     int object_count;
  847.     SECStatus rv;
  848.     rv = SECSuccess;
  849.     PK11_FreeSlotCerts(slot);
  850.     object_count = PK11_NumberObjectsFor(slot,slotcb->findTemplate, 
  851. slotcb->templateCount);
  852.     /*Actually this isn't a failure... there just were no certs to be found*/
  853.     if (object_count == 0) {
  854. return SECSuccess;
  855.     }
  856.     slot->cert_array = (CERTCertificate **)
  857. PORT_Alloc(sizeof(CERTCertificate *)*object_count);
  858.     if (slot->cert_array == NULL) {
  859. return SECFailure;
  860.     }
  861.     slot->cert_count = 0;
  862.     slot->array_size = object_count;
  863.     PK11_TraverseSlot(slot,arg);
  864.     /* Update the PQG parameters for the extracted certs. */
  865.     rv = pk11_UpdateSlotPQG(slot);
  866.     return rv;
  867. }
  868. /*
  869.  * read all the certs from a slot
  870.  */
  871. SECStatus
  872. PK11_ReadSlotCerts(PK11SlotInfo *slot)
  873. {
  874.     /* build slot list */
  875.     pk11CertCallback caller;
  876.     pk11DoCertCallback saver;
  877.     pk11TraverseSlotCert creater;
  878.     CK_ATTRIBUTE theTemplate;
  879.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  880.     PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass));
  881.     caller.callback = NULL;
  882.     caller.callbackArg = NULL;
  883.     saver.callback = pk11_SaveCert;
  884.     saver.noslotcallback = NULL;
  885.     saver.callbackArg = (void *) & caller;
  886.     creater.callback = pk11_DoCerts;
  887.     creater.callbackArg = (void *) & saver;
  888.     creater.findTemplate = &theTemplate;
  889.     creater.templateCount = 1;
  890.     return pk11_ExtractCertsFromSlot(slot, &creater);
  891. }
  892. /*
  893.  * Extract all the certs on a card from a slot.
  894.  */
  895. static SECStatus
  896. pk11_TraverseAllSlots(PRBool loadCerts,
  897. SECStatus (*callback)(PK11SlotInfo *,void *),void *arg,void *wincx) {
  898.     PK11SlotList *list;
  899.     PK11SlotListElement *le;
  900.     SECStatus rv;
  901.     /* get them all! */
  902.     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,loadCerts,wincx);
  903.     if (list == NULL) return SECFailure;
  904.     /* look at each slot and authenticate as necessary */
  905.     for (le = list->head ; le; le = le->next) {
  906. /* don't nab internal slots */
  907. if ((!loadCerts) && le->slot->isInternal == PR_TRUE) {
  908.     continue;
  909. }
  910. if (loadCerts || !PK11_IsFriendly(le->slot)) {
  911.              rv = PK11_Authenticate(le->slot, loadCerts, wincx);
  912.              if (rv != SECSuccess) continue;
  913. }
  914. (*callback)(le->slot,arg);
  915.     }
  916.     PK11_FreeSlotList(list);
  917.     return SECSuccess;
  918. }
  919. /*
  920.  * Extract all the certs on a card from a slot.
  921.  */
  922. SECStatus
  923. PK11_TraverseSlotCerts(SECStatus(* callback)(CERTCertificate*,SECItem *,void *),
  924. void *arg, void *wincx) {
  925.     pk11CertCallback caller;
  926.     pk11DoCertCallback saver;
  927.     pk11TraverseSlotCert creater;
  928.     CK_ATTRIBUTE theTemplate;
  929.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  930.     PK11_SETATTRS(&theTemplate, CKA_CLASS, &certClass, sizeof(certClass));
  931.     caller.callback = callback;
  932.     caller.callbackArg = arg;
  933.     saver.callback = pk11_SaveCert;
  934.     saver.noslotcallback = NULL;
  935.     saver.callbackArg = (void *) & caller;
  936.     creater.callback = pk11_DoCerts;
  937.     creater.callbackArg = (void *) & saver;
  938.     creater.findTemplate = &theTemplate;
  939.     creater.templateCount = 1;
  940.     return pk11_TraverseAllSlots(PR_FALSE, pk11_ExtractCertsFromSlot, 
  941. &creater, wincx);
  942. }
  943. CK_OBJECT_HANDLE *
  944. PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr,
  945. CK_OBJECT_CLASS objclass, int *returnCount, void *wincx) {
  946.     char *tokenName;
  947.     char *delimit;
  948.     PK11SlotInfo *slot;
  949.     CK_OBJECT_HANDLE *objID;
  950.     CK_ATTRIBUTE findTemplate[] = {
  951.  { CKA_LABEL, NULL, 0},
  952.  { CKA_CLASS, NULL, 0},
  953.     };
  954.     int findCount = sizeof(findTemplate)/sizeof(findTemplate[0]);
  955.     SECStatus rv;
  956.     PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass));
  957.     *slotptr = slot = NULL;
  958.     *returnCount = 0;
  959.     /* first find the slot associated with this nickname */
  960.     if ((delimit = PORT_Strchr(nickname,':')) != NULL) {
  961. int len = delimit - nickname;
  962. tokenName = (char*)PORT_Alloc(len+1);
  963. PORT_Memcpy(tokenName,nickname,len);
  964. tokenName[len] = 0;
  965.         slot = *slotptr = PK11_FindSlotByName(tokenName);
  966.         PORT_Free(tokenName);
  967. /* if we couldn't find a slot, assume the nickname is an internal cert
  968.  * with no proceding slot name */
  969. if (slot == NULL) {
  970. slot = *slotptr = PK11_GetInternalKeySlot();
  971. } else {
  972. nickname = delimit+1;
  973. }
  974.     } else {
  975. *slotptr = slot = PK11_GetInternalKeySlot();
  976.     }
  977.     if (slot == NULL) {
  978.         return CK_INVALID_KEY;
  979.     }
  980.     if (!PK11_IsFriendly(slot)) {
  981. rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  982. if (rv != SECSuccess) {
  983.     PK11_FreeSlot(slot);
  984.     *slotptr = NULL;
  985.     return CK_INVALID_KEY;
  986.  }
  987.     }
  988.     findTemplate[0].pValue = nickname;
  989.     findTemplate[0].ulValueLen = PORT_Strlen(nickname);
  990.     objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,returnCount);
  991.     if (objID == NULL) {
  992. /* PKCS #11 isn't clear on whether or not the NULL is
  993.  * stored in the template.... try the find again with the
  994.  * full null terminated string. */
  995.      findTemplate[0].ulValueLen += 1;
  996.         objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,
  997. returnCount);
  998. if (objID == NULL) {
  999.     /* Well that's the best we can do. It's just not here */
  1000.     /* what about faked nicknames? */
  1001.     PK11_FreeSlot(slot);
  1002.     *slotptr = NULL;
  1003.     *returnCount = 0;
  1004. }
  1005.     }
  1006.     return objID;
  1007. }
  1008.    
  1009. CERTCertificate *
  1010. PK11_FindCertFromNickname(char *nickname, void *wincx) {
  1011.     PK11SlotInfo *slot;
  1012.     int count=0;
  1013.     CK_OBJECT_HANDLE *certID = PK11_FindObjectsFromNickname(nickname,&slot,
  1014.   CKO_CERTIFICATE, &count, wincx);
  1015.     CERTCertificate *cert;
  1016.     if (certID == CK_INVALID_KEY) return NULL;
  1017.     cert = PK11_MakeCertFromHandle(slot,certID[0],NULL);
  1018.     PK11_FreeSlot(slot);
  1019.     PORT_Free(certID);
  1020.     return cert;
  1021. }
  1022. CERTCertList *
  1023. PK11_FindCertsFromNickname(char *nickname, void *wincx) {
  1024.     PK11SlotInfo *slot;
  1025.     int i,count = 0;
  1026.     CK_OBJECT_HANDLE *certID = PK11_FindObjectsFromNickname(nickname,&slot,
  1027.   CKO_CERTIFICATE, &count, wincx);
  1028.     CERTCertList *certList = NULL;
  1029.     if (certID == NULL) return NULL;
  1030.     certList= CERT_NewCertList();
  1031.     for (i=0; i < count; i++) {
  1032.      CERTCertificate *cert = PK11_MakeCertFromHandle(slot,certID[i],NULL);
  1033. if (cert) CERT_AddCertToListTail(certList,cert);
  1034.     }
  1035.     if (CERT_LIST_HEAD(certList) == NULL) {
  1036. CERT_DestroyCertList(certList);
  1037. certList = NULL;
  1038.     }
  1039.     PK11_FreeSlot(slot);
  1040.     PORT_Free(certID);
  1041.     return certList;
  1042. }
  1043. /*
  1044.  * extract a key ID for a certificate...
  1045.  * NOTE: We call this function from PKCS11.c If we ever use
  1046.  * pkcs11 to extract the public key (we currently do not), this will break.
  1047.  */
  1048. SECItem *
  1049. PK11_GetPubIndexKeyID(CERTCertificate *cert) {
  1050.     SECKEYPublicKey *pubk;
  1051.     SECItem *newItem = NULL;
  1052.     pubk = CERT_ExtractPublicKey(cert);
  1053.     if (pubk == NULL) return NULL;
  1054.     switch (pubk->keyType) {
  1055.     case rsaKey:
  1056. newItem = SECITEM_DupItem(&pubk->u.rsa.modulus);
  1057. break;
  1058.     case dsaKey:
  1059.         newItem = SECITEM_DupItem(&pubk->u.dsa.publicValue);
  1060. break;
  1061.     case dhKey:
  1062.         newItem = SECITEM_DupItem(&pubk->u.dh.publicValue);
  1063.     case fortezzaKey:
  1064.     default:
  1065. newItem = NULL; /* Fortezza Fix later... */
  1066.     }
  1067.     SECKEY_DestroyPublicKey(pubk);
  1068.     /* make hash of it */
  1069.     return newItem;
  1070. }
  1071. /*
  1072.  * generate a CKA_ID from a certificate.
  1073.  */
  1074. SECItem *
  1075. pk11_mkcertKeyID(CERTCertificate *cert) {
  1076.     SECItem *pubKeyData = PK11_GetPubIndexKeyID(cert) ;
  1077.     SECItem *certCKA_ID;
  1078.     if (pubKeyData == NULL) return NULL;
  1079.     
  1080.     certCKA_ID = PK11_MakeIDFromPubKey(pubKeyData);
  1081.     SECITEM_FreeItem(pubKeyData,PR_TRUE);
  1082.     return certCKA_ID;
  1083. }
  1084. /*
  1085.  * Generate a CKA_ID from the relevant public key data. The CKA_ID is generated
  1086.  * from the pubKeyData by SHA1_Hashing it to produce a smaller CKA_ID (to make
  1087.  * smart cards happy.
  1088.  */
  1089. SECItem *
  1090. PK11_MakeIDFromPubKey(SECItem *pubKeyData) {
  1091.     PK11Context *context;
  1092.     SECItem *certCKA_ID;
  1093.     SECStatus rv;
  1094.     context = PK11_CreateDigestContext(SEC_OID_SHA1);
  1095.     if (context == NULL) {
  1096. return NULL;
  1097.     }
  1098.     rv = PK11_DigestBegin(context);
  1099.     if (rv == SECSuccess) {
  1100.      rv = PK11_DigestOp(context,pubKeyData->data,pubKeyData->len);
  1101.     }
  1102.     if (rv != SECSuccess) {
  1103. PK11_DestroyContext(context,PR_TRUE);
  1104. return NULL;
  1105.     }
  1106.     certCKA_ID = (SECItem *)PORT_Alloc(sizeof(SECItem));
  1107.     if (certCKA_ID == NULL) {
  1108. PK11_DestroyContext(context,PR_TRUE);
  1109. return NULL;
  1110.     }
  1111.     certCKA_ID->len = SHA1_LENGTH;
  1112.     certCKA_ID->data = (unsigned char*)PORT_Alloc(certCKA_ID->len);
  1113.     if (certCKA_ID->data == NULL) {
  1114. PORT_Free(certCKA_ID);
  1115. PK11_DestroyContext(context,PR_TRUE);
  1116.         return NULL;
  1117.     }
  1118.     rv = PK11_DigestFinal(context,certCKA_ID->data,&certCKA_ID->len,
  1119. SHA1_LENGTH);
  1120.     PK11_DestroyContext(context,PR_TRUE);
  1121.     if (rv != SECSuccess) {
  1122.      SECITEM_FreeItem(certCKA_ID,PR_TRUE);
  1123. return NULL;
  1124.     }
  1125.     return certCKA_ID;
  1126. }
  1127. /*
  1128.  * Write the cert into the token.
  1129.  */
  1130. SECStatus
  1131. PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert, 
  1132. CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust) {
  1133.     int len = 0;
  1134.     SECItem *keyID = pk11_mkcertKeyID(cert);
  1135.     CK_ATTRIBUTE keyAttrs[] = {
  1136. { CKA_LABEL, NULL, 0},
  1137. { CKA_SUBJECT, NULL, 0},
  1138.     };
  1139.     CK_OBJECT_CLASS certc = CKO_CERTIFICATE;
  1140.     CK_CERTIFICATE_TYPE certType = CKC_X_509;
  1141.     CK_OBJECT_HANDLE certID;
  1142.     CK_SESSION_HANDLE rwsession;
  1143.     CK_BBOOL cktrue = CK_TRUE;
  1144.     SECStatus rv = SECFailure;
  1145.     CK_ATTRIBUTE certAttrs[] = {
  1146. { CKA_ID, NULL, 0 },
  1147. { CKA_LABEL, NULL, 0},
  1148. { CKA_CLASS,  NULL, 0},
  1149. { CKA_TOKEN,  NULL, 0},
  1150. { CKA_CERTIFICATE_TYPE, NULL, 0},
  1151. { CKA_SUBJECT, NULL, 0},
  1152. { CKA_ISSUER, NULL, 0},
  1153. { CKA_SERIAL_NUMBER,  NULL, 0},
  1154. { CKA_VALUE,  NULL, 0},
  1155. { CKA_NETSCAPE_TRUST,  NULL, 0},
  1156.     };
  1157.     int certCount = sizeof(certAttrs)/sizeof(certAttrs[0]), keyCount = 2;
  1158.     CK_ATTRIBUTE *attrs;
  1159.     CK_RV crv;
  1160.     SECCertUsage *certUsage = NULL;
  1161.     if (keyID == NULL) {
  1162. PORT_SetError(SEC_ERROR_ADDING_CERT);
  1163. return rv;
  1164.     }
  1165.     len = ((nickname) ? PORT_Strlen(nickname) : 0);
  1166.     
  1167.     attrs = certAttrs;
  1168.     PK11_SETATTRS(attrs,CKA_ID, keyID->data, keyID->len); attrs++;
  1169.     if(nickname) {
  1170. PK11_SETATTRS(attrs,CKA_LABEL, nickname, len ); attrs++;
  1171.     }
  1172.     PK11_SETATTRS(attrs,CKA_CLASS, &certc, sizeof(certc) ); attrs++;
  1173.     PK11_SETATTRS(attrs,CKA_TOKEN, &cktrue, sizeof(cktrue) ); attrs++;
  1174.     PK11_SETATTRS(attrs,CKA_CERTIFICATE_TYPE, &certType,
  1175. sizeof(certType)); attrs++;
  1176.     PK11_SETATTRS(attrs,CKA_SUBJECT, cert->derSubject.data,
  1177.  cert->derSubject.len ); attrs++;
  1178.     PK11_SETATTRS(attrs,CKA_ISSUER, cert->derIssuer.data,
  1179.  cert->derIssuer.len ); attrs++;
  1180.     PK11_SETATTRS(attrs,CKA_SERIAL_NUMBER, cert->serialNumber.data,
  1181.  cert->serialNumber.len); attrs++;
  1182.     PK11_SETATTRS(attrs,CKA_VALUE, cert->derCert.data, cert->derCert.len);
  1183.     if(includeTrust && PK11_IsInternal(slot)) {
  1184. attrs++;
  1185. certUsage = (SECCertUsage*)PORT_Alloc(sizeof(SECCertUsage));
  1186. if(!certUsage) {
  1187.     SECITEM_FreeItem(keyID,PR_TRUE);
  1188.     PORT_SetError(SEC_ERROR_NO_MEMORY);
  1189.     return rv;
  1190. }
  1191. *certUsage = certUsageUserCertImport;
  1192. PK11_SETATTRS(attrs,CKA_NETSCAPE_TRUST, certUsage, sizeof(SECCertUsage));
  1193.     } else {
  1194. certCount--;
  1195.     }
  1196.     attrs = keyAttrs;
  1197.     if(nickname) {
  1198. PK11_SETATTRS(attrs,CKA_LABEL, nickname, len ); attrs++;
  1199.     }
  1200.     PK11_SETATTRS(attrs,CKA_SUBJECT, cert->derSubject.data,
  1201.  cert->derSubject.len );
  1202.     if(!nickname) {
  1203. certCount--;
  1204. keyCount--;
  1205.     }
  1206.     rwsession = PK11_GetRWSession(slot);
  1207.     crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession,key,keyAttrs,
  1208. keyCount);
  1209.     if (crv != CKR_OK) {
  1210. PORT_SetError( PK11_MapError(crv) );
  1211. goto done;
  1212.     }
  1213.     crv = PK11_GETTAB(slot)->
  1214. C_CreateObject(rwsession,certAttrs,certCount,&certID);
  1215.     if (crv == CKR_OK) {
  1216. rv = SECSuccess;
  1217.     } else {
  1218. PORT_SetError( PK11_MapError(crv) );
  1219.     }
  1220. done:
  1221.     SECITEM_FreeItem(keyID,PR_TRUE);
  1222.     PK11_RestoreROSession(slot,rwsession);
  1223.     if(certUsage) {
  1224. PORT_Free(certUsage);
  1225.     }
  1226.     return rv;
  1227. }
  1228. /*
  1229.  * get a certificate handle, look at the cached handle first..
  1230.  */
  1231. CK_OBJECT_HANDLE
  1232. pk11_getcerthandle(PK11SlotInfo *slot, CERTCertificate *cert, 
  1233. CK_ATTRIBUTE *theTemplate,int tsize)
  1234. {
  1235.     CK_OBJECT_HANDLE certh;
  1236.     if (cert->slot == slot) {
  1237. certh = cert->pkcs11ID;
  1238. if (certh == CK_INVALID_KEY) {
  1239.           certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
  1240.      cert->pkcs11ID = certh;
  1241. }
  1242.     } else {
  1243.      certh = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
  1244.     }
  1245.     return certh;
  1246. }
  1247. /*
  1248.  * return the private key From a given Cert
  1249.  */
  1250. SECKEYPrivateKey *
  1251. PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot, CERTCertificate *cert,
  1252.  void *wincx) {
  1253.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1254.     CK_ATTRIBUTE theTemplate[] = {
  1255. { CKA_VALUE, NULL, 0 },
  1256. { CKA_CLASS, NULL, 0 }
  1257.     };
  1258.     /* if you change the array, change the variable below as well */
  1259.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1260.     CK_OBJECT_HANDLE certh;
  1261.     CK_OBJECT_HANDLE keyh;
  1262.     CK_ATTRIBUTE *attrs = theTemplate;
  1263.     SECStatus rv;
  1264.     PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 
  1265. cert->derCert.len); attrs++;
  1266.     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
  1267.     /*
  1268.      * issue the find
  1269.      */
  1270.     rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  1271.     if (rv != SECSuccess) {
  1272. return NULL;
  1273.     }
  1274.     certh = pk11_getcerthandle(slot,cert,theTemplate,tsize);
  1275.     if (certh == CK_INVALID_KEY) {
  1276. return NULL;
  1277.     }
  1278.     keyh = PK11_MatchItem(slot,certh,CKO_PRIVATE_KEY);
  1279.     if (keyh == CK_INVALID_KEY) { return NULL; }
  1280.     return PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyh, wincx);
  1281. /*
  1282.  * return the private key with the given ID
  1283.  */
  1284. static CK_OBJECT_HANDLE
  1285. pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot, SECItem *keyID)  {
  1286.     CK_OBJECT_CLASS privKey = CKO_PRIVATE_KEY;
  1287.     CK_ATTRIBUTE theTemplate[] = {
  1288. { CKA_ID, NULL, 0 },
  1289. { CKA_CLASS, NULL, 0 },
  1290.     };
  1291.     /* if you change the array, change the variable below as well */
  1292.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1293.     CK_ATTRIBUTE *attrs = theTemplate;
  1294.     PK11_SETATTRS(attrs, CKA_ID, keyID->data, keyID->len ); attrs++;
  1295.     PK11_SETATTRS(attrs, CKA_CLASS, &privKey, sizeof(privKey));
  1296.     return pk11_FindObjectByTemplate(slot,theTemplate,tsize);
  1297. /*
  1298.  * import a cert for a private key we have already generated. Set the label
  1299.  * on both to be the nickname. This is for the Key Gen, orphaned key case.
  1300.  */
  1301. PK11SlotInfo *
  1302. PK11_KeyForCertExists(CERTCertificate *cert, CK_OBJECT_HANDLE *keyPtr, 
  1303. void *wincx) {
  1304.     PK11SlotList *list;
  1305.     PK11SlotListElement *le;
  1306.     SECItem *keyID;
  1307.     CK_OBJECT_HANDLE key;
  1308.     PK11SlotInfo *slot = NULL;
  1309.     SECStatus rv;
  1310.     keyID = pk11_mkcertKeyID(cert);
  1311.     /* get them all! */
  1312.     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
  1313.     if ((keyID == NULL) || (list == NULL)) {
  1314. if (keyID) SECITEM_FreeItem(keyID,PR_TRUE);
  1315. if (list) PK11_FreeSlotList(list);
  1316.      return NULL;
  1317.     }
  1318.     /* Look for the slot that holds the Key */
  1319.     for (le = list->head ; le; le = le->next) {
  1320. rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
  1321. if (rv != SECSuccess) continue;
  1322. key = pk11_FindPrivateKeyFromCertID(le->slot,keyID);
  1323. if (key != CK_INVALID_KEY) {
  1324.     slot = PK11_ReferenceSlot(le->slot);
  1325.     if (keyPtr) *keyPtr = key;
  1326.     break;
  1327. }
  1328.     }
  1329.     SECITEM_FreeItem(keyID,PR_TRUE);
  1330.     PK11_FreeSlotList(list);
  1331.     return slot;
  1332. }
  1333. PK11SlotInfo *
  1334. PK11_ImportCertForKey(CERTCertificate *cert, char *nickname,void *wincx) {
  1335.     PK11SlotInfo *slot = NULL;
  1336.     CK_OBJECT_HANDLE key;
  1337.     slot = PK11_KeyForCertExists(cert,&key,wincx);
  1338.     if (slot) {
  1339. if (PK11_ImportCert(slot,cert,key,nickname,PR_FALSE) != SECSuccess) {
  1340.     PK11_FreeSlot(slot);
  1341.     slot = NULL;
  1342. }
  1343.     } else {
  1344. PORT_SetError(SEC_ERROR_ADDING_CERT);
  1345.     }
  1346.     return slot;
  1347. }
  1348. static CK_OBJECT_HANDLE
  1349. pk11_FindCertObjectByTemplate(PK11SlotInfo **slotPtr, 
  1350. CK_ATTRIBUTE *searchTemplate, int count, void *wincx) {
  1351.     PK11SlotList *list;
  1352.     PK11SlotListElement *le;
  1353.     CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY;
  1354.     PK11SlotInfo *slot = NULL;
  1355.     SECStatus rv;
  1356.     *slotPtr = NULL;
  1357.     /* get them all! */
  1358.     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
  1359.     if (list == NULL) {
  1360. if (list) PK11_FreeSlotList(list);
  1361.      return CK_INVALID_KEY;
  1362.     }
  1363.     /* Look for the slot that holds the Key */
  1364.     for (le = list->head ; le; le = le->next) {
  1365.   if (!PK11_IsFriendly(le->slot)) {
  1366.     rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
  1367.     if (rv != SECSuccess) continue;
  1368. }
  1369. certHandle = pk11_FindObjectByTemplate(le->slot,searchTemplate,count);
  1370. if (certHandle != CK_INVALID_KEY) {
  1371.     slot = PK11_ReferenceSlot(le->slot);
  1372.     break;
  1373. }
  1374.     }
  1375.     PK11_FreeSlotList(list);
  1376.     if (slot == NULL) {
  1377. return CK_INVALID_KEY;
  1378.     }
  1379.     *slotPtr = slot;
  1380.     return certHandle;
  1381. }
  1382. /*
  1383.  * We're looking for a cert which we have the private key for that's on the
  1384.  * list of recipients. This searches one slot.
  1385.  * this is the new version for NSS SMIME code
  1386.  * this stuff should REALLY be in the SMIME code, but some things in here are not public
  1387.  * (they should be!)
  1388.  */
  1389. static CK_OBJECT_HANDLE
  1390. pk11_FindCertObjectByRecipientNew(PK11SlotInfo *slot, NSSCMSRecipient **recipientlist, int *rlIndex)
  1391. {
  1392.     CK_OBJECT_HANDLE certHandle;
  1393.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1394.     CK_OBJECT_CLASS peerClass ;
  1395.     CK_ATTRIBUTE searchTemplate[] = {
  1396. { CKA_CLASS, NULL, 0 },
  1397. { CKA_ISSUER, NULL, 0 },
  1398. { CKA_SERIAL_NUMBER, NULL, 0}
  1399.     };
  1400.     int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE);
  1401.     NSSCMSRecipient *ri = NULL;
  1402.     CK_ATTRIBUTE *attrs;
  1403.     int i;
  1404.     peerClass = CKO_PRIVATE_KEY;
  1405.     if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) {
  1406. peerClass = CKO_PUBLIC_KEY;
  1407.     }
  1408.     for (i=0; (ri = recipientlist[i]) != NULL; i++) {
  1409. /* XXXXX fixme - not yet implemented! */
  1410. if (ri->kind == RLSubjKeyID)
  1411.     continue;
  1412.      attrs = searchTemplate;
  1413. PK11_SETATTRS(attrs, CKA_CLASS, &certClass,sizeof(certClass)); attrs++;
  1414. PK11_SETATTRS(attrs, CKA_ISSUER, ri->id.issuerAndSN->derIssuer.data, 
  1415. ri->id.issuerAndSN->derIssuer.len); attrs++;
  1416. PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, 
  1417.   ri->id.issuerAndSN->serialNumber.data,ri->id.issuerAndSN->serialNumber.len);
  1418. certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count);
  1419. if (certHandle != CK_INVALID_KEY) {
  1420.     CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL);
  1421.     if (PK11_IsUserCert(slot,cert,certHandle)) {
  1422. /* we've found a cert handle, now let's see if there is a key
  1423.          * associated with it... */
  1424. ri->slot = PK11_ReferenceSlot(slot);
  1425. *rlIndex = i;
  1426. CERT_DestroyCertificate(cert);       
  1427. return certHandle;
  1428.     }
  1429.     CERT_DestroyCertificate(cert);       
  1430. }
  1431.     }
  1432.     *rlIndex = -1;
  1433.     return CK_INVALID_KEY;
  1434. }
  1435. /*
  1436.  * This function is the same as above, but it searches all the slots.
  1437.  * this is the new version for NSS SMIME code
  1438.  * this stuff should REALLY be in the SMIME code, but some things in here are not public
  1439.  * (they should be!)
  1440.  */
  1441. static CK_OBJECT_HANDLE
  1442. pk11_AllFindCertObjectByRecipientNew(NSSCMSRecipient **recipientlist, void *wincx, int *rlIndex)
  1443. {
  1444.     PK11SlotList *list;
  1445.     PK11SlotListElement *le;
  1446.     CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY;
  1447.     PK11SlotInfo *slot = NULL;
  1448.     SECStatus rv;
  1449.     /* get them all! */
  1450.     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
  1451.     if (list == NULL) {
  1452. if (list) PK11_FreeSlotList(list);
  1453.      return CK_INVALID_KEY;
  1454.     }
  1455.     /* Look for the slot that holds the Key */
  1456.     for (le = list->head ; le; le = le->next) {
  1457. if ( !PK11_IsFriendly(le->slot)) {
  1458.     rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
  1459.     if (rv != SECSuccess) continue;
  1460. }
  1461. certHandle = pk11_FindCertObjectByRecipientNew(le->slot, recipientlist, rlIndex);
  1462. if (certHandle != CK_INVALID_KEY)
  1463.     break;
  1464.     }
  1465.     PK11_FreeSlotList(list);
  1466.     return (le == NULL) ? CK_INVALID_KEY : certHandle;
  1467. }
  1468. /*
  1469.  * We're looking for a cert which we have the private key for that's on the
  1470.  * list of recipients. This searches one slot.
  1471.  */
  1472. static CK_OBJECT_HANDLE
  1473. pk11_FindCertObjectByRecipient(PK11SlotInfo *slot, 
  1474. SEC_PKCS7RecipientInfo **recipientArray,SEC_PKCS7RecipientInfo **rip)
  1475. {
  1476.     CK_OBJECT_HANDLE certHandle;
  1477.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1478.     CK_OBJECT_CLASS peerClass ;
  1479.     CK_ATTRIBUTE searchTemplate[] = {
  1480. { CKA_CLASS, NULL, 0 },
  1481. { CKA_ISSUER, NULL, 0 },
  1482. { CKA_SERIAL_NUMBER, NULL, 0}
  1483.     };
  1484.     int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE);
  1485.     SEC_PKCS7RecipientInfo *ri = NULL;
  1486.     CK_ATTRIBUTE *attrs;
  1487.     int i;
  1488.     peerClass = CKO_PRIVATE_KEY;
  1489.     if (!PK11_IsLoggedIn(slot,NULL) && PK11_NeedLogin(slot)) {
  1490. peerClass = CKO_PUBLIC_KEY;
  1491.     }
  1492.     for (i=0; (ri = recipientArray[i]) != NULL; i++) {
  1493.      attrs = searchTemplate;
  1494. PK11_SETATTRS(attrs, CKA_CLASS, &certClass,sizeof(certClass)); attrs++;
  1495. PK11_SETATTRS(attrs, CKA_ISSUER, ri->issuerAndSN->derIssuer.data, 
  1496. ri->issuerAndSN->derIssuer.len); attrs++;
  1497. PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, 
  1498.   ri->issuerAndSN->serialNumber.data,ri->issuerAndSN->serialNumber.len);
  1499. certHandle = pk11_FindObjectByTemplate(slot,searchTemplate,count);
  1500. if (certHandle != CK_INVALID_KEY) {
  1501.     CERTCertificate *cert = pk11_fastCert(slot,certHandle,NULL,NULL);
  1502.     if (PK11_IsUserCert(slot,cert,certHandle)) {
  1503. /* we've found a cert handle, now let's see if there is a key
  1504.          * associated with it... */
  1505. *rip = ri;
  1506. CERT_DestroyCertificate(cert);       
  1507. return certHandle;
  1508.     }
  1509.     CERT_DestroyCertificate(cert);       
  1510. }
  1511.     }
  1512.     *rip = NULL;
  1513.     return CK_INVALID_KEY;
  1514. }
  1515. /*
  1516.  * This function is the same as above, but it searches all the slots.
  1517.  */
  1518. static CK_OBJECT_HANDLE
  1519. pk11_AllFindCertObjectByRecipient(PK11SlotInfo **slotPtr, 
  1520. SEC_PKCS7RecipientInfo **recipientArray,SEC_PKCS7RecipientInfo **rip,
  1521. void *wincx) {
  1522.     PK11SlotList *list;
  1523.     PK11SlotListElement *le;
  1524.     CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY;
  1525.     PK11SlotInfo *slot = NULL;
  1526.     SECStatus rv;
  1527.     *slotPtr = NULL;
  1528.     /* get them all! */
  1529.     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_TRUE,wincx);
  1530.     if (list == NULL) {
  1531. if (list) PK11_FreeSlotList(list);
  1532.      return CK_INVALID_KEY;
  1533.     }
  1534.     *rip = NULL;
  1535.     /* Look for the slot that holds the Key */
  1536.     for (le = list->head ; le; le = le->next) {
  1537. if ( !PK11_IsFriendly(le->slot)) {
  1538.     rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
  1539.     if (rv != SECSuccess) continue;
  1540. }
  1541. certHandle = pk11_FindCertObjectByRecipient(le->slot,
  1542. recipientArray,rip);
  1543. if (certHandle != CK_INVALID_KEY) {
  1544.     slot = PK11_ReferenceSlot(le->slot);
  1545.     break;
  1546. }
  1547.     }
  1548.     PK11_FreeSlotList(list);
  1549.     if (slot == NULL) {
  1550. return CK_INVALID_KEY;
  1551.     }
  1552.     *slotPtr = slot;
  1553.     return certHandle;
  1554. }
  1555. /*
  1556.  * We need to invert the search logic for PKCS 7 because if we search for
  1557.  * each cert on the list over all the slots, we wind up with lots of spurious
  1558.  * password prompts. This way we get only one password prompt per slot, at
  1559.  * the max, and most of the time we can find the cert, and only prompt for
  1560.  * the key...
  1561.  */
  1562. CERTCertificate *
  1563. PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slotPtr, 
  1564. SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip,
  1565. SECKEYPrivateKey**privKey, void *wincx)
  1566. {
  1567.     CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY;
  1568.     CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY;
  1569.     PK11SlotInfo *slot = NULL;
  1570.     CERTCertificate *cert = NULL;
  1571.     SECStatus rv;
  1572.     *privKey = NULL;
  1573.     certHandle = pk11_AllFindCertObjectByRecipient(slotPtr,array,rip,wincx);
  1574.     if (certHandle == CK_INVALID_KEY) {
  1575. return NULL;
  1576.     }
  1577.     rv = PK11_Authenticate(*slotPtr,PR_TRUE,wincx);
  1578.     if (rv != SECSuccess) {
  1579. PK11_FreeSlot(*slotPtr);
  1580. *slotPtr = NULL;
  1581. return NULL;
  1582.     }
  1583.     keyHandle = PK11_MatchItem(*slotPtr,certHandle,CKO_PRIVATE_KEY);
  1584.     if (keyHandle == CK_INVALID_KEY) { 
  1585. PK11_FreeSlot(*slotPtr);
  1586. *slotPtr = NULL;
  1587. return NULL;
  1588.     }
  1589.     *privKey =  PK11_MakePrivKey(*slotPtr, nullKey, PR_TRUE, keyHandle, wincx);
  1590.     if (*privKey == NULL) {
  1591. PK11_FreeSlot(*slotPtr);
  1592. *slotPtr = NULL;
  1593. return NULL;
  1594.     }
  1595.     cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL);
  1596.     if (cert == NULL) {
  1597. PK11_FreeSlot(*slotPtr);
  1598. SECKEY_DestroyPrivateKey(*privKey);
  1599. *slotPtr = NULL;
  1600. *privKey = NULL;
  1601. return NULL;
  1602.     }
  1603.     return cert;
  1604. }
  1605. /*
  1606.  * This is the new version of the above function for NSS SMIME code
  1607.  * this stuff should REALLY be in the SMIME code, but some things in here are not public
  1608.  * (they should be!)
  1609.  */
  1610. int
  1611. PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist, void *wincx)
  1612. {
  1613.     CK_OBJECT_HANDLE certHandle = CK_INVALID_KEY;
  1614.     CK_OBJECT_HANDLE keyHandle = CK_INVALID_KEY;
  1615.     SECStatus rv;
  1616.     NSSCMSRecipient *rl;
  1617.     int rlIndex;
  1618.     certHandle = pk11_AllFindCertObjectByRecipientNew(recipientlist, wincx, &rlIndex);
  1619.     if (certHandle == CK_INVALID_KEY) {
  1620. return NULL;
  1621.     }
  1622.     rl = recipientlist[rlIndex];
  1623.     /* at this point, rl->slot is set */
  1624.     /* authenticate to the token */
  1625.     if (PK11_Authenticate(rl->slot, PR_TRUE, wincx) != SECSuccess) {
  1626. PK11_FreeSlot(rl->slot);
  1627. rl->slot = NULL;
  1628. return -1;
  1629.     }
  1630.     /* try to get a private key handle for the cert we found */
  1631.     keyHandle = PK11_MatchItem(rl->slot, certHandle, CKO_PRIVATE_KEY);
  1632.     if (keyHandle == CK_INVALID_KEY) { 
  1633. PK11_FreeSlot(rl->slot);
  1634. rl->slot = NULL;
  1635. return -1;
  1636.     }
  1637.     /* make a private key out of the handle */
  1638.     rl->privkey = PK11_MakePrivKey(rl->slot, nullKey, PR_TRUE, keyHandle, wincx);
  1639.     if (rl->privkey == NULL) {
  1640. PK11_FreeSlot(rl->slot);
  1641. rl->slot = NULL;
  1642. return -1;
  1643.     }
  1644.     /* make a cert from the cert handle */
  1645.     rl->cert = PK11_MakeCertFromHandle(rl->slot, certHandle, NULL);
  1646.     if (rl->cert == NULL) {
  1647. PK11_FreeSlot(rl->slot);
  1648. SECKEY_DestroyPrivateKey(rl->privkey);
  1649. rl->slot = NULL;
  1650. rl->privkey = NULL;
  1651. return NULL;
  1652.     }
  1653.     return rlIndex;
  1654. }
  1655. CERTCertificate *
  1656. PK11_FindCertByIssuerAndSN(PK11SlotInfo **slotPtr, CERTIssuerAndSN *issuerSN,
  1657.  void *wincx)
  1658. {
  1659.     CK_OBJECT_HANDLE certHandle;
  1660.     CERTCertificate *cert = NULL;
  1661.     CK_ATTRIBUTE searchTemplate[] = {
  1662. { CKA_ISSUER, NULL, 0 },
  1663. { CKA_SERIAL_NUMBER, NULL, 0}
  1664.     };
  1665.     int count = sizeof(searchTemplate)/sizeof(CK_ATTRIBUTE);
  1666.     CK_ATTRIBUTE *attrs = searchTemplate;
  1667.     PK11_SETATTRS(attrs, CKA_ISSUER, issuerSN->derIssuer.data, 
  1668. issuerSN->derIssuer.len); attrs++;
  1669.     PK11_SETATTRS(attrs, CKA_SERIAL_NUMBER, issuerSN->serialNumber.data, 
  1670. issuerSN->serialNumber.len);
  1671.     certHandle = pk11_FindCertObjectByTemplate
  1672. (slotPtr,searchTemplate,count,wincx);
  1673.     if (certHandle == CK_INVALID_KEY) {
  1674. return NULL;
  1675.     }
  1676.     cert = PK11_MakeCertFromHandle(*slotPtr,certHandle,NULL);
  1677.     if (cert == NULL) {
  1678. PK11_FreeSlot(*slotPtr);
  1679. return NULL;
  1680.     }
  1681.     return cert;
  1682. }
  1683. CK_OBJECT_HANDLE
  1684. PK11_FindObjectForCert(CERTCertificate *cert, void *wincx, PK11SlotInfo **pSlot)
  1685. {
  1686.     CK_OBJECT_HANDLE certHandle;
  1687.     CK_ATTRIBUTE searchTemplate = { CKA_VALUE, NULL, 0 };
  1688.     
  1689.     PK11_SETATTRS(&searchTemplate, CKA_VALUE, cert->derCert.data,
  1690.   cert->derCert.len);
  1691.     if (cert->slot) {
  1692. certHandle = pk11_getcerthandle(cert->slot,cert,&searchTemplate,1);
  1693. if (certHandle != CK_INVALID_KEY) {
  1694.     *pSlot = PK11_ReferenceSlot(cert->slot);
  1695.     return certHandle;
  1696. }
  1697.     }
  1698.     certHandle = pk11_FindCertObjectByTemplate(pSlot,&searchTemplate,1,wincx);
  1699.     if (certHandle != CK_INVALID_KEY) {
  1700. if (cert->slot == NULL) {
  1701.     cert->slot = PK11_ReferenceSlot(*pSlot);
  1702.     cert->pkcs11ID = certHandle;
  1703.     cert->ownSlot = PR_FALSE;
  1704. }
  1705.     }
  1706.     return(certHandle);
  1707. }
  1708. SECKEYPrivateKey *
  1709. PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx)
  1710. {
  1711.     CK_OBJECT_HANDLE certHandle;
  1712.     CK_OBJECT_HANDLE keyHandle;
  1713.     PK11SlotInfo *slot = NULL;
  1714.     SECKEYPrivateKey *privKey;
  1715.     SECStatus rv;
  1716.     certHandle = PK11_FindObjectForCert(cert, wincx, &slot);
  1717.     if (certHandle == CK_INVALID_KEY) {
  1718.  return NULL;
  1719.     }
  1720.     rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  1721.     if (rv != SECSuccess) {
  1722. PK11_FreeSlot(slot);
  1723. return NULL;
  1724.     }
  1725.     keyHandle = PK11_MatchItem(slot,certHandle,CKO_PRIVATE_KEY);
  1726.     if (keyHandle == CK_INVALID_KEY) { 
  1727. PK11_FreeSlot(slot);
  1728. return NULL;
  1729.     }
  1730.     privKey =  PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
  1731.     PK11_FreeSlot(slot);
  1732.     return privKey;
  1733. }
  1734. CK_OBJECT_HANDLE
  1735. pk11_FindPubKeyByAnyCert(CERTCertificate *cert, PK11SlotInfo **slot, void *wincx)
  1736. {
  1737.     CK_OBJECT_HANDLE certHandle;
  1738.     CK_OBJECT_HANDLE keyHandle;
  1739.     certHandle = PK11_FindObjectForCert(cert, wincx, slot);
  1740.     if (certHandle == CK_INVALID_KEY) {
  1741.  return CK_INVALID_KEY;
  1742.     }
  1743.     keyHandle = PK11_MatchItem(*slot,certHandle,CKO_PUBLIC_KEY);
  1744.     if (keyHandle == CK_INVALID_KEY) { 
  1745. PK11_FreeSlot(*slot);
  1746. return CK_INVALID_KEY;
  1747.     }
  1748.     return keyHandle;
  1749. }
  1750. SECKEYPrivateKey *
  1751. PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID, void *wincx)
  1752. {
  1753.     CK_OBJECT_HANDLE keyHandle;
  1754.     SECKEYPrivateKey *privKey;
  1755.     keyHandle = pk11_FindPrivateKeyFromCertID(slot, keyID);
  1756.     if (keyHandle == CK_INVALID_KEY) { 
  1757. return NULL;
  1758.     }
  1759.     privKey =  PK11_MakePrivKey(slot, nullKey, PR_TRUE, keyHandle, wincx);
  1760.     return privKey;
  1761. }
  1762. /*
  1763.  * find the number of certs in the slot with the same subject name
  1764.  */
  1765. int
  1766. PK11_NumberCertsForCertSubject(CERTCertificate *cert)
  1767. {
  1768.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1769.     CK_ATTRIBUTE theTemplate[] = {
  1770. { CKA_CLASS, NULL, 0 },
  1771. { CKA_SUBJECT, NULL, 0 },
  1772.     };
  1773.     CK_ATTRIBUTE *attr = theTemplate;
  1774.    int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1775.     PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
  1776.     PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len);
  1777.     if ((cert->slot == NULL) || (cert->slot->isInternal)) {
  1778. return 0;
  1779.     }
  1780.     return PK11_NumberObjectsFor(cert->slot,theTemplate,templateSize);
  1781. }
  1782. /*
  1783.  *  Walk all the certs with the same subject
  1784.  */
  1785. SECStatus
  1786. PK11_TraverseCertsForSubject(CERTCertificate *cert,
  1787.         SECStatus(* callback)(CERTCertificate*, void *), void *arg)
  1788. {
  1789.     if(!cert) {
  1790. return SECFailure;
  1791.     }
  1792.     return PK11_TraverseCertsForSubjectInSlot(cert, cert->slot, callback, arg);
  1793. }
  1794. SECStatus
  1795. PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert, PK11SlotInfo *slot,
  1796. SECStatus(* callback)(CERTCertificate*, void *), void *arg)
  1797. {
  1798.     pk11DoCertCallback caller;
  1799.     pk11TraverseSlotCert callarg;
  1800.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1801.     CK_ATTRIBUTE theTemplate[] = {
  1802. { CKA_CLASS, NULL, 0 },
  1803. { CKA_SUBJECT, NULL, 0 },
  1804.     };
  1805.     CK_ATTRIBUTE *attr = theTemplate;
  1806.    int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1807.     PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
  1808.     PK11_SETATTRS(attr,CKA_SUBJECT,cert->derSubject.data,cert->derSubject.len);
  1809.     if ((slot == NULL) || (slot->isInternal)) {
  1810. return SECSuccess;
  1811.     }
  1812.     caller.noslotcallback = callback;
  1813.     caller.callback = NULL;
  1814.     caller.callbackArg = arg;
  1815.     callarg.callback = pk11_DoCerts;
  1816.     callarg.callbackArg = (void *) & caller;
  1817.     callarg.findTemplate = theTemplate;
  1818.     callarg.templateCount = templateSize;
  1819.     
  1820.     return PK11_TraverseSlot(slot, &callarg);
  1821. }
  1822. SECStatus
  1823. PK11_TraverseCertsForNicknameInSlot(SECItem *nickname, PK11SlotInfo *slot,
  1824. SECStatus(* callback)(CERTCertificate*, void *), void *arg)
  1825. {
  1826.     pk11DoCertCallback caller;
  1827.     pk11TraverseSlotCert callarg;
  1828.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1829.     CK_ATTRIBUTE theTemplate[] = {
  1830. { CKA_CLASS, NULL, 0 },
  1831. { CKA_LABEL, NULL, 0 },
  1832.     };
  1833.     CK_ATTRIBUTE *attr = theTemplate;
  1834.     int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1835.     if(!nickname) {
  1836. return SECSuccess;
  1837.     }
  1838.     PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
  1839.     PK11_SETATTRS(attr,CKA_LABEL,nickname->data,nickname->len);
  1840.     if ((slot == NULL) || (slot->isInternal)) {
  1841. return SECSuccess;
  1842.     }
  1843.     caller.noslotcallback = callback;
  1844.     caller.callback = NULL;
  1845.     caller.callbackArg = arg;
  1846.     callarg.callback = pk11_DoCerts;
  1847.     callarg.callbackArg = (void *) & caller;
  1848.     callarg.findTemplate = theTemplate;
  1849.     callarg.templateCount = templateSize;
  1850.     return PK11_TraverseSlot(slot, &callarg);
  1851. }
  1852. SECStatus
  1853. PK11_TraverseCertsInSlot(PK11SlotInfo *slot,
  1854. SECStatus(* callback)(CERTCertificate*, void *), void *arg)
  1855. {
  1856.     pk11DoCertCallback caller;
  1857.     pk11TraverseSlotCert callarg;
  1858.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1859.     CK_ATTRIBUTE theTemplate[] = {
  1860. { CKA_CLASS, NULL, 0 },
  1861.     };
  1862.     CK_ATTRIBUTE *attr = theTemplate;
  1863.     int templateSize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1864.     PK11_SETATTRS(attr,CKA_CLASS, &certClass, sizeof(certClass)); attr++;
  1865.     if (slot == NULL) {
  1866. return SECSuccess;
  1867.     }
  1868.     caller.noslotcallback = callback;
  1869.     caller.callback = NULL;
  1870.     caller.callbackArg = arg;
  1871.     callarg.callback = pk11_DoCerts;
  1872.     callarg.callbackArg = (void *) & caller;
  1873.     callarg.findTemplate = theTemplate;
  1874.     callarg.templateCount = templateSize;
  1875.     return PK11_TraverseSlot(slot, &callarg);
  1876. }
  1877. /*
  1878.  * return the certificate associated with a derCert 
  1879.  */
  1880. CERTCertificate *
  1881. PK11_FindCertFromDERCert(PK11SlotInfo *slot, CERTCertificate *cert,
  1882.  void *wincx)
  1883. {
  1884.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1885.     CK_ATTRIBUTE theTemplate[] = {
  1886. { CKA_VALUE, NULL, 0 },
  1887. { CKA_CLASS, NULL, 0 }
  1888.     };
  1889.     /* if you change the array, change the variable below as well */
  1890.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1891.     CK_OBJECT_HANDLE certh;
  1892.     CK_ATTRIBUTE *attrs = theTemplate;
  1893.     SECStatus rv;
  1894.     PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data, 
  1895. cert->derCert.len); attrs++;
  1896.     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
  1897.     /*
  1898.      * issue the find
  1899.      */
  1900.     if ( !PK11_IsFriendly(slot)) {
  1901. rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  1902. if (rv != SECSuccess) return NULL;
  1903.     }
  1904.     certh = pk11_getcerthandle(slot,cert,theTemplate,tsize);
  1905.     if (certh == CK_INVALID_KEY) {
  1906. return NULL;
  1907.     }
  1908.     return PK11_MakeCertFromHandle(slot, certh, NULL);
  1909. /*
  1910.  * return the certificate associated with a derCert 
  1911.  */
  1912. CERTCertificate *
  1913. PK11_FindCertFromDERSubjectAndNickname(PK11SlotInfo *slot, 
  1914. CERTCertificate *cert, 
  1915. char *nickname, void *wincx)
  1916. {
  1917.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  1918.     CK_ATTRIBUTE theTemplate[] = {
  1919. { CKA_SUBJECT, NULL, 0 },
  1920. { CKA_LABEL, NULL, 0 },
  1921. { CKA_CLASS, NULL, 0 }
  1922.     };
  1923.     /* if you change the array, change the variable below as well */
  1924.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1925.     CK_OBJECT_HANDLE certh;
  1926.     CK_ATTRIBUTE *attrs = theTemplate;
  1927.     SECStatus rv;
  1928.     PK11_SETATTRS(attrs, CKA_SUBJECT, cert->derSubject.data, 
  1929. cert->derSubject.len); attrs++;
  1930.     PK11_SETATTRS(attrs, CKA_LABEL, nickname, PORT_Strlen(nickname));
  1931.     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
  1932.     /*
  1933.      * issue the find
  1934.      */
  1935.     if ( !PK11_IsFriendly(slot)) {
  1936. rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  1937. if (rv != SECSuccess) return NULL;
  1938.     }
  1939.     certh = pk11_getcerthandle(slot,cert,theTemplate,tsize);
  1940.     if (certh == CK_INVALID_KEY) {
  1941. return NULL;
  1942.     }
  1943.     return PK11_MakeCertFromHandle(slot, certh, NULL);
  1944. }
  1945. /*
  1946.  * import a cert for a private key we have already generated. Set the label
  1947.  * on both to be the nickname.
  1948.  */
  1949. static CK_OBJECT_HANDLE 
  1950. pk11_findKeyObjectByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 
  1951. void *wincx)
  1952. {
  1953.     SECItem *keyID;
  1954.     CK_OBJECT_HANDLE key;
  1955.     SECStatus rv;
  1956.     if((slot == NULL) || (cert == NULL)) {
  1957. return CK_INVALID_KEY;
  1958.     }
  1959.     keyID = pk11_mkcertKeyID(cert);
  1960.     if(keyID == NULL) {
  1961. return CK_INVALID_KEY;
  1962.     }
  1963.     key = CK_INVALID_KEY;
  1964.     rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  1965.     if (rv != SECSuccess) goto loser;
  1966.     key = pk11_FindPrivateKeyFromCertID(slot, keyID);
  1967. loser:
  1968.     SECITEM_ZfreeItem(keyID, PR_TRUE);
  1969.     return key;
  1970. }
  1971. SECKEYPrivateKey *
  1972. PK11_FindKeyByDERCert(PK11SlotInfo *slot, CERTCertificate *cert, 
  1973. void *wincx)
  1974. {
  1975.     CK_OBJECT_HANDLE keyHandle;
  1976.     if((slot == NULL) || (cert == NULL)) {
  1977. return NULL;
  1978.     }
  1979.     keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx);
  1980.     if (keyHandle == CK_INVALID_KEY) {
  1981. return NULL;
  1982.     }
  1983.     return PK11_MakePrivKey(slot,nullKey,PR_TRUE,keyHandle,wincx);
  1984. }
  1985. SECStatus
  1986. PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert, 
  1987. char *nickname, 
  1988. PRBool addCertUsage,void *wincx)
  1989. {
  1990.     CK_OBJECT_HANDLE keyHandle;
  1991.     if((slot == NULL) || (cert == NULL) || (nickname == NULL)) {
  1992. return SECFailure;
  1993.     }
  1994.     keyHandle = pk11_findKeyObjectByDERCert(slot, cert, wincx);
  1995.     if (keyHandle == CK_INVALID_KEY) {
  1996. return SECFailure;
  1997.     }
  1998.     return PK11_ImportCert(slot, cert, keyHandle, nickname, addCertUsage);
  1999. }   
  2000. /* remove when the real version comes out */
  2001. #define SEC_OID_MISSI_KEA 300  /* until we have v3 stuff merged */
  2002. PRBool
  2003. KEAPQGCompare(CERTCertificate *server,CERTCertificate *cert) {
  2004.     if ( SECKEY_KEAParamCompare(server,cert) == SECEqual ) {
  2005.         return PR_TRUE;
  2006.     } else {
  2007. return PR_FALSE;
  2008.     }
  2009. }
  2010. PRBool
  2011. PK11_FortezzaHasKEA(CERTCertificate *cert) {
  2012.    /* look at the subject and see if it is a KEA for MISSI key */
  2013.    SECOidData *oid;
  2014.    if ((cert->trust == NULL) ||
  2015.        ((cert->trust->sslFlags & CERTDB_USER) != CERTDB_USER)) {
  2016.        return PR_FALSE;
  2017.    }
  2018.    oid = SECOID_FindOID(&cert->subjectPublicKeyInfo.algorithm.algorithm);
  2019.    return (PRBool)((oid->offset == SEC_OID_MISSI_KEA_DSS_OLD) || 
  2020. (oid->offset == SEC_OID_MISSI_KEA_DSS) ||
  2021. (oid->offset == SEC_OID_MISSI_KEA)) ;
  2022. }
  2023. /*
  2024.  * Find a kea cert on this slot that matches the domain of it's peer
  2025.  */
  2026. static CERTCertificate
  2027. *pk11_GetKEAMate(PK11SlotInfo *slot,CERTCertificate *peer)
  2028. {
  2029.     int i;
  2030.     CERTCertificate *returnedCert = NULL;
  2031.     for (i=0; i < slot->cert_count; i++) {
  2032. CERTCertificate *cert = slot->cert_array[i];
  2033. if (PK11_FortezzaHasKEA(cert) && KEAPQGCompare(peer,cert)) {
  2034. returnedCert = CERT_DupCertificate(cert);
  2035. break;
  2036. }
  2037.     }
  2038.     return returnedCert;
  2039. }
  2040. /*
  2041.  * The following is a FORTEZZA only Certificate request. We call this when we
  2042.  * are doing a non-client auth SSL connection. We are only interested in the
  2043.  * fortezza slots, and we are only interested in certs that share the same root
  2044.  * key as the server.
  2045.  */
  2046. CERTCertificate *
  2047. PK11_FindBestKEAMatch(CERTCertificate *server, void *wincx)
  2048. {
  2049.     PK11SlotList *keaList = PK11_GetAllTokens(CKM_KEA_KEY_DERIVE,
  2050. PR_FALSE,PR_TRUE,wincx);
  2051.     PK11SlotListElement *le;
  2052.     CERTCertificate *returnedCert = NULL;
  2053.     SECStatus rv;
  2054.     /* loop through all the fortezza tokens */
  2055.     for (le = keaList->head; le; le = le->next) {
  2056.         rv = PK11_Authenticate(le->slot, PR_TRUE, wincx);
  2057.         if (rv != SECSuccess) continue;
  2058. if (le->slot->session == CK_INVALID_SESSION) {
  2059.     continue;
  2060. }
  2061. returnedCert = pk11_GetKEAMate(le->slot,server);
  2062. if (returnedCert) break;
  2063.     }
  2064.     PK11_FreeSlotList(keaList);
  2065.     return returnedCert;
  2066. }
  2067. /*
  2068.  * find a matched pair of kea certs to key exchange parameters from one 
  2069.  * fortezza card to another as necessary.
  2070.  */
  2071. SECStatus
  2072. PK11_GetKEAMatchedCerts(PK11SlotInfo *slot1, PK11SlotInfo *slot2,
  2073. CERTCertificate **cert1, CERTCertificate **cert2)
  2074. {
  2075.     PK11SlotList *keaList = PK11_GetAllTokens(CKM_KEA_KEY_DERIVE,
  2076. PR_FALSE,PR_TRUE,NULL);
  2077.     CERTCertificate *returnedCert = NULL;
  2078.     int i;
  2079.     for (i=0; i < slot1->cert_count; i++) {
  2080. CERTCertificate *cert = slot1->cert_array[i];
  2081. if (PK11_FortezzaHasKEA(cert)) {
  2082.     returnedCert = pk11_GetKEAMate(slot2,cert);
  2083.     if (returnedCert != NULL) {
  2084. *cert2 = returnedCert;
  2085. *cert1 = CERT_DupCertificate(cert);
  2086. return SECSuccess;
  2087.     }
  2088. }
  2089.     }
  2090.     return SECFailure;
  2091. }
  2092. SECOidTag 
  2093. PK11_FortezzaMapSig(SECOidTag algTag)
  2094. {
  2095.     switch (algTag) {
  2096.     case SEC_OID_MISSI_KEA_DSS:
  2097.     case SEC_OID_MISSI_DSS:
  2098.     case SEC_OID_MISSI_DSS_OLD:
  2099.     case SEC_OID_MISSI_KEA_DSS_OLD:
  2100.     case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
  2101. return SEC_OID_ANSIX9_DSA_SIGNATURE;
  2102.     default:
  2103. break;
  2104.     }
  2105.     return algTag;
  2106. }
  2107. /*
  2108.  * return the private key From a given Cert
  2109.  */
  2110. CK_OBJECT_HANDLE
  2111. PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert, void *wincx)
  2112. {
  2113.     CK_OBJECT_CLASS certClass = CKO_CERTIFICATE;
  2114.     CK_ATTRIBUTE theTemplate[] = {
  2115. { CKA_VALUE, NULL, 0 },
  2116. { CKA_CLASS, NULL, 0 }
  2117.     };
  2118.     /* if you change the array, change the variable below as well */
  2119.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  2120.     CK_ATTRIBUTE *attrs = theTemplate;
  2121.     SECStatus rv;
  2122.     PK11_SETATTRS(attrs, CKA_VALUE, cert->derCert.data,
  2123. cert->derCert.len); attrs++;
  2124.     PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
  2125.     /*
  2126.      * issue the find
  2127.      */
  2128.     rv = PK11_Authenticate(slot, PR_TRUE, wincx);
  2129.     if (rv != SECSuccess) {
  2130. return CK_INVALID_KEY;
  2131.     }
  2132.     return pk11_getcerthandle(slot,cert,theTemplate,tsize);
  2133. }
  2134. SECItem *
  2135. PK11_GetKeyIDFromCert(CERTCertificate *cert, void *wincx)
  2136. {
  2137.     CK_OBJECT_HANDLE handle;
  2138.     PK11SlotInfo *slot = NULL;
  2139.     CK_ATTRIBUTE theTemplate[] = {
  2140. { CKA_ID, NULL, 0 },
  2141.     };
  2142.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  2143.     SECItem *item = NULL;
  2144.     CK_RV crv;
  2145.     handle = PK11_FindObjectForCert(cert,wincx,&slot);
  2146.     if (handle == CK_INVALID_KEY) {
  2147. goto loser;
  2148.     }
  2149.     crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize);
  2150.     if (crv != CKR_OK) {
  2151. PORT_SetError( PK11_MapError(crv) );
  2152. goto loser;
  2153.     }
  2154.     item = PORT_ZNew(SECItem);
  2155.     if (item) {
  2156.         item->data = theTemplate[0].pValue;
  2157.         item->len = theTemplate[0].ulValueLen;
  2158.     }
  2159. loser:
  2160.     PK11_FreeSlot(slot);
  2161.     return item;
  2162. }
  2163. SECItem *
  2164. PK11_GetKeyIDFromPrivateKey(SECKEYPrivateKey *key, void *wincx)
  2165. {
  2166.     CK_ATTRIBUTE theTemplate[] = {
  2167. { CKA_ID, NULL, 0 },
  2168.     };
  2169.     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  2170.     SECItem *item = NULL;
  2171.     CK_RV crv;
  2172.     crv = PK11_GetAttributes(NULL,key->pkcs11Slot,key->pkcs11ID,
  2173. theTemplate,tsize);
  2174.     if (crv != CKR_OK) {
  2175. PORT_SetError( PK11_MapError(crv) );
  2176. goto loser;
  2177.     }
  2178.     item = PORT_ZNew(SECItem);
  2179.     if (item) {
  2180.         item->data = theTemplate[0].pValue;
  2181.         item->len = theTemplate[0].ulValueLen;
  2182.     }
  2183. loser:
  2184.     return item;
  2185. }