security/nss/lib/pk11wrap/pk11obj.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial