security/nss/lib/pk11wrap/pk11obj.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     4 /*
     5  * This file manages object type indepentent functions.
     6  */
     7 #include "seccomon.h"
     8 #include "secmod.h"
     9 #include "secmodi.h"
    10 #include "secmodti.h"
    11 #include "pkcs11.h"
    12 #include "pkcs11t.h"
    13 #include "pk11func.h"
    14 #include "key.h" 
    15 #include "secitem.h"
    16 #include "secerr.h"
    17 #include "sslerr.h"
    19 #define PK11_SEARCH_CHUNKSIZE 10
    21 /*
    22  * Build a block big enough to hold the data
    23  */
    24 SECItem *
    25 PK11_BlockData(SECItem *data,unsigned long size) {
    26     SECItem *newData;
    28     newData = (SECItem *)PORT_Alloc(sizeof(SECItem));
    29     if (newData == NULL) return NULL;
    31     newData->len = (data->len + (size-1))/size;
    32     newData->len *= size;
    34     newData->data = (unsigned char *) PORT_ZAlloc(newData->len); 
    35     if (newData->data == NULL) {
    36 	PORT_Free(newData);
    37 	return NULL;
    38     }
    39     PORT_Memset(newData->data,newData->len-data->len,newData->len); 
    40     PORT_Memcpy(newData->data,data->data,data->len);
    41     return newData;
    42 }
    45 SECStatus
    46 PK11_DestroyObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) {
    47     CK_RV crv;
    49     PK11_EnterSlotMonitor(slot);
    50     crv = PK11_GETTAB(slot)->C_DestroyObject(slot->session,object);
    51     PK11_ExitSlotMonitor(slot);
    52     if (crv != CKR_OK) {
    53 	return SECFailure;
    54     }
    55     return SECSuccess;
    56 }
    58 SECStatus
    59 PK11_DestroyTokenObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) {
    60     CK_RV crv;
    61     SECStatus rv = SECSuccess;
    62     CK_SESSION_HANDLE rwsession;
    65     rwsession = PK11_GetRWSession(slot);
    66     if (rwsession == CK_INVALID_SESSION) {
    67     	PORT_SetError(SEC_ERROR_BAD_DATA);
    68     	return SECFailure;
    69     }
    71     crv = PK11_GETTAB(slot)->C_DestroyObject(rwsession,object);
    72     if (crv != CKR_OK) {
    73 	rv = SECFailure;
    74 	PORT_SetError(PK11_MapError(crv));
    75     }
    76     PK11_RestoreROSession(slot,rwsession);
    77     return rv;
    78 }
    80 /*
    81  * Read in a single attribute into a SECItem. Allocate space for it with 
    82  * PORT_Alloc unless an arena is supplied. In the latter case use the arena
    83  * to allocate the space.
    84  *
    85  * PK11_ReadAttribute sets the 'data' and 'len' fields of the SECItem but
    86  * does not modify its 'type' field.
    87  */
    88 SECStatus
    89 PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
    90 	 CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result) {
    91     CK_ATTRIBUTE attr = { 0, NULL, 0 };
    92     CK_RV crv;
    94     attr.type = type;
    96     PK11_EnterSlotMonitor(slot);
    97     crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1);
    98     if (crv != CKR_OK) {
    99 	PK11_ExitSlotMonitor(slot);
   100 	PORT_SetError(PK11_MapError(crv));
   101 	return SECFailure;
   102     }
   103     if (arena) {
   104     	attr.pValue = PORT_ArenaAlloc(arena,attr.ulValueLen);
   105     } else {
   106     	attr.pValue = PORT_Alloc(attr.ulValueLen);
   107     }
   108     if (attr.pValue == NULL) {
   109 	PK11_ExitSlotMonitor(slot);
   110 	return SECFailure;
   111     }
   112     crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1);
   113     PK11_ExitSlotMonitor(slot);
   114     if (crv != CKR_OK) {
   115 	PORT_SetError(PK11_MapError(crv));
   116 	if (!arena) PORT_Free(attr.pValue);
   117 	return SECFailure;
   118     }
   120     result->data = (unsigned char*)attr.pValue;
   121     result->len = attr.ulValueLen;
   123     return SECSuccess;
   124 }
   126 /*
   127  * Read in a single attribute into As a Ulong. 
   128  */
   129 CK_ULONG
   130 PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
   131 	 CK_ATTRIBUTE_TYPE type) {
   132     CK_ATTRIBUTE attr;
   133     CK_ULONG value = CK_UNAVAILABLE_INFORMATION;
   134     CK_RV crv;
   136     PK11_SETATTRS(&attr,type,&value,sizeof(value));
   138     PK11_EnterSlotMonitor(slot);
   139     crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1);
   140     PK11_ExitSlotMonitor(slot);
   141     if (crv != CKR_OK) {
   142 	PORT_SetError(PK11_MapError(crv));
   143     }
   144     return value;
   145 }
   147 /*
   148  * check to see if a bool has been set.
   149  */
   150 CK_BBOOL
   151 PK11_HasAttributeSet( PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
   152 				 CK_ATTRIBUTE_TYPE type, PRBool haslock )
   153 {
   154     CK_BBOOL ckvalue = CK_FALSE;
   155     CK_ATTRIBUTE theTemplate;
   156     CK_RV crv;
   158     /* Prepare to retrieve the attribute. */
   159     PK11_SETATTRS( &theTemplate, type, &ckvalue, sizeof( CK_BBOOL ) );
   161     /* Retrieve attribute value. */
   162     if (!haslock) PK11_EnterSlotMonitor(slot);
   163     crv = PK11_GETTAB( slot )->C_GetAttributeValue( slot->session, id,
   164                                                     &theTemplate, 1 );
   165     if (!haslock) PK11_ExitSlotMonitor(slot);
   166     if( crv != CKR_OK ) {
   167         PORT_SetError( PK11_MapError( crv ) );
   168         return CK_FALSE;
   169     }
   171     return ckvalue;
   172 }
   174 /*
   175  * returns a full list of attributes. Allocate space for them. If an arena is
   176  * provided, allocate space out of the arena.
   177  */
   178 CK_RV
   179 PK11_GetAttributes(PLArenaPool *arena,PK11SlotInfo *slot,
   180 			CK_OBJECT_HANDLE obj,CK_ATTRIBUTE *attr, int count)
   181 {
   182     int i;
   183     /* make pedantic happy... note that it's only used arena != NULL */ 
   184     void *mark = NULL; 
   185     CK_RV crv;
   186     PORT_Assert(slot->session != CK_INVALID_SESSION);
   187     if (slot->session == CK_INVALID_SESSION)
   188 	return CKR_SESSION_HANDLE_INVALID;
   190     /*
   191      * first get all the lengths of the parameters.
   192      */
   193     PK11_EnterSlotMonitor(slot);
   194     crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,obj,attr,count);
   195     if (crv != CKR_OK) {
   196 	PK11_ExitSlotMonitor(slot);
   197 	return crv;
   198     }
   200     if (arena) {
   201     	mark = PORT_ArenaMark(arena);
   202 	if (mark == NULL) return CKR_HOST_MEMORY;
   203     }
   205     /*
   206      * now allocate space to store the results.
   207      */
   208     for (i=0; i < count; i++) {
   209 	if (attr[i].ulValueLen == 0)
   210 	    continue;
   211 	if (arena) {
   212 	    attr[i].pValue = PORT_ArenaAlloc(arena,attr[i].ulValueLen);
   213 	    if (attr[i].pValue == NULL) {
   214 		/* arena failures, just release the mark */
   215 		PORT_ArenaRelease(arena,mark);
   216 		PK11_ExitSlotMonitor(slot);
   217 		return CKR_HOST_MEMORY;
   218 	    }
   219 	} else {
   220 	    attr[i].pValue = PORT_Alloc(attr[i].ulValueLen);
   221 	    if (attr[i].pValue == NULL) {
   222 		/* Separate malloc failures, loop to release what we have 
   223 		 * so far */
   224 		int j;
   225 		for (j= 0; j < i; j++) { 
   226 		    PORT_Free(attr[j].pValue);
   227 		    /* don't give the caller pointers to freed memory */
   228 		    attr[j].pValue = NULL; 
   229 		}
   230 		PK11_ExitSlotMonitor(slot);
   231 		return CKR_HOST_MEMORY;
   232 	    }
   233 	}
   234     }
   236     /*
   237      * finally get the results.
   238      */
   239     crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,obj,attr,count);
   240     PK11_ExitSlotMonitor(slot);
   241     if (crv != CKR_OK) {
   242 	if (arena) {
   243 	    PORT_ArenaRelease(arena,mark);
   244 	} else {
   245 	    for (i= 0; i < count; i++) {
   246 		PORT_Free(attr[i].pValue);
   247 		/* don't give the caller pointers to freed memory */
   248 		attr[i].pValue = NULL;
   249 	    }
   250 	}
   251     } else if (arena && mark) {
   252 	PORT_ArenaUnmark(arena,mark);
   253     }
   254     return crv;
   255 }
   257 PRBool
   258 PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle)
   259 {
   260     return (PRBool) PK11_HasAttributeSet(slot, handle, CKA_TOKEN, PR_FALSE);
   261 }
   263 char *
   264 PK11_GetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id) 
   265 {
   266     char *nickname = NULL;
   267     SECItem result;
   268     SECStatus rv;
   270     rv = PK11_ReadAttribute(slot,id,CKA_LABEL,NULL,&result);
   271     if (rv != SECSuccess) {
   272 	return NULL;
   273     }
   275     nickname = PORT_ZAlloc(result.len+1);
   276     if (nickname == NULL) {
   277 	PORT_Free(result.data);
   278 	return NULL;
   279     }
   280     PORT_Memcpy(nickname, result.data, result.len);
   281     PORT_Free(result.data);
   282     return nickname;
   283 }
   285 SECStatus
   286 PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, 
   287 						const char *nickname) 
   288 {
   289     int len = PORT_Strlen(nickname);
   290     CK_ATTRIBUTE setTemplate;
   291     CK_RV crv;
   292     CK_SESSION_HANDLE rwsession;
   294     if (len < 0) {
   295 	return SECFailure;
   296     }
   298     PK11_SETATTRS(&setTemplate, CKA_LABEL, (CK_CHAR *) nickname, len);
   299     rwsession = PK11_GetRWSession(slot);
   300     if (rwsession == CK_INVALID_SESSION) {
   301     	PORT_SetError(SEC_ERROR_BAD_DATA);
   302     	return SECFailure;
   303     }
   304     crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, id,
   305 			&setTemplate, 1);
   306     PK11_RestoreROSession(slot, rwsession);
   307     if (crv != CKR_OK) {
   308 	PORT_SetError(PK11_MapError(crv));
   309 	return SECFailure;
   310     }
   311     return SECSuccess;
   312 }
   314 /*
   315  * strip leading zero's from key material
   316  */
   317 void
   318 pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib) {
   319     char *ptr = (char *)attrib->pValue;
   320     unsigned long len = attrib->ulValueLen;
   322     while ((len > 1) && (*ptr == 0)) {
   323 	len--;
   324 	ptr++;
   325     }
   326     attrib->pValue = ptr;
   327     attrib->ulValueLen = len;
   328 }
   330 /*
   331  * get a new session on a slot. If we run out of session, use the slot's
   332  * 'exclusive' session. In this case owner becomes false.
   333  */
   334 CK_SESSION_HANDLE
   335 pk11_GetNewSession(PK11SlotInfo *slot,PRBool *owner)
   336 {
   337     CK_SESSION_HANDLE session;
   338     *owner =  PR_TRUE;
   339     if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
   340     if ( PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION, 
   341 			slot,pk11_notify,&session) != CKR_OK) {
   342 	*owner = PR_FALSE;
   343 	session = slot->session;
   344     }
   345     if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
   347     return session;
   348 }
   350 void
   351 pk11_CloseSession(PK11SlotInfo *slot,CK_SESSION_HANDLE session,PRBool owner)
   352 {
   353     if (!owner) return;
   354     if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot);
   355     (void) PK11_GETTAB(slot)->C_CloseSession(session);
   356     if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot);
   357 }
   360 SECStatus
   361 PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
   362 				const CK_ATTRIBUTE *theTemplate, int count, 
   363 				PRBool token, CK_OBJECT_HANDLE *objectID)
   364 {
   365 	CK_SESSION_HANDLE rwsession;
   366 	CK_RV crv;
   367 	SECStatus rv = SECSuccess;
   369 	rwsession = session;
   370 	if (token) {
   371 	    rwsession =  PK11_GetRWSession(slot);
   372 	} else if (rwsession == CK_INVALID_SESSION) {
   373 	    rwsession =  slot->session;
   374 	    if (rwsession != CK_INVALID_SESSION)
   375 		PK11_EnterSlotMonitor(slot);
   376 	}
   377 	if (rwsession == CK_INVALID_SESSION) {
   378 	    PORT_SetError(SEC_ERROR_BAD_DATA);
   379 	    return SECFailure;
   380 	}
   381 	crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, 
   382 	      /* cast away const :-( */         (CK_ATTRIBUTE_PTR)theTemplate,
   383 						count, objectID);
   384 	if(crv != CKR_OK) {
   385 	    PORT_SetError( PK11_MapError(crv) );
   386 	    rv = SECFailure;
   387 	}
   388 	if (token) {
   389 	    PK11_RestoreROSession(slot, rwsession);
   390 	} else if (session == CK_INVALID_SESSION) {
   391 	    PK11_ExitSlotMonitor(slot);
   392         }
   394 	return rv;
   395 }
   398 /* This function may add a maximum of 9 attributes. */
   399 unsigned int
   400 pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue)
   401 {
   403     const static CK_ATTRIBUTE_TYPE attrTypes[12] = {
   404 	CKA_ENCRYPT,      CKA_DECRYPT, 0 /* DIGEST */,     CKA_SIGN,
   405 	CKA_SIGN_RECOVER, CKA_VERIFY,  CKA_VERIFY_RECOVER, 0 /* GEN */,
   406 	0 /* GEN PAIR */, CKA_WRAP,    CKA_UNWRAP,         CKA_DERIVE 
   407     };
   409     const CK_ATTRIBUTE_TYPE *pType	= attrTypes;
   410           CK_ATTRIBUTE      *attr	= attrs;
   411           CK_FLAGS          test	= CKF_ENCRYPT;
   414     PR_ASSERT(!(flags & ~CKF_KEY_OPERATION_FLAGS));
   415     flags &= CKF_KEY_OPERATION_FLAGS;
   417     for (; flags && test <= CKF_DERIVE; test <<= 1, ++pType) {
   418     	if (test & flags) {
   419 	    flags ^= test;
   420 	    PR_ASSERT(*pType);
   421 	    PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue); 
   422 	    ++attr;
   423 	}
   424     }
   425     return (attr - attrs);
   426 }
   428 /*
   429  * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE
   430  * and PK11_ATTR_PUBLIC are set.
   431  */
   432 PRBool
   433 pk11_BadAttrFlags(PK11AttrFlags attrFlags)
   434 {
   435     PK11AttrFlags trueFlags = attrFlags & 0x55555555;
   436     PK11AttrFlags falseFlags = (attrFlags >> 1) & 0x55555555;
   437     return ((trueFlags & falseFlags) != 0);
   438 }
   440 /*
   441  * This function may add a maximum of 5 attributes.
   442  * The caller must make sure the attribute flags don't have conflicts.
   443  */
   444 unsigned int
   445 pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs,
   446 				CK_BBOOL *ckTrue, CK_BBOOL *ckFalse)
   447 {
   448     const static CK_ATTRIBUTE_TYPE attrTypes[5] = {
   449 	CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_SENSITIVE,
   450 	CKA_EXTRACTABLE
   451     };
   453     const CK_ATTRIBUTE_TYPE *pType	= attrTypes;
   454           CK_ATTRIBUTE      *attr	= attrs;
   455           PK11AttrFlags      test	= PK11_ATTR_TOKEN;
   457     PR_ASSERT(!pk11_BadAttrFlags(attrFlags));
   459     /* we test two related bitflags in each iteration */
   460     for (; attrFlags && test <= PK11_ATTR_EXTRACTABLE; test <<= 2, ++pType) {
   461     	if (test & attrFlags) {
   462 	    attrFlags ^= test;
   463 	    PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue); 
   464 	    ++attr;
   465 	} else if ((test << 1) & attrFlags) {
   466 	    attrFlags ^= (test << 1);
   467 	    PK11_SETATTRS(attr, *pType, ckFalse, sizeof *ckFalse); 
   468 	    ++attr;
   469 	}
   470     }
   471     return (attr - attrs);
   472 }
   474 /*
   475  * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually
   476  * set up a signature to get the signaure length.
   477  */
   478 static int
   479 pk11_backupGetSignLength(SECKEYPrivateKey *key)
   480 {
   481     PK11SlotInfo *slot = key->pkcs11Slot;
   482     CK_MECHANISM mech = {0, NULL, 0 };
   483     PRBool owner = PR_TRUE;
   484     CK_SESSION_HANDLE session;
   485     CK_ULONG len;
   486     CK_RV crv;
   487     unsigned char h_data[20]  = { 0 };
   488     unsigned char buf[20]; /* obviously to small */
   489     CK_ULONG smallLen = sizeof(buf);
   491     mech.mechanism = PK11_MapSignKeyType(key->keyType);
   493     session = pk11_GetNewSession(slot,&owner);
   494     if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
   495     crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID);
   496     if (crv != CKR_OK) {
   497 	if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
   498 	pk11_CloseSession(slot,session,owner);
   499 	PORT_SetError( PK11_MapError(crv) );
   500 	return -1;
   501     }
   502     len = 0;
   503     crv = PK11_GETTAB(slot)->C_Sign(session,h_data,sizeof(h_data),
   504 					NULL, &len);
   505     /* now call C_Sign with too small a buffer to clear the session state */
   506     (void) PK11_GETTAB(slot)->
   507 			C_Sign(session,h_data,sizeof(h_data),buf,&smallLen);
   509     if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
   510     pk11_CloseSession(slot,session,owner);
   511     if (crv != CKR_OK) {
   512 	PORT_SetError( PK11_MapError(crv) );
   513 	return -1;
   514     }
   515     return len;
   516 }
   518 /*
   519  * get the length of a signature object based on the key
   520  */
   521 int
   522 PK11_SignatureLen(SECKEYPrivateKey *key)
   523 {
   524     int val;
   525     SECItem attributeItem = {siBuffer, NULL, 0};
   526     SECStatus rv;
   527     int length; 
   529     switch (key->keyType) {
   530     case rsaKey:
   531 	val = PK11_GetPrivateModulusLen(key);
   532 	if (val == -1) {
   533 	    return pk11_backupGetSignLength(key);
   534 	}
   535 	return (unsigned long) val;
   537     case fortezzaKey:
   538 	return 40;
   540     case dsaKey:
   541         rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_SUBPRIME, 
   542 				NULL, &attributeItem);
   543         if (rv == SECSuccess) {
   544 	    length = attributeItem.len;
   545 	    if ((length > 0) && attributeItem.data[0] == 0) {
   546 		length--;
   547 	    }
   548 	    PORT_Free(attributeItem.data);
   549 	    return length*2;
   550 	}
   551 	return pk11_backupGetSignLength(key);
   553     case ecKey:
   554         rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_EC_PARAMS, 
   555 				NULL, &attributeItem);
   556 	if (rv == SECSuccess) {
   557 	    length = SECKEY_ECParamsToBasePointOrderLen(&attributeItem);
   558 	    PORT_Free(attributeItem.data);
   559 	    if (length != 0) {
   560 		length = ((length + 7)/8) * 2;
   561 		return length;
   562 	    }
   563 	}
   564 	return pk11_backupGetSignLength(key);
   565     default:
   566 	break;
   567     }
   568     PORT_SetError( SEC_ERROR_INVALID_KEY );
   569     return 0;
   570 }
   572 /*
   573  * copy a key (or any other object) on a token
   574  */
   575 CK_OBJECT_HANDLE
   576 PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject)
   577 {
   578     CK_OBJECT_HANDLE destObject;
   579     CK_RV crv;
   581     PK11_EnterSlotMonitor(slot);
   582     crv = PK11_GETTAB(slot)->C_CopyObject(slot->session,srcObject,NULL,0,
   583 				&destObject);
   584     PK11_ExitSlotMonitor(slot);
   585     if (crv == CKR_OK) return destObject;
   586     PORT_SetError( PK11_MapError(crv) );
   587     return CK_INVALID_HANDLE;
   588 }
   590 PRBool
   591 pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs,
   592 						CK_ATTRIBUTE_TYPE target)
   593 {
   594     for (; numAttrs > 0; ++attr, --numAttrs) {
   595     	if (attr->type == target)
   596 	    return PR_TRUE;
   597     }
   598     return PR_FALSE;
   599 }
   601 /*
   602  * Recover the Signed data. We need this because our old verify can't
   603  * figure out which hash algorithm to use until we decryptted this.
   604  */
   605 SECStatus
   606 PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig,
   607 		   SECItem *dsig, void *wincx)
   608 {
   609     PK11SlotInfo *slot = key->pkcs11Slot;
   610     CK_OBJECT_HANDLE id = key->pkcs11ID;
   611     CK_MECHANISM mech = {0, NULL, 0 };
   612     PRBool owner = PR_TRUE;
   613     CK_SESSION_HANDLE session;
   614     CK_ULONG len;
   615     CK_RV crv;
   617     mech.mechanism = PK11_MapSignKeyType(key->keyType);
   619     if (slot == NULL) {
   620 	slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
   621 				CKF_VERIFY_RECOVER,0,wincx);
   622 	if (slot == NULL) {
   623 	    	PORT_SetError( SEC_ERROR_NO_MODULE );
   624 		return SECFailure;
   625 	}
   626 	id = PK11_ImportPublicKey(slot,key,PR_FALSE);
   627     } else {
   628 	PK11_ReferenceSlot(slot);
   629     }
   631     if (id == CK_INVALID_HANDLE) {
   632 	PK11_FreeSlot(slot);
   633 	PORT_SetError( SEC_ERROR_BAD_KEY );
   634 	return SECFailure;
   635     }
   637     session = pk11_GetNewSession(slot,&owner);
   638     if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
   639     crv = PK11_GETTAB(slot)->C_VerifyRecoverInit(session,&mech,id);
   640     if (crv != CKR_OK) {
   641 	if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
   642 	pk11_CloseSession(slot,session,owner);
   643 	PORT_SetError( PK11_MapError(crv) );
   644 	PK11_FreeSlot(slot);
   645 	return SECFailure;
   646     }
   647     len = dsig->len;
   648     crv = PK11_GETTAB(slot)->C_VerifyRecover(session,sig->data,
   649 						sig->len, dsig->data, &len);
   650     if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
   651     pk11_CloseSession(slot,session,owner);
   652     dsig->len = len;
   653     if (crv != CKR_OK) {
   654 	PORT_SetError( PK11_MapError(crv) );
   655 	PK11_FreeSlot(slot);
   656 	return SECFailure;
   657     }
   658     PK11_FreeSlot(slot);
   659     return SECSuccess;
   660 }
   662 /*
   663  * verify a signature from its hash.
   664  */
   665 SECStatus
   666 PK11_Verify(SECKEYPublicKey *key, const SECItem *sig, const SECItem *hash,
   667 	    void *wincx)
   668 {
   669     PK11SlotInfo *slot = key->pkcs11Slot;
   670     CK_OBJECT_HANDLE id = key->pkcs11ID;
   671     CK_MECHANISM mech = {0, NULL, 0 };
   672     PRBool owner = PR_TRUE;
   673     CK_SESSION_HANDLE session;
   674     CK_RV crv;
   676     mech.mechanism = PK11_MapSignKeyType(key->keyType);
   678     if (slot == NULL) {
   679 	unsigned int length =  0;
   680 	if ((mech.mechanism == CKM_DSA) && 
   681 				/* 129 is 1024 bits translated to bytes and
   682 				 * padded with an optional '0' to maintain a
   683 				 * positive sign */
   684 				(key->u.dsa.params.prime.len > 129)) {
   685 	    /* we need to get a slot that not only can do DSA, but can do DSA2
   686 	     * key lengths */
   687 	    length = key->u.dsa.params.prime.len;
   688 	    if (key->u.dsa.params.prime.data[0] == 0) {
   689 		length --;
   690 	    }
   691 	    /* convert keysize to bits for slot lookup */
   692 	    length *= 8;
   693 	}
   694 	slot = PK11_GetBestSlotWithAttributes(mech.mechanism,
   695 						CKF_VERIFY,length,wincx);
   696 	if (slot == NULL) {
   697 	    PORT_SetError( SEC_ERROR_NO_MODULE );
   698 	    return SECFailure;
   699 	}
   700 	id = PK11_ImportPublicKey(slot,key,PR_FALSE);
   702     } else {
   703 	PK11_ReferenceSlot(slot);
   704     }
   706     if (id == CK_INVALID_HANDLE) {
   707 	PK11_FreeSlot(slot);
   708 	PORT_SetError( SEC_ERROR_BAD_KEY );
   709 	return SECFailure;
   710     }
   712     session = pk11_GetNewSession(slot,&owner);
   713     if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
   714     crv = PK11_GETTAB(slot)->C_VerifyInit(session,&mech,id);
   715     if (crv != CKR_OK) {
   716 	if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
   717 	pk11_CloseSession(slot,session,owner);
   718 	PK11_FreeSlot(slot);
   719 	PORT_SetError( PK11_MapError(crv) );
   720 	return SECFailure;
   721     }
   722     crv = PK11_GETTAB(slot)->C_Verify(session,hash->data,
   723 					hash->len, sig->data, sig->len);
   724     if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
   725     pk11_CloseSession(slot,session,owner);
   726     PK11_FreeSlot(slot);
   727     if (crv != CKR_OK) {
   728 	PORT_SetError( PK11_MapError(crv) );
   729 	return SECFailure;
   730     }
   731     return SECSuccess;
   732 }
   734 /*
   735  * sign a hash. The algorithm is determined by the key.
   736  */
   737 SECStatus
   738 PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash)
   739 {
   740     PK11SlotInfo *slot = key->pkcs11Slot;
   741     CK_MECHANISM mech = {0, NULL, 0 };
   742     PRBool owner = PR_TRUE;
   743     CK_SESSION_HANDLE session;
   744     PRBool haslock = PR_FALSE;
   745     CK_ULONG len;
   746     CK_RV crv;
   748     mech.mechanism = PK11_MapSignKeyType(key->keyType);
   750     if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) {
   751 	PK11_HandlePasswordCheck(slot, key->wincx);
   752     }
   754     session = pk11_GetNewSession(slot,&owner);
   755     haslock = (!owner || !(slot->isThreadSafe));
   756     if (haslock) PK11_EnterSlotMonitor(slot);
   757     crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID);
   758     if (crv != CKR_OK) {
   759 	if (haslock) PK11_ExitSlotMonitor(slot);
   760 	pk11_CloseSession(slot,session,owner);
   761 	PORT_SetError( PK11_MapError(crv) );
   762 	return SECFailure;
   763     }
   765     /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then 
   766      * do C_Login with CKU_CONTEXT_SPECIFIC 
   767      * between C_SignInit and C_Sign */
   768     if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
   769 	PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
   770     }
   772     len = sig->len;
   773     crv = PK11_GETTAB(slot)->C_Sign(session,hash->data,
   774 					hash->len, sig->data, &len);
   775     if (haslock) PK11_ExitSlotMonitor(slot);
   776     pk11_CloseSession(slot,session,owner);
   777     sig->len = len;
   778     if (crv != CKR_OK) {
   779 	PORT_SetError( PK11_MapError(crv) );
   780 	return SECFailure;
   781     }
   782     return SECSuccess;
   783 }
   785 /*
   786  * sign data with a MAC key.
   787  */
   788 SECStatus
   789 PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism,
   790 		    SECItem *param, SECItem *sig, const SECItem *data)
   791 {
   792     PK11SlotInfo *slot = symKey->slot;
   793     CK_MECHANISM mech = {0, NULL, 0 };
   794     PRBool owner = PR_TRUE;
   795     CK_SESSION_HANDLE session;
   796     PRBool haslock = PR_FALSE;
   797     CK_ULONG len;
   798     CK_RV crv;
   800     mech.mechanism = mechanism;
   801     if (param) {
   802 	mech.pParameter = param->data;
   803 	mech.ulParameterLen = param->len;
   804     }
   806     session = pk11_GetNewSession(slot,&owner);
   807     haslock = (!owner || !(slot->isThreadSafe));
   808     if (haslock) PK11_EnterSlotMonitor(slot);
   809     crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,symKey->objectID);
   810     if (crv != CKR_OK) {
   811 	if (haslock) PK11_ExitSlotMonitor(slot);
   812 	pk11_CloseSession(slot,session,owner);
   813 	PORT_SetError( PK11_MapError(crv) );
   814 	return SECFailure;
   815     }
   817     len = sig->len;
   818     crv = PK11_GETTAB(slot)->C_Sign(session,data->data,
   819 					data->len, sig->data, &len);
   820     if (haslock) PK11_ExitSlotMonitor(slot);
   821     pk11_CloseSession(slot,session,owner);
   822     sig->len = len;
   823     if (crv != CKR_OK) {
   824 	PORT_SetError( PK11_MapError(crv) );
   825 	return SECFailure;
   826     }
   827     return SECSuccess;
   828 }
   830 SECStatus
   831 PK11_Decrypt(PK11SymKey *symKey,
   832              CK_MECHANISM_TYPE mechanism, SECItem *param,
   833              unsigned char *out, unsigned int *outLen,
   834              unsigned int maxLen,
   835              const unsigned char *enc, unsigned encLen)
   836 {
   837     PK11SlotInfo *slot = symKey->slot;
   838     CK_MECHANISM mech = {0, NULL, 0 };
   839     CK_ULONG len = maxLen;
   840     PRBool owner = PR_TRUE;
   841     CK_SESSION_HANDLE session;
   842     PRBool haslock = PR_FALSE;
   843     CK_RV crv;
   845     mech.mechanism = mechanism;
   846     if (param) {
   847 	mech.pParameter = param->data;
   848 	mech.ulParameterLen = param->len;
   849     }
   851     session = pk11_GetNewSession(slot, &owner);
   852     haslock = (!owner || !slot->isThreadSafe);
   853     if (haslock) PK11_EnterSlotMonitor(slot);
   854     crv = PK11_GETTAB(slot)->C_DecryptInit(session, &mech, symKey->objectID);
   855     if (crv != CKR_OK) {
   856 	if (haslock) PK11_ExitSlotMonitor(slot);
   857 	pk11_CloseSession(slot, session, owner);
   858 	PORT_SetError( PK11_MapError(crv) );
   859 	return SECFailure;
   860     }
   862     crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen,
   863                                        out, &len);
   864     if (haslock) PK11_ExitSlotMonitor(slot);
   865     pk11_CloseSession(slot, session, owner);
   866     *outLen = len;
   867     if (crv != CKR_OK) {
   868 	PORT_SetError( PK11_MapError(crv) );
   869 	return SECFailure;
   870     }
   871     return SECSuccess;
   872 }
   874 SECStatus
   875 PK11_Encrypt(PK11SymKey *symKey,
   876              CK_MECHANISM_TYPE mechanism, SECItem *param,
   877              unsigned char *out, unsigned int *outLen,
   878              unsigned int maxLen,
   879              const unsigned char *data, unsigned int dataLen)
   880 {
   881     PK11SlotInfo *slot = symKey->slot;
   882     CK_MECHANISM mech = {0, NULL, 0 };
   883     CK_ULONG len = maxLen;
   884     PRBool owner = PR_TRUE;
   885     CK_SESSION_HANDLE session;
   886     PRBool haslock = PR_FALSE;
   887     CK_RV crv;
   889     mech.mechanism = mechanism;
   890     if (param) {
   891 	mech.pParameter = param->data;
   892 	mech.ulParameterLen = param->len;
   893     }
   895     session = pk11_GetNewSession(slot, &owner);
   896     haslock = (!owner || !slot->isThreadSafe);
   897     if (haslock) PK11_EnterSlotMonitor(slot);
   898     crv = PK11_GETTAB(slot)->C_EncryptInit(session, &mech, symKey->objectID);
   899     if (crv != CKR_OK) {
   900 	if (haslock) PK11_ExitSlotMonitor(slot);
   901 	pk11_CloseSession(slot,session,owner);
   902 	PORT_SetError( PK11_MapError(crv) );
   903 	return SECFailure;
   904     }
   905     crv = PK11_GETTAB(slot)->C_Encrypt(session, (unsigned char *)data,
   906                                        dataLen, out, &len);
   907     if (haslock) PK11_ExitSlotMonitor(slot);
   908     pk11_CloseSession(slot,session,owner);
   909     *outLen = len;
   910     if (crv != CKR_OK) {
   911 	PORT_SetError( PK11_MapError(crv) );
   912 	return SECFailure;
   913     }
   914     return SECSuccess;
   915 }
   917 static SECStatus
   918 pk11_PrivDecryptRaw(SECKEYPrivateKey *key,
   919                     unsigned char *data,  unsigned *outLen, unsigned int maxLen,
   920                     const unsigned char *enc, unsigned encLen,
   921                     CK_MECHANISM_PTR mech)
   922 {
   923     PK11SlotInfo *slot = key->pkcs11Slot;
   924     CK_ULONG out = maxLen;
   925     PRBool owner = PR_TRUE;
   926     CK_SESSION_HANDLE session;
   927     PRBool haslock = PR_FALSE;
   928     CK_RV crv;
   930     if (key->keyType != rsaKey) {
   931 	PORT_SetError( SEC_ERROR_INVALID_KEY );
   932 	return SECFailure;
   933     }
   935     /* Why do we do a PK11_handle check here? for simple
   936      * decryption? .. because the user may have asked for 'ask always'
   937      * and this is a private key operation. In practice, thought, it's mute
   938      * since only servers wind up using this function */
   939     if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) {
   940 	PK11_HandlePasswordCheck(slot, key->wincx);
   941     }
   942     session = pk11_GetNewSession(slot,&owner);
   943     haslock = (!owner || !(slot->isThreadSafe));
   944     if (haslock) PK11_EnterSlotMonitor(slot);
   945     crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, key->pkcs11ID);
   946     if (crv != CKR_OK) {
   947 	if (haslock) PK11_ExitSlotMonitor(slot);
   948 	pk11_CloseSession(slot,session,owner);
   949 	PORT_SetError( PK11_MapError(crv) );
   950 	return SECFailure;
   951     }
   953     /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then 
   954      * do C_Login with CKU_CONTEXT_SPECIFIC 
   955      * between C_DecryptInit and C_Decrypt
   956      * ... But see note above about servers */
   957     if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) {
   958 	PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE);
   959     }
   961     crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen,
   962 				       data, &out);
   963     if (haslock) PK11_ExitSlotMonitor(slot);
   964     pk11_CloseSession(slot,session,owner);
   965     *outLen = out;
   966     if (crv != CKR_OK) {
   967 	PORT_SetError( PK11_MapError(crv) );
   968 	return SECFailure;
   969     }
   970     return SECSuccess;
   971 }
   973 SECStatus
   974 PK11_PubDecryptRaw(SECKEYPrivateKey *key,
   975                    unsigned char *data, unsigned *outLen, unsigned int maxLen,
   976                    const unsigned char *enc, unsigned encLen)
   977 {
   978     CK_MECHANISM mech = {CKM_RSA_X_509, NULL, 0 };
   979     return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
   980 }
   982 SECStatus
   983 PK11_PrivDecryptPKCS1(SECKEYPrivateKey *key,
   984                       unsigned char *data, unsigned *outLen, unsigned int maxLen,
   985                       const unsigned char *enc, unsigned encLen)
   986 {
   987     CK_MECHANISM mech = {CKM_RSA_PKCS, NULL, 0 };
   988     return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech);
   989 }
   991 static SECStatus
   992 pk11_PubEncryptRaw(SECKEYPublicKey *key,
   993                    unsigned char *out, unsigned int *outLen,
   994                    unsigned int maxLen,
   995                    const unsigned char *data, unsigned dataLen,
   996                    CK_MECHANISM_PTR mech, void *wincx)
   997 {
   998     PK11SlotInfo *slot;
   999     CK_OBJECT_HANDLE id;
  1000     CK_ULONG len = maxLen;
  1001     PRBool owner = PR_TRUE;
  1002     CK_SESSION_HANDLE session;
  1003     CK_RV crv;
  1005     slot = PK11_GetBestSlotWithAttributes(mech->mechanism,CKF_ENCRYPT,0,wincx);
  1006     if (slot == NULL) {
  1007 	PORT_SetError( SEC_ERROR_NO_MODULE );
  1008 	return SECFailure;
  1011     id = PK11_ImportPublicKey(slot,key,PR_FALSE);
  1013     if (id == CK_INVALID_HANDLE) {
  1014 	PK11_FreeSlot(slot);
  1015 	PORT_SetError( SEC_ERROR_BAD_KEY );
  1016 	return SECFailure;
  1019     session = pk11_GetNewSession(slot,&owner);
  1020     if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot);
  1021     crv = PK11_GETTAB(slot)->C_EncryptInit(session, mech, id);
  1022     if (crv != CKR_OK) {
  1023 	if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
  1024 	pk11_CloseSession(slot,session,owner);
  1025 	PK11_FreeSlot(slot);
  1026 	PORT_SetError( PK11_MapError(crv) );
  1027 	return SECFailure;
  1029     crv = PK11_GETTAB(slot)->C_Encrypt(session,(unsigned char *)data,dataLen,
  1030 				       out,&len);
  1031     if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot);
  1032     pk11_CloseSession(slot,session,owner);
  1033     PK11_FreeSlot(slot);
  1034     *outLen = len;
  1035     if (crv != CKR_OK) {
  1036 	PORT_SetError( PK11_MapError(crv) );
  1037 	return SECFailure;
  1039     return SECSuccess;
  1042 SECStatus
  1043 PK11_PubEncryptRaw(SECKEYPublicKey *key,
  1044                    unsigned char *enc,
  1045                    const unsigned char *data, unsigned dataLen,
  1046                    void *wincx)
  1048     CK_MECHANISM mech = {CKM_RSA_X_509, NULL, 0 };
  1049     unsigned int outLen;
  1050     if (!key || key->keyType != rsaKey) {
  1051 	PORT_SetError(SEC_ERROR_BAD_KEY);
  1052 	return SECFailure;
  1054     outLen = SECKEY_PublicKeyStrength(key);
  1055     return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
  1056                               wincx);
  1059 SECStatus
  1060 PK11_PubEncryptPKCS1(SECKEYPublicKey *key,
  1061                      unsigned char *enc,
  1062                      const unsigned char *data, unsigned dataLen,
  1063                      void *wincx)
  1065     CK_MECHANISM mech = {CKM_RSA_PKCS, NULL, 0 };
  1066     unsigned int outLen;
  1067     if (!key || key->keyType != rsaKey) {
  1068 	PORT_SetError(SEC_ERROR_BAD_KEY);
  1069 	return SECFailure;
  1071     outLen = SECKEY_PublicKeyStrength(key);
  1072     return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech,
  1073                               wincx);
  1076 SECStatus
  1077 PK11_PrivDecrypt(SECKEYPrivateKey *key,
  1078                  CK_MECHANISM_TYPE mechanism, SECItem *param,
  1079                  unsigned char *out, unsigned int *outLen,
  1080                  unsigned int maxLen,
  1081                  const unsigned char *enc, unsigned encLen)
  1083     CK_MECHANISM mech = { mechanism, NULL, 0 };
  1084     if (param) {
  1085         mech.pParameter = param->data;
  1086         mech.ulParameterLen = param->len;
  1088     return pk11_PrivDecryptRaw(key, out, outLen, maxLen, enc, encLen, &mech);
  1091 SECStatus
  1092 PK11_PubEncrypt(SECKEYPublicKey *key,
  1093                 CK_MECHANISM_TYPE mechanism, SECItem *param,
  1094                 unsigned char *out, unsigned int *outLen,
  1095                 unsigned int maxLen,
  1096                 const unsigned char *data, unsigned dataLen,
  1097                 void *wincx)
  1099     CK_MECHANISM mech = { mechanism, NULL, 0 };
  1100     if (param) {
  1101         mech.pParameter = param->data;
  1102         mech.ulParameterLen = param->len;
  1104     return pk11_PubEncryptRaw(key, out, outLen, maxLen, data, dataLen, &mech,
  1105                               wincx);
  1108 SECKEYPrivateKey *
  1109 PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
  1110 		   CK_MECHANISM_TYPE wrapType, SECItem *param, 
  1111 		   SECItem *wrappedKey, SECItem *label, 
  1112 		   SECItem *idValue, PRBool perm, PRBool sensitive,
  1113 		   CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage,
  1114 		   int usageCount, void *wincx)
  1116     CK_BBOOL cktrue = CK_TRUE;
  1117     CK_BBOOL ckfalse = CK_FALSE;
  1118     CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
  1119     CK_ATTRIBUTE keyTemplate[15] ;
  1120     int templateCount = 0;
  1121     CK_OBJECT_HANDLE privKeyID;
  1122     CK_MECHANISM mechanism;
  1123     CK_ATTRIBUTE *attrs = keyTemplate;
  1124     SECItem *param_free = NULL, *ck_id = NULL;
  1125     CK_RV crv;
  1126     CK_SESSION_HANDLE rwsession;
  1127     PK11SymKey *newKey = NULL;
  1128     int i;
  1130     if(!slot || !wrappedKey || !idValue) {
  1131 	/* SET AN ERROR!!! */
  1132 	return NULL;
  1135     ck_id = PK11_MakeIDFromPubKey(idValue);
  1136     if(!ck_id) {
  1137 	return NULL;
  1140     PK11_SETATTRS(attrs, CKA_TOKEN, perm ? &cktrue : &ckfalse,
  1141 					 sizeof(cktrue)); attrs++;
  1142     PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++;
  1143     PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++;
  1144     PK11_SETATTRS(attrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse,
  1145 					 sizeof(cktrue)); attrs++;
  1146     PK11_SETATTRS(attrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse,
  1147 					sizeof(cktrue)); attrs++;
  1148     if (label && label->data) {
  1149 	PK11_SETATTRS(attrs, CKA_LABEL, label->data, label->len); attrs++;
  1151     PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); attrs++;
  1152     for (i=0; i < usageCount; i++) {
  1153     	PK11_SETATTRS(attrs, usage[i], &cktrue, sizeof(cktrue)); attrs++;
  1156     if (PK11_IsInternal(slot)) {
  1157 	PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, idValue->data, 
  1158 		      idValue->len); attrs++;
  1161     templateCount = attrs - keyTemplate;
  1162     PR_ASSERT(templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)) );
  1164     mechanism.mechanism = wrapType;
  1165     if(!param) param = param_free= PK11_ParamFromIV(wrapType, NULL);
  1166     if(param) {
  1167 	mechanism.pParameter = param->data;
  1168 	mechanism.ulParameterLen = param->len;
  1169     } else {
  1170 	mechanism.pParameter = NULL;
  1171 	mechanism.ulParameterLen = 0;
  1174     if (wrappingKey->slot != slot) {
  1175 	newKey = pk11_CopyToSlot(slot,wrapType,CKA_UNWRAP,wrappingKey);
  1176     } else {
  1177 	newKey = PK11_ReferenceSymKey(wrappingKey);
  1180     if (newKey) {
  1181 	if (perm) {
  1182 	    /* Get RW Session will either lock the monitor if necessary, 
  1183 	     *  or return a thread safe session handle, or fail. */ 
  1184 	    rwsession = PK11_GetRWSession(slot);
  1185 	} else {
  1186 	    rwsession = slot->session;
  1187 	    if (rwsession != CK_INVALID_SESSION) 
  1188 		PK11_EnterSlotMonitor(slot);
  1190         /* This is a lot a work to deal with fussy PKCS #11 modules
  1191          * that can't bother to return BAD_DATA when presented with an
  1192          * invalid session! */
  1193 	if (rwsession == CK_INVALID_SESSION) {
  1194 	    PORT_SetError(SEC_ERROR_BAD_DATA);
  1195 	    goto loser;
  1197 	crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism, 
  1198 					 newKey->objectID,
  1199 					 wrappedKey->data, 
  1200 					 wrappedKey->len, keyTemplate, 
  1201 					 templateCount, &privKeyID);
  1203 	if (perm) {
  1204 	    PK11_RestoreROSession(slot, rwsession);
  1205 	} else {
  1206 	    PK11_ExitSlotMonitor(slot);
  1208 	PK11_FreeSymKey(newKey);
  1209 	newKey = NULL;
  1210     } else {
  1211 	crv = CKR_FUNCTION_NOT_SUPPORTED;
  1214     if (ck_id) {
  1215 	SECITEM_FreeItem(ck_id, PR_TRUE);
  1216 	ck_id = NULL;
  1219     if (crv != CKR_OK) {
  1220 	/* we couldn't unwrap the key, use the internal module to do the
  1221 	 * unwrap, then load the new key into the token */
  1222 	 PK11SlotInfo *int_slot = PK11_GetInternalSlot();
  1224 	if (int_slot && (slot != int_slot)) {
  1225 	    SECKEYPrivateKey *privKey = PK11_UnwrapPrivKey(int_slot,
  1226 			wrappingKey, wrapType, param, wrappedKey, label,
  1227 			idValue, PR_FALSE, PR_FALSE, 
  1228 			keyType, usage, usageCount, wincx);
  1229 	    if (privKey) {
  1230 		SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(slot,privKey,
  1231 						NULL,perm,sensitive);
  1232 		SECKEY_DestroyPrivateKey(privKey);
  1233 		PK11_FreeSlot(int_slot);
  1234 		return newPrivKey;
  1237 	if (int_slot) PK11_FreeSlot(int_slot);
  1238 	PORT_SetError( PK11_MapError(crv) );
  1239 	return NULL;
  1241     return PK11_MakePrivKey(slot, nullKey, PR_FALSE, privKeyID, wincx);
  1243 loser:
  1244     if (newKey) {
  1245 	PK11_FreeSymKey(newKey);
  1247     if (ck_id) {
  1248 	SECITEM_FreeItem(ck_id, PR_TRUE);
  1250     return NULL;
  1253 /*
  1254  * Now we're going to wrap a SECKEYPrivateKey with a PK11SymKey
  1255  * The strategy is to get both keys to reside in the same slot,
  1256  * one that can perform the desired crypto mechanism and then
  1257  * call C_WrapKey after all the setup has taken place.
  1258  */
  1259 SECStatus
  1260 PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey, 
  1261 		 SECKEYPrivateKey *privKey, CK_MECHANISM_TYPE wrapType, 
  1262 		 SECItem *param, SECItem *wrappedKey, void *wincx)
  1264     PK11SlotInfo     *privSlot   = privKey->pkcs11Slot; /* The slot where
  1265 							 * the private key
  1266 							 * we are going to
  1267 							 * wrap lives.
  1268 							 */
  1269     PK11SymKey       *newSymKey  = NULL;
  1270     SECKEYPrivateKey *newPrivKey = NULL;
  1271     SECItem          *param_free = NULL;
  1272     CK_ULONG          len        = wrappedKey->len;
  1273     CK_MECHANISM      mech;
  1274     CK_RV             crv;
  1276     if (!privSlot || !PK11_DoesMechanism(privSlot, wrapType)) {
  1277         /* Figure out a slot that does the mechanism and try to import
  1278 	 * the private key onto that slot.
  1279 	 */
  1280         PK11SlotInfo *int_slot = PK11_GetInternalSlot();
  1282 	privSlot = int_slot; /* The private key has a new home */
  1283 	newPrivKey = PK11_LoadPrivKey(privSlot,privKey,NULL,PR_FALSE,PR_FALSE);
  1284 	/* newPrivKey has allocated its own reference to the slot, so it's
  1285 	 * safe until we destroy newPrivkey.
  1286 	 */
  1287 	PK11_FreeSlot(int_slot);
  1288 	if (newPrivKey == NULL) {
  1289 	    return SECFailure;
  1291 	privKey = newPrivKey;
  1294     if (privSlot != wrappingKey->slot) {
  1295         newSymKey = pk11_CopyToSlot (privSlot, wrapType, CKA_WRAP, 
  1296 				     wrappingKey);
  1297 	wrappingKey = newSymKey;
  1300     if (wrappingKey == NULL) {
  1301         if (newPrivKey) {
  1302 		SECKEY_DestroyPrivateKey(newPrivKey);
  1304 	return SECFailure;
  1306     mech.mechanism = wrapType;
  1307     if (!param) {
  1308         param = param_free = PK11_ParamFromIV(wrapType, NULL);
  1310     if (param) {
  1311         mech.pParameter     = param->data;
  1312 	mech.ulParameterLen = param->len;
  1313     } else {
  1314         mech.pParameter     = NULL;
  1315 	mech.ulParameterLen = 0;
  1318     PK11_EnterSlotMonitor(privSlot);
  1319     crv = PK11_GETTAB(privSlot)->C_WrapKey(privSlot->session, &mech, 
  1320 					   wrappingKey->objectID, 
  1321 					   privKey->pkcs11ID,
  1322 					   wrappedKey->data, &len);
  1323     PK11_ExitSlotMonitor(privSlot);
  1325     if (newSymKey) {
  1326         PK11_FreeSymKey(newSymKey);
  1328     if (newPrivKey) {
  1329         SECKEY_DestroyPrivateKey(newPrivKey);
  1331     if (param_free) {
  1332 	SECITEM_FreeItem(param_free,PR_TRUE);
  1335     if (crv != CKR_OK) {
  1336         PORT_SetError( PK11_MapError(crv) );
  1337 	return SECFailure;
  1340     wrappedKey->len = len;
  1341     return SECSuccess;
  1344 #if 0
  1345 /*
  1346  * Sample code relating to linked list returned by PK11_FindGenericObjects
  1347  */
  1349 /*
  1350  * You can walk the list with the following code:
  1351  */
  1352     firstObj = PK11_FindGenericObjects(slot, objClass);
  1353     for (thisObj=firstObj;
  1354          thisObj; 
  1355          thisObj=PK11_GetNextGenericObject(thisObj)) {
  1356         /* operate on thisObj */
  1358 /*
  1359  * If you want a particular object from the list...
  1360  */
  1361     firstObj = PK11_FindGenericObjects(slot, objClass);
  1362     for (thisObj=firstObj;
  1363          thisObj; 
  1364          thisObj=PK11_GetNextGenericObject(thisObj)) {
  1365    	if (isMyObj(thisObj)) {
  1366   	    if ( thisObj == firstObj) {
  1367                 /* NOTE: firstObj could be NULL at this point */
  1368   		firstObj = PK11_GetNextGenericObject(thsObj); 
  1370   	    PK11_UnlinkGenericObject(thisObj);
  1371             myObj = thisObj;
  1372             break;
  1376     PK11_DestroyGenericObjects(firstObj);
  1378       /* use myObj */
  1380     PK11_DestroyGenericObject(myObj);
  1381 #endif /* sample code */
  1383 /*
  1384  * return a linked, non-circular list of generic objects.
  1385  * If you are only interested
  1386  * in one object, just use the first object in the list. To find the
  1387  * rest of the list use PK11_GetNextGenericObject() to return the next object.
  1388  */
  1389 PK11GenericObject *
  1390 PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass)
  1392     CK_ATTRIBUTE template[1];
  1393     CK_ATTRIBUTE *attrs = template;
  1394     CK_OBJECT_HANDLE *objectIDs = NULL;
  1395     PK11GenericObject *lastObj = NULL, *obj;
  1396     PK11GenericObject *firstObj = NULL;
  1397     int i, count = 0;
  1400     PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++;
  1402     objectIDs = pk11_FindObjectsByTemplate(slot,template,1,&count);
  1403     if (objectIDs == NULL) {
  1404 	return NULL;
  1407     /* where we connect our object once we've created it.. */
  1408     for (i=0; i < count; i++) {
  1409 	obj = PORT_New(PK11GenericObject);
  1410 	if ( !obj ) {
  1411 	    if (firstObj) {
  1412 		PK11_DestroyGenericObjects(firstObj);
  1414 	    PORT_Free(objectIDs);
  1415 	    return NULL;
  1417 	/* initialize it */	
  1418 	obj->slot = PK11_ReferenceSlot(slot);
  1419 	obj->objectID = objectIDs[i];
  1420 	obj->next = NULL;
  1421 	obj->prev = NULL;
  1423 	/* link it in */
  1424 	if (firstObj == NULL) {
  1425 	    firstObj = obj;
  1426 	} else {
  1427 	    PK11_LinkGenericObject(lastObj, obj);
  1429 	lastObj = obj;
  1431     PORT_Free(objectIDs);
  1432     return firstObj;
  1435 /*
  1436  * get the Next Object in the list.
  1437  */
  1438 PK11GenericObject *
  1439 PK11_GetNextGenericObject(PK11GenericObject *object)
  1441     return object->next;
  1444 PK11GenericObject *
  1445 PK11_GetPrevGenericObject(PK11GenericObject *object)
  1447     return object->prev;
  1450 /*
  1451  * Link a single object into a new list.
  1452  * if the object is already in another list, remove it first.
  1453  */
  1454 SECStatus
  1455 PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object)
  1457     PK11_UnlinkGenericObject(object);
  1458     object->prev = list;
  1459     object->next = list->next;
  1460     list->next = object;
  1461     if (object->next != NULL) {
  1462 	object->next->prev = object;
  1464    return SECSuccess;
  1467 /*
  1468  * remove an object from the list. If the object isn't already in
  1469  * a list unlink becomes a noop.
  1470  */
  1471 SECStatus
  1472 PK11_UnlinkGenericObject(PK11GenericObject *object)
  1474     if (object->prev != NULL) {
  1475 	object->prev->next = object->next;
  1477     if (object->next != NULL) {
  1478 	object->next->prev = object->prev;
  1481     object->next = NULL;
  1482     object->prev = NULL;
  1483     return SECSuccess;
  1486 /*
  1487  * This function removes a single object from the list and destroys it.
  1488  * For an already unlinked object there is no difference between
  1489  * PK11_DestroyGenericObject and PK11_DestroyGenericObjects
  1490  */
  1491 SECStatus 
  1492 PK11_DestroyGenericObject(PK11GenericObject *object)
  1494     if (object == NULL) {
  1495 	return SECSuccess;
  1498     PK11_UnlinkGenericObject(object);
  1499     if (object->slot) {
  1500 	PK11_FreeSlot(object->slot);
  1502     PORT_Free(object);
  1503     return SECSuccess;
  1506 /*
  1507  * walk down a link list of generic objects destroying them.
  1508  * This will destroy all objects in a list that the object is linked into.
  1509  * (the list is traversed in both directions).
  1510  */
  1511 SECStatus 
  1512 PK11_DestroyGenericObjects(PK11GenericObject *objects)
  1514     PK11GenericObject *nextObject;
  1515     PK11GenericObject *prevObject;
  1517     if (objects == NULL) {
  1518 	return SECSuccess;
  1521     nextObject = objects->next;
  1522     prevObject = objects->prev;
  1524     /* delete all the objects after it in the list */
  1525     for (; objects;  objects = nextObject) {
  1526 	nextObject = objects->next;
  1527 	PK11_DestroyGenericObject(objects);
  1529     /* delete all the objects before it in the list */
  1530     for (objects = prevObject; objects;  objects = prevObject) {
  1531 	prevObject = objects->prev;
  1532 	PK11_DestroyGenericObject(objects);
  1534     return SECSuccess;
  1538 /*
  1539  * Hand Create a new object and return the Generic object for our new object.
  1540  */
  1541 PK11GenericObject *
  1542 PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
  1543 		int count,  PRBool token)
  1545     CK_OBJECT_HANDLE objectID;
  1546     PK11GenericObject *obj;
  1547     CK_RV crv;
  1549     PK11_EnterSlotMonitor(slot);
  1550     crv = PK11_CreateNewObject(slot, slot->session, pTemplate, count, 
  1551 			       token, &objectID);
  1552     PK11_ExitSlotMonitor(slot);
  1553     if (crv != CKR_OK) {
  1554 	PORT_SetError(PK11_MapError(crv));
  1555 	return NULL;
  1558     obj = PORT_New(PK11GenericObject);
  1559     if ( !obj ) {
  1560 	/* error set by PORT_New */
  1561 	return NULL;
  1564     /* initialize it */	
  1565     obj->slot = PK11_ReferenceSlot(slot);
  1566     obj->objectID = objectID;
  1567     obj->next = NULL;
  1568     obj->prev = NULL;
  1569     return obj;
  1572 /*
  1573  * Change an attribute on a raw object
  1574  */
  1575 SECStatus
  1576 PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec, 
  1577 				CK_ATTRIBUTE_TYPE attrType, SECItem *item)
  1579     PK11SlotInfo *slot = NULL;
  1580     CK_OBJECT_HANDLE handle;
  1581     CK_ATTRIBUTE setTemplate;
  1582     CK_RV crv;
  1583     CK_SESSION_HANDLE rwsession;
  1585     switch (objType) {
  1586     case PK11_TypeGeneric:
  1587 	slot = ((PK11GenericObject *)objSpec)->slot;
  1588 	handle = ((PK11GenericObject *)objSpec)->objectID;
  1589 	break;
  1590     case PK11_TypePrivKey:
  1591 	slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot;
  1592 	handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID;
  1593 	break;
  1594     case PK11_TypePubKey:
  1595 	slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot;
  1596 	handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID;
  1597 	break;
  1598     case PK11_TypeSymKey:
  1599 	slot = ((PK11SymKey *)objSpec)->slot;
  1600 	handle = ((PK11SymKey *)objSpec)->objectID;
  1601 	break;
  1602     case PK11_TypeCert: /* don't handle cert case for now */
  1603     default:
  1604 	break;
  1606     if (slot == NULL) {
  1607 	PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
  1608 	return SECFailure;
  1611     PK11_SETATTRS(&setTemplate, attrType, (CK_CHAR *) item->data, item->len);
  1612     rwsession = PK11_GetRWSession(slot);
  1613     if (rwsession == CK_INVALID_SESSION) {
  1614     	PORT_SetError(SEC_ERROR_BAD_DATA);
  1615     	return SECFailure;
  1617     crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, handle,
  1618 			&setTemplate, 1);
  1619     PK11_RestoreROSession(slot, rwsession);
  1620     if (crv != CKR_OK) {
  1621 	PORT_SetError(PK11_MapError(crv));
  1622 	return SECFailure;
  1624     return SECSuccess;
  1628 SECStatus
  1629 PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec, 
  1630 				CK_ATTRIBUTE_TYPE attrType, SECItem *item)
  1632     PK11SlotInfo *slot = NULL;
  1633     CK_OBJECT_HANDLE handle;
  1635     switch (objType) {
  1636     case PK11_TypeGeneric:
  1637 	slot = ((PK11GenericObject *)objSpec)->slot;
  1638 	handle = ((PK11GenericObject *)objSpec)->objectID;
  1639 	break;
  1640     case PK11_TypePrivKey:
  1641 	slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot;
  1642 	handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID;
  1643 	break;
  1644     case PK11_TypePubKey:
  1645 	slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot;
  1646 	handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID;
  1647 	break;
  1648     case PK11_TypeSymKey:
  1649 	slot = ((PK11SymKey *)objSpec)->slot;
  1650 	handle = ((PK11SymKey *)objSpec)->objectID;
  1651 	break;
  1652     case PK11_TypeCert: /* don't handle cert case for now */
  1653     default:
  1654 	break;
  1656     if (slot == NULL) {
  1657 	PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE);
  1658 	return SECFailure;
  1661     return PK11_ReadAttribute(slot, handle, attrType, NULL, item);
  1665 /*
  1666  * return the object handle that matches the template
  1667  */
  1668 CK_OBJECT_HANDLE
  1669 pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize)
  1671     CK_OBJECT_HANDLE object;
  1672     CK_RV crv = CKR_SESSION_HANDLE_INVALID;
  1673     CK_ULONG objectCount;
  1675     /*
  1676      * issue the find
  1677      */
  1678     PK11_EnterSlotMonitor(slot);
  1679     if (slot->session != CK_INVALID_SESSION) {
  1680 	crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, 
  1681 	                                           theTemplate, tsize);
  1683     if (crv != CKR_OK) {
  1684         PK11_ExitSlotMonitor(slot);
  1685 	PORT_SetError( PK11_MapError(crv) );
  1686 	return CK_INVALID_HANDLE;
  1689     crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount);
  1690     PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
  1691     PK11_ExitSlotMonitor(slot);
  1692     if ((crv != CKR_OK) || (objectCount < 1)) {
  1693 	/* shouldn't use SSL_ERROR... here */
  1694 	PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) :
  1695 						  SSL_ERROR_NO_CERTIFICATE);
  1696 	return CK_INVALID_HANDLE;
  1699     /* blow up if the PKCS #11 module returns us and invalid object handle */
  1700     PORT_Assert(object != CK_INVALID_HANDLE);
  1701     return object;
  1704 /*
  1705  * return all the object handles that matches the template
  1706  */
  1707 CK_OBJECT_HANDLE *
  1708 pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
  1709                            int templCount, int *object_count) 
  1711     CK_OBJECT_HANDLE *objID = NULL;
  1712     CK_ULONG returned_count = 0;
  1713     CK_RV crv = CKR_SESSION_HANDLE_INVALID;
  1715     PK11_EnterSlotMonitor(slot);
  1716     if (slot->session != CK_INVALID_SESSION) {
  1717 	crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, 
  1718 	                                           findTemplate, templCount);
  1720     if (crv != CKR_OK) {
  1721 	PK11_ExitSlotMonitor(slot);
  1722 	PORT_SetError( PK11_MapError(crv) );
  1723 	*object_count = -1;
  1724 	return NULL;
  1728     /*
  1729      * collect all the Matching Objects
  1730      */
  1731     do {
  1732 	CK_OBJECT_HANDLE *oldObjID = objID;
  1734 	if (objID == NULL) {
  1735     	    objID = (CK_OBJECT_HANDLE *) PORT_Alloc(sizeof(CK_OBJECT_HANDLE)*
  1736 				(*object_count+ PK11_SEARCH_CHUNKSIZE));
  1737 	} else {
  1738     	    objID = (CK_OBJECT_HANDLE *) PORT_Realloc(objID,
  1739 		sizeof(CK_OBJECT_HANDLE)*(*object_count+PK11_SEARCH_CHUNKSIZE));
  1742 	if (objID == NULL) {
  1743 	    if (oldObjID) PORT_Free(oldObjID);
  1744 	    break;
  1746     	crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,
  1747 		&objID[*object_count],PK11_SEARCH_CHUNKSIZE,&returned_count);
  1748 	if (crv != CKR_OK) {
  1749 	    PORT_SetError( PK11_MapError(crv) );
  1750 	    PORT_Free(objID);
  1751 	    objID = NULL;
  1752 	    break;
  1754 	*object_count += returned_count;
  1755     } while (returned_count == PK11_SEARCH_CHUNKSIZE);
  1757     PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
  1758     PK11_ExitSlotMonitor(slot);
  1760     if (objID && (*object_count == 0)) {
  1761 	PORT_Free(objID);
  1762 	return NULL;
  1764     if (objID == NULL) *object_count = -1;
  1765     return objID;
  1767 /*
  1768  * given a PKCS #11 object, match it's peer based on the KeyID. searchID
  1769  * is typically a privateKey or a certificate while the peer is the opposite
  1770  */
  1771 CK_OBJECT_HANDLE
  1772 PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID,
  1773 				 		CK_OBJECT_CLASS matchclass)
  1775     CK_ATTRIBUTE theTemplate[] = {
  1776 	{ CKA_ID, NULL, 0 },
  1777 	{ CKA_CLASS, NULL, 0 }
  1778     };
  1779     /* if you change the array, change the variable below as well */
  1780     CK_ATTRIBUTE *keyclass = &theTemplate[1];
  1781     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  1782     /* if you change the array, change the variable below as well */
  1783     CK_OBJECT_HANDLE peerID;
  1784     CK_OBJECT_HANDLE parent;
  1785     PLArenaPool *arena;
  1786     CK_RV crv;
  1788     /* now we need to create space for the public key */
  1789     arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE);
  1790     if (arena == NULL) return CK_INVALID_HANDLE;
  1792     crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize);
  1793     if (crv != CKR_OK) {
  1794 	PORT_FreeArena(arena,PR_FALSE);
  1795 	PORT_SetError( PK11_MapError(crv) );
  1796 	return CK_INVALID_HANDLE;
  1799     if ((theTemplate[0].ulValueLen == 0) || (theTemplate[0].ulValueLen == -1)) {
  1800 	PORT_FreeArena(arena,PR_FALSE);
  1801 	if (matchclass == CKO_CERTIFICATE)
  1802 	    PORT_SetError(SEC_ERROR_BAD_KEY);
  1803 	else
  1804 	    PORT_SetError(SEC_ERROR_NO_KEY);
  1805 	return CK_INVALID_HANDLE;
  1810     /*
  1811      * issue the find
  1812      */
  1813     parent = *(CK_OBJECT_CLASS *)(keyclass->pValue);
  1814     *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass;
  1816     peerID = pk11_FindObjectByTemplate(slot,theTemplate,tsize);
  1817     PORT_FreeArena(arena,PR_FALSE);
  1819     return peerID;
  1822 /*
  1823  * count the number of objects that match the template.
  1824  */
  1825 int
  1826 PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, 
  1827 							int templCount)
  1829     CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE];
  1830     int object_count = 0;
  1831     CK_ULONG returned_count = 0;
  1832     CK_RV crv = CKR_SESSION_HANDLE_INVALID;
  1834     PK11_EnterSlotMonitor(slot);
  1835     if (slot->session != CK_INVALID_SESSION) {
  1836 	crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
  1837 						   findTemplate, templCount);
  1839     if (crv != CKR_OK) {
  1840         PK11_ExitSlotMonitor(slot);
  1841 	PORT_SetError( PK11_MapError(crv) );
  1842 	return object_count;
  1845     /*
  1846      * collect all the Matching Objects
  1847      */
  1848     do {
  1849     	crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, objID, 
  1850 	                                       PK11_SEARCH_CHUNKSIZE, 
  1851 					       &returned_count);
  1852 	if (crv != CKR_OK) {
  1853 	    PORT_SetError( PK11_MapError(crv) );
  1854 	    break;
  1856 	object_count += returned_count;
  1857     } while (returned_count == PK11_SEARCH_CHUNKSIZE);
  1859     PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
  1860     PK11_ExitSlotMonitor(slot);
  1861     return object_count;
  1864 /*
  1865  * Traverse all the objects in a given slot.
  1866  */
  1867 SECStatus
  1868 PK11_TraverseSlot(PK11SlotInfo *slot, void *arg)
  1870     int i;
  1871     CK_OBJECT_HANDLE *objID = NULL;
  1872     int object_count = 0;
  1873     pk11TraverseSlot *slotcb = (pk11TraverseSlot*) arg;
  1875     objID = pk11_FindObjectsByTemplate(slot,slotcb->findTemplate,
  1876 		slotcb->templateCount,&object_count);
  1878     /*Actually this isn't a failure... there just were no objs to be found*/
  1879     if (object_count == 0) {
  1880 	return SECSuccess;
  1883     if (objID == NULL) {
  1884 	return SECFailure;
  1887     for (i=0; i < object_count; i++) {
  1888 	(*slotcb->callback)(slot,objID[i],slotcb->callbackArg);
  1890     PORT_Free(objID);
  1891     return SECSuccess;
  1894 /*
  1895  * Traverse all the objects in all slots.
  1896  */
  1897 SECStatus
  1898 pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), 
  1899 				void *arg, PRBool forceLogin, void *wincx) {
  1900     PK11SlotList *list;
  1901     PK11SlotListElement *le;
  1902     SECStatus rv;
  1904     /* get them all! */
  1905     list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,wincx);
  1906     if (list == NULL) return SECFailure;
  1908     /* look at each slot and authenticate as necessary */
  1909     for (le = list->head ; le; le = le->next) {
  1910 	if (forceLogin) {
  1911 	    rv = pk11_AuthenticateUnfriendly(le->slot, PR_FALSE, wincx);
  1912 	    if (rv != SECSuccess) {
  1913 		continue;
  1916 	if (callback) {
  1917 	    (*callback)(le->slot,arg);
  1921     PK11_FreeSlotList(list);
  1923     return SECSuccess;
  1926 CK_OBJECT_HANDLE *
  1927 PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr,
  1928 		CK_OBJECT_CLASS objclass, int *returnCount, void *wincx)
  1930     char *tokenName;
  1931     char *delimit;
  1932     PK11SlotInfo *slot;
  1933     CK_OBJECT_HANDLE *objID;
  1934     CK_ATTRIBUTE findTemplate[] = {
  1935 	 { CKA_LABEL, NULL, 0},
  1936 	 { CKA_CLASS, NULL, 0},
  1937     };
  1938     int findCount = sizeof(findTemplate)/sizeof(findTemplate[0]);
  1939     SECStatus rv;
  1940     PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass));
  1942     *slotptr = slot = NULL;
  1943     *returnCount = 0;
  1944     /* first find the slot associated with this nickname */
  1945     if ((delimit = PORT_Strchr(nickname,':')) != NULL) {
  1946 	int len = delimit - nickname;
  1947 	tokenName = (char*)PORT_Alloc(len+1);
  1948 	PORT_Memcpy(tokenName,nickname,len);
  1949 	tokenName[len] = 0;
  1951         slot = *slotptr = PK11_FindSlotByName(tokenName);
  1952         PORT_Free(tokenName);
  1953 	/* if we couldn't find a slot, assume the nickname is an internal cert
  1954 	 * with no proceding slot name */
  1955 	if (slot == NULL) {
  1956 		slot = *slotptr = PK11_GetInternalKeySlot();
  1957 	} else {
  1958 		nickname = delimit+1;
  1960     } else {
  1961 	*slotptr = slot = PK11_GetInternalKeySlot();
  1963     if (slot == NULL) {
  1964         return CK_INVALID_HANDLE;
  1967     rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx);
  1968     if (rv != SECSuccess) {
  1969 	PK11_FreeSlot(slot);
  1970 	*slotptr = NULL;
  1971 	return CK_INVALID_HANDLE;
  1974     findTemplate[0].pValue = nickname;
  1975     findTemplate[0].ulValueLen = PORT_Strlen(nickname);
  1976     objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,returnCount);
  1977     if (objID == NULL) {
  1978 	/* PKCS #11 isn't clear on whether or not the NULL is
  1979 	 * stored in the template.... try the find again with the
  1980 	 * full null terminated string. */
  1981     	findTemplate[0].ulValueLen += 1;
  1982         objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,
  1983 								returnCount);
  1984 	if (objID == NULL) {
  1985 	    /* Well that's the best we can do. It's just not here */
  1986 	    /* what about faked nicknames? */
  1987 	    PK11_FreeSlot(slot);
  1988 	    *slotptr = NULL;
  1989 	    *returnCount = 0;
  1993     return objID;
  1996 SECItem *
  1997 pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle) 
  1999     CK_ATTRIBUTE theTemplate[] = {
  2000 	{ CKA_ID, NULL, 0 },
  2001     };
  2002     int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]);
  2003     CK_RV crv;
  2004     SECItem *item;
  2006     item = SECITEM_AllocItem(NULL, NULL, 0);
  2008     if (item == NULL) {
  2009 	return NULL;
  2012     crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize);
  2013     if (crv != CKR_OK) {
  2014 	SECITEM_FreeItem(item,PR_TRUE);
  2015 	PORT_SetError( PK11_MapError(crv) );
  2016 	return NULL;
  2019     item->data = (unsigned char*) theTemplate[0].pValue;
  2020     item->len =theTemplate[0].ulValueLen;
  2022     return item;

mercurial