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