1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/pk11wrap/pk11obj.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2024 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 +/* 1.8 + * This file manages object type indepentent functions. 1.9 + */ 1.10 +#include "seccomon.h" 1.11 +#include "secmod.h" 1.12 +#include "secmodi.h" 1.13 +#include "secmodti.h" 1.14 +#include "pkcs11.h" 1.15 +#include "pkcs11t.h" 1.16 +#include "pk11func.h" 1.17 +#include "key.h" 1.18 +#include "secitem.h" 1.19 +#include "secerr.h" 1.20 +#include "sslerr.h" 1.21 + 1.22 +#define PK11_SEARCH_CHUNKSIZE 10 1.23 + 1.24 +/* 1.25 + * Build a block big enough to hold the data 1.26 + */ 1.27 +SECItem * 1.28 +PK11_BlockData(SECItem *data,unsigned long size) { 1.29 + SECItem *newData; 1.30 + 1.31 + newData = (SECItem *)PORT_Alloc(sizeof(SECItem)); 1.32 + if (newData == NULL) return NULL; 1.33 + 1.34 + newData->len = (data->len + (size-1))/size; 1.35 + newData->len *= size; 1.36 + 1.37 + newData->data = (unsigned char *) PORT_ZAlloc(newData->len); 1.38 + if (newData->data == NULL) { 1.39 + PORT_Free(newData); 1.40 + return NULL; 1.41 + } 1.42 + PORT_Memset(newData->data,newData->len-data->len,newData->len); 1.43 + PORT_Memcpy(newData->data,data->data,data->len); 1.44 + return newData; 1.45 +} 1.46 + 1.47 + 1.48 +SECStatus 1.49 +PK11_DestroyObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) { 1.50 + CK_RV crv; 1.51 + 1.52 + PK11_EnterSlotMonitor(slot); 1.53 + crv = PK11_GETTAB(slot)->C_DestroyObject(slot->session,object); 1.54 + PK11_ExitSlotMonitor(slot); 1.55 + if (crv != CKR_OK) { 1.56 + return SECFailure; 1.57 + } 1.58 + return SECSuccess; 1.59 +} 1.60 + 1.61 +SECStatus 1.62 +PK11_DestroyTokenObject(PK11SlotInfo *slot,CK_OBJECT_HANDLE object) { 1.63 + CK_RV crv; 1.64 + SECStatus rv = SECSuccess; 1.65 + CK_SESSION_HANDLE rwsession; 1.66 + 1.67 + 1.68 + rwsession = PK11_GetRWSession(slot); 1.69 + if (rwsession == CK_INVALID_SESSION) { 1.70 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.71 + return SECFailure; 1.72 + } 1.73 + 1.74 + crv = PK11_GETTAB(slot)->C_DestroyObject(rwsession,object); 1.75 + if (crv != CKR_OK) { 1.76 + rv = SECFailure; 1.77 + PORT_SetError(PK11_MapError(crv)); 1.78 + } 1.79 + PK11_RestoreROSession(slot,rwsession); 1.80 + return rv; 1.81 +} 1.82 + 1.83 +/* 1.84 + * Read in a single attribute into a SECItem. Allocate space for it with 1.85 + * PORT_Alloc unless an arena is supplied. In the latter case use the arena 1.86 + * to allocate the space. 1.87 + * 1.88 + * PK11_ReadAttribute sets the 'data' and 'len' fields of the SECItem but 1.89 + * does not modify its 'type' field. 1.90 + */ 1.91 +SECStatus 1.92 +PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, 1.93 + CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result) { 1.94 + CK_ATTRIBUTE attr = { 0, NULL, 0 }; 1.95 + CK_RV crv; 1.96 + 1.97 + attr.type = type; 1.98 + 1.99 + PK11_EnterSlotMonitor(slot); 1.100 + crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1); 1.101 + if (crv != CKR_OK) { 1.102 + PK11_ExitSlotMonitor(slot); 1.103 + PORT_SetError(PK11_MapError(crv)); 1.104 + return SECFailure; 1.105 + } 1.106 + if (arena) { 1.107 + attr.pValue = PORT_ArenaAlloc(arena,attr.ulValueLen); 1.108 + } else { 1.109 + attr.pValue = PORT_Alloc(attr.ulValueLen); 1.110 + } 1.111 + if (attr.pValue == NULL) { 1.112 + PK11_ExitSlotMonitor(slot); 1.113 + return SECFailure; 1.114 + } 1.115 + crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1); 1.116 + PK11_ExitSlotMonitor(slot); 1.117 + if (crv != CKR_OK) { 1.118 + PORT_SetError(PK11_MapError(crv)); 1.119 + if (!arena) PORT_Free(attr.pValue); 1.120 + return SECFailure; 1.121 + } 1.122 + 1.123 + result->data = (unsigned char*)attr.pValue; 1.124 + result->len = attr.ulValueLen; 1.125 + 1.126 + return SECSuccess; 1.127 +} 1.128 + 1.129 +/* 1.130 + * Read in a single attribute into As a Ulong. 1.131 + */ 1.132 +CK_ULONG 1.133 +PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, 1.134 + CK_ATTRIBUTE_TYPE type) { 1.135 + CK_ATTRIBUTE attr; 1.136 + CK_ULONG value = CK_UNAVAILABLE_INFORMATION; 1.137 + CK_RV crv; 1.138 + 1.139 + PK11_SETATTRS(&attr,type,&value,sizeof(value)); 1.140 + 1.141 + PK11_EnterSlotMonitor(slot); 1.142 + crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,id,&attr,1); 1.143 + PK11_ExitSlotMonitor(slot); 1.144 + if (crv != CKR_OK) { 1.145 + PORT_SetError(PK11_MapError(crv)); 1.146 + } 1.147 + return value; 1.148 +} 1.149 + 1.150 +/* 1.151 + * check to see if a bool has been set. 1.152 + */ 1.153 +CK_BBOOL 1.154 +PK11_HasAttributeSet( PK11SlotInfo *slot, CK_OBJECT_HANDLE id, 1.155 + CK_ATTRIBUTE_TYPE type, PRBool haslock ) 1.156 +{ 1.157 + CK_BBOOL ckvalue = CK_FALSE; 1.158 + CK_ATTRIBUTE theTemplate; 1.159 + CK_RV crv; 1.160 + 1.161 + /* Prepare to retrieve the attribute. */ 1.162 + PK11_SETATTRS( &theTemplate, type, &ckvalue, sizeof( CK_BBOOL ) ); 1.163 + 1.164 + /* Retrieve attribute value. */ 1.165 + if (!haslock) PK11_EnterSlotMonitor(slot); 1.166 + crv = PK11_GETTAB( slot )->C_GetAttributeValue( slot->session, id, 1.167 + &theTemplate, 1 ); 1.168 + if (!haslock) PK11_ExitSlotMonitor(slot); 1.169 + if( crv != CKR_OK ) { 1.170 + PORT_SetError( PK11_MapError( crv ) ); 1.171 + return CK_FALSE; 1.172 + } 1.173 + 1.174 + return ckvalue; 1.175 +} 1.176 + 1.177 +/* 1.178 + * returns a full list of attributes. Allocate space for them. If an arena is 1.179 + * provided, allocate space out of the arena. 1.180 + */ 1.181 +CK_RV 1.182 +PK11_GetAttributes(PLArenaPool *arena,PK11SlotInfo *slot, 1.183 + CK_OBJECT_HANDLE obj,CK_ATTRIBUTE *attr, int count) 1.184 +{ 1.185 + int i; 1.186 + /* make pedantic happy... note that it's only used arena != NULL */ 1.187 + void *mark = NULL; 1.188 + CK_RV crv; 1.189 + PORT_Assert(slot->session != CK_INVALID_SESSION); 1.190 + if (slot->session == CK_INVALID_SESSION) 1.191 + return CKR_SESSION_HANDLE_INVALID; 1.192 + 1.193 + /* 1.194 + * first get all the lengths of the parameters. 1.195 + */ 1.196 + PK11_EnterSlotMonitor(slot); 1.197 + crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,obj,attr,count); 1.198 + if (crv != CKR_OK) { 1.199 + PK11_ExitSlotMonitor(slot); 1.200 + return crv; 1.201 + } 1.202 + 1.203 + if (arena) { 1.204 + mark = PORT_ArenaMark(arena); 1.205 + if (mark == NULL) return CKR_HOST_MEMORY; 1.206 + } 1.207 + 1.208 + /* 1.209 + * now allocate space to store the results. 1.210 + */ 1.211 + for (i=0; i < count; i++) { 1.212 + if (attr[i].ulValueLen == 0) 1.213 + continue; 1.214 + if (arena) { 1.215 + attr[i].pValue = PORT_ArenaAlloc(arena,attr[i].ulValueLen); 1.216 + if (attr[i].pValue == NULL) { 1.217 + /* arena failures, just release the mark */ 1.218 + PORT_ArenaRelease(arena,mark); 1.219 + PK11_ExitSlotMonitor(slot); 1.220 + return CKR_HOST_MEMORY; 1.221 + } 1.222 + } else { 1.223 + attr[i].pValue = PORT_Alloc(attr[i].ulValueLen); 1.224 + if (attr[i].pValue == NULL) { 1.225 + /* Separate malloc failures, loop to release what we have 1.226 + * so far */ 1.227 + int j; 1.228 + for (j= 0; j < i; j++) { 1.229 + PORT_Free(attr[j].pValue); 1.230 + /* don't give the caller pointers to freed memory */ 1.231 + attr[j].pValue = NULL; 1.232 + } 1.233 + PK11_ExitSlotMonitor(slot); 1.234 + return CKR_HOST_MEMORY; 1.235 + } 1.236 + } 1.237 + } 1.238 + 1.239 + /* 1.240 + * finally get the results. 1.241 + */ 1.242 + crv = PK11_GETTAB(slot)->C_GetAttributeValue(slot->session,obj,attr,count); 1.243 + PK11_ExitSlotMonitor(slot); 1.244 + if (crv != CKR_OK) { 1.245 + if (arena) { 1.246 + PORT_ArenaRelease(arena,mark); 1.247 + } else { 1.248 + for (i= 0; i < count; i++) { 1.249 + PORT_Free(attr[i].pValue); 1.250 + /* don't give the caller pointers to freed memory */ 1.251 + attr[i].pValue = NULL; 1.252 + } 1.253 + } 1.254 + } else if (arena && mark) { 1.255 + PORT_ArenaUnmark(arena,mark); 1.256 + } 1.257 + return crv; 1.258 +} 1.259 + 1.260 +PRBool 1.261 +PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle) 1.262 +{ 1.263 + return (PRBool) PK11_HasAttributeSet(slot, handle, CKA_TOKEN, PR_FALSE); 1.264 +} 1.265 + 1.266 +char * 1.267 +PK11_GetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id) 1.268 +{ 1.269 + char *nickname = NULL; 1.270 + SECItem result; 1.271 + SECStatus rv; 1.272 + 1.273 + rv = PK11_ReadAttribute(slot,id,CKA_LABEL,NULL,&result); 1.274 + if (rv != SECSuccess) { 1.275 + return NULL; 1.276 + } 1.277 + 1.278 + nickname = PORT_ZAlloc(result.len+1); 1.279 + if (nickname == NULL) { 1.280 + PORT_Free(result.data); 1.281 + return NULL; 1.282 + } 1.283 + PORT_Memcpy(nickname, result.data, result.len); 1.284 + PORT_Free(result.data); 1.285 + return nickname; 1.286 +} 1.287 + 1.288 +SECStatus 1.289 +PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id, 1.290 + const char *nickname) 1.291 +{ 1.292 + int len = PORT_Strlen(nickname); 1.293 + CK_ATTRIBUTE setTemplate; 1.294 + CK_RV crv; 1.295 + CK_SESSION_HANDLE rwsession; 1.296 + 1.297 + if (len < 0) { 1.298 + return SECFailure; 1.299 + } 1.300 + 1.301 + PK11_SETATTRS(&setTemplate, CKA_LABEL, (CK_CHAR *) nickname, len); 1.302 + rwsession = PK11_GetRWSession(slot); 1.303 + if (rwsession == CK_INVALID_SESSION) { 1.304 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.305 + return SECFailure; 1.306 + } 1.307 + crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, id, 1.308 + &setTemplate, 1); 1.309 + PK11_RestoreROSession(slot, rwsession); 1.310 + if (crv != CKR_OK) { 1.311 + PORT_SetError(PK11_MapError(crv)); 1.312 + return SECFailure; 1.313 + } 1.314 + return SECSuccess; 1.315 +} 1.316 + 1.317 +/* 1.318 + * strip leading zero's from key material 1.319 + */ 1.320 +void 1.321 +pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib) { 1.322 + char *ptr = (char *)attrib->pValue; 1.323 + unsigned long len = attrib->ulValueLen; 1.324 + 1.325 + while ((len > 1) && (*ptr == 0)) { 1.326 + len--; 1.327 + ptr++; 1.328 + } 1.329 + attrib->pValue = ptr; 1.330 + attrib->ulValueLen = len; 1.331 +} 1.332 + 1.333 +/* 1.334 + * get a new session on a slot. If we run out of session, use the slot's 1.335 + * 'exclusive' session. In this case owner becomes false. 1.336 + */ 1.337 +CK_SESSION_HANDLE 1.338 +pk11_GetNewSession(PK11SlotInfo *slot,PRBool *owner) 1.339 +{ 1.340 + CK_SESSION_HANDLE session; 1.341 + *owner = PR_TRUE; 1.342 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.343 + if ( PK11_GETTAB(slot)->C_OpenSession(slot->slotID,CKF_SERIAL_SESSION, 1.344 + slot,pk11_notify,&session) != CKR_OK) { 1.345 + *owner = PR_FALSE; 1.346 + session = slot->session; 1.347 + } 1.348 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.349 + 1.350 + return session; 1.351 +} 1.352 + 1.353 +void 1.354 +pk11_CloseSession(PK11SlotInfo *slot,CK_SESSION_HANDLE session,PRBool owner) 1.355 +{ 1.356 + if (!owner) return; 1.357 + if (!slot->isThreadSafe) PK11_EnterSlotMonitor(slot); 1.358 + (void) PK11_GETTAB(slot)->C_CloseSession(session); 1.359 + if (!slot->isThreadSafe) PK11_ExitSlotMonitor(slot); 1.360 +} 1.361 + 1.362 + 1.363 +SECStatus 1.364 +PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session, 1.365 + const CK_ATTRIBUTE *theTemplate, int count, 1.366 + PRBool token, CK_OBJECT_HANDLE *objectID) 1.367 +{ 1.368 + CK_SESSION_HANDLE rwsession; 1.369 + CK_RV crv; 1.370 + SECStatus rv = SECSuccess; 1.371 + 1.372 + rwsession = session; 1.373 + if (token) { 1.374 + rwsession = PK11_GetRWSession(slot); 1.375 + } else if (rwsession == CK_INVALID_SESSION) { 1.376 + rwsession = slot->session; 1.377 + if (rwsession != CK_INVALID_SESSION) 1.378 + PK11_EnterSlotMonitor(slot); 1.379 + } 1.380 + if (rwsession == CK_INVALID_SESSION) { 1.381 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.382 + return SECFailure; 1.383 + } 1.384 + crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, 1.385 + /* cast away const :-( */ (CK_ATTRIBUTE_PTR)theTemplate, 1.386 + count, objectID); 1.387 + if(crv != CKR_OK) { 1.388 + PORT_SetError( PK11_MapError(crv) ); 1.389 + rv = SECFailure; 1.390 + } 1.391 + if (token) { 1.392 + PK11_RestoreROSession(slot, rwsession); 1.393 + } else if (session == CK_INVALID_SESSION) { 1.394 + PK11_ExitSlotMonitor(slot); 1.395 + } 1.396 + 1.397 + return rv; 1.398 +} 1.399 + 1.400 + 1.401 +/* This function may add a maximum of 9 attributes. */ 1.402 +unsigned int 1.403 +pk11_OpFlagsToAttributes(CK_FLAGS flags, CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue) 1.404 +{ 1.405 + 1.406 + const static CK_ATTRIBUTE_TYPE attrTypes[12] = { 1.407 + CKA_ENCRYPT, CKA_DECRYPT, 0 /* DIGEST */, CKA_SIGN, 1.408 + CKA_SIGN_RECOVER, CKA_VERIFY, CKA_VERIFY_RECOVER, 0 /* GEN */, 1.409 + 0 /* GEN PAIR */, CKA_WRAP, CKA_UNWRAP, CKA_DERIVE 1.410 + }; 1.411 + 1.412 + const CK_ATTRIBUTE_TYPE *pType = attrTypes; 1.413 + CK_ATTRIBUTE *attr = attrs; 1.414 + CK_FLAGS test = CKF_ENCRYPT; 1.415 + 1.416 + 1.417 + PR_ASSERT(!(flags & ~CKF_KEY_OPERATION_FLAGS)); 1.418 + flags &= CKF_KEY_OPERATION_FLAGS; 1.419 + 1.420 + for (; flags && test <= CKF_DERIVE; test <<= 1, ++pType) { 1.421 + if (test & flags) { 1.422 + flags ^= test; 1.423 + PR_ASSERT(*pType); 1.424 + PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue); 1.425 + ++attr; 1.426 + } 1.427 + } 1.428 + return (attr - attrs); 1.429 +} 1.430 + 1.431 +/* 1.432 + * Check for conflicting flags, for example, if both PK11_ATTR_PRIVATE 1.433 + * and PK11_ATTR_PUBLIC are set. 1.434 + */ 1.435 +PRBool 1.436 +pk11_BadAttrFlags(PK11AttrFlags attrFlags) 1.437 +{ 1.438 + PK11AttrFlags trueFlags = attrFlags & 0x55555555; 1.439 + PK11AttrFlags falseFlags = (attrFlags >> 1) & 0x55555555; 1.440 + return ((trueFlags & falseFlags) != 0); 1.441 +} 1.442 + 1.443 +/* 1.444 + * This function may add a maximum of 5 attributes. 1.445 + * The caller must make sure the attribute flags don't have conflicts. 1.446 + */ 1.447 +unsigned int 1.448 +pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags, CK_ATTRIBUTE *attrs, 1.449 + CK_BBOOL *ckTrue, CK_BBOOL *ckFalse) 1.450 +{ 1.451 + const static CK_ATTRIBUTE_TYPE attrTypes[5] = { 1.452 + CKA_TOKEN, CKA_PRIVATE, CKA_MODIFIABLE, CKA_SENSITIVE, 1.453 + CKA_EXTRACTABLE 1.454 + }; 1.455 + 1.456 + const CK_ATTRIBUTE_TYPE *pType = attrTypes; 1.457 + CK_ATTRIBUTE *attr = attrs; 1.458 + PK11AttrFlags test = PK11_ATTR_TOKEN; 1.459 + 1.460 + PR_ASSERT(!pk11_BadAttrFlags(attrFlags)); 1.461 + 1.462 + /* we test two related bitflags in each iteration */ 1.463 + for (; attrFlags && test <= PK11_ATTR_EXTRACTABLE; test <<= 2, ++pType) { 1.464 + if (test & attrFlags) { 1.465 + attrFlags ^= test; 1.466 + PK11_SETATTRS(attr, *pType, ckTrue, sizeof *ckTrue); 1.467 + ++attr; 1.468 + } else if ((test << 1) & attrFlags) { 1.469 + attrFlags ^= (test << 1); 1.470 + PK11_SETATTRS(attr, *pType, ckFalse, sizeof *ckFalse); 1.471 + ++attr; 1.472 + } 1.473 + } 1.474 + return (attr - attrs); 1.475 +} 1.476 + 1.477 +/* 1.478 + * Some non-compliant PKCS #11 vendors do not give us the modulus, so actually 1.479 + * set up a signature to get the signaure length. 1.480 + */ 1.481 +static int 1.482 +pk11_backupGetSignLength(SECKEYPrivateKey *key) 1.483 +{ 1.484 + PK11SlotInfo *slot = key->pkcs11Slot; 1.485 + CK_MECHANISM mech = {0, NULL, 0 }; 1.486 + PRBool owner = PR_TRUE; 1.487 + CK_SESSION_HANDLE session; 1.488 + CK_ULONG len; 1.489 + CK_RV crv; 1.490 + unsigned char h_data[20] = { 0 }; 1.491 + unsigned char buf[20]; /* obviously to small */ 1.492 + CK_ULONG smallLen = sizeof(buf); 1.493 + 1.494 + mech.mechanism = PK11_MapSignKeyType(key->keyType); 1.495 + 1.496 + session = pk11_GetNewSession(slot,&owner); 1.497 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.498 + crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID); 1.499 + if (crv != CKR_OK) { 1.500 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.501 + pk11_CloseSession(slot,session,owner); 1.502 + PORT_SetError( PK11_MapError(crv) ); 1.503 + return -1; 1.504 + } 1.505 + len = 0; 1.506 + crv = PK11_GETTAB(slot)->C_Sign(session,h_data,sizeof(h_data), 1.507 + NULL, &len); 1.508 + /* now call C_Sign with too small a buffer to clear the session state */ 1.509 + (void) PK11_GETTAB(slot)-> 1.510 + C_Sign(session,h_data,sizeof(h_data),buf,&smallLen); 1.511 + 1.512 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.513 + pk11_CloseSession(slot,session,owner); 1.514 + if (crv != CKR_OK) { 1.515 + PORT_SetError( PK11_MapError(crv) ); 1.516 + return -1; 1.517 + } 1.518 + return len; 1.519 +} 1.520 + 1.521 +/* 1.522 + * get the length of a signature object based on the key 1.523 + */ 1.524 +int 1.525 +PK11_SignatureLen(SECKEYPrivateKey *key) 1.526 +{ 1.527 + int val; 1.528 + SECItem attributeItem = {siBuffer, NULL, 0}; 1.529 + SECStatus rv; 1.530 + int length; 1.531 + 1.532 + switch (key->keyType) { 1.533 + case rsaKey: 1.534 + val = PK11_GetPrivateModulusLen(key); 1.535 + if (val == -1) { 1.536 + return pk11_backupGetSignLength(key); 1.537 + } 1.538 + return (unsigned long) val; 1.539 + 1.540 + case fortezzaKey: 1.541 + return 40; 1.542 + 1.543 + case dsaKey: 1.544 + rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_SUBPRIME, 1.545 + NULL, &attributeItem); 1.546 + if (rv == SECSuccess) { 1.547 + length = attributeItem.len; 1.548 + if ((length > 0) && attributeItem.data[0] == 0) { 1.549 + length--; 1.550 + } 1.551 + PORT_Free(attributeItem.data); 1.552 + return length*2; 1.553 + } 1.554 + return pk11_backupGetSignLength(key); 1.555 + 1.556 + case ecKey: 1.557 + rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, CKA_EC_PARAMS, 1.558 + NULL, &attributeItem); 1.559 + if (rv == SECSuccess) { 1.560 + length = SECKEY_ECParamsToBasePointOrderLen(&attributeItem); 1.561 + PORT_Free(attributeItem.data); 1.562 + if (length != 0) { 1.563 + length = ((length + 7)/8) * 2; 1.564 + return length; 1.565 + } 1.566 + } 1.567 + return pk11_backupGetSignLength(key); 1.568 + default: 1.569 + break; 1.570 + } 1.571 + PORT_SetError( SEC_ERROR_INVALID_KEY ); 1.572 + return 0; 1.573 +} 1.574 + 1.575 +/* 1.576 + * copy a key (or any other object) on a token 1.577 + */ 1.578 +CK_OBJECT_HANDLE 1.579 +PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject) 1.580 +{ 1.581 + CK_OBJECT_HANDLE destObject; 1.582 + CK_RV crv; 1.583 + 1.584 + PK11_EnterSlotMonitor(slot); 1.585 + crv = PK11_GETTAB(slot)->C_CopyObject(slot->session,srcObject,NULL,0, 1.586 + &destObject); 1.587 + PK11_ExitSlotMonitor(slot); 1.588 + if (crv == CKR_OK) return destObject; 1.589 + PORT_SetError( PK11_MapError(crv) ); 1.590 + return CK_INVALID_HANDLE; 1.591 +} 1.592 + 1.593 +PRBool 1.594 +pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs, 1.595 + CK_ATTRIBUTE_TYPE target) 1.596 +{ 1.597 + for (; numAttrs > 0; ++attr, --numAttrs) { 1.598 + if (attr->type == target) 1.599 + return PR_TRUE; 1.600 + } 1.601 + return PR_FALSE; 1.602 +} 1.603 + 1.604 +/* 1.605 + * Recover the Signed data. We need this because our old verify can't 1.606 + * figure out which hash algorithm to use until we decryptted this. 1.607 + */ 1.608 +SECStatus 1.609 +PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig, 1.610 + SECItem *dsig, void *wincx) 1.611 +{ 1.612 + PK11SlotInfo *slot = key->pkcs11Slot; 1.613 + CK_OBJECT_HANDLE id = key->pkcs11ID; 1.614 + CK_MECHANISM mech = {0, NULL, 0 }; 1.615 + PRBool owner = PR_TRUE; 1.616 + CK_SESSION_HANDLE session; 1.617 + CK_ULONG len; 1.618 + CK_RV crv; 1.619 + 1.620 + mech.mechanism = PK11_MapSignKeyType(key->keyType); 1.621 + 1.622 + if (slot == NULL) { 1.623 + slot = PK11_GetBestSlotWithAttributes(mech.mechanism, 1.624 + CKF_VERIFY_RECOVER,0,wincx); 1.625 + if (slot == NULL) { 1.626 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.627 + return SECFailure; 1.628 + } 1.629 + id = PK11_ImportPublicKey(slot,key,PR_FALSE); 1.630 + } else { 1.631 + PK11_ReferenceSlot(slot); 1.632 + } 1.633 + 1.634 + if (id == CK_INVALID_HANDLE) { 1.635 + PK11_FreeSlot(slot); 1.636 + PORT_SetError( SEC_ERROR_BAD_KEY ); 1.637 + return SECFailure; 1.638 + } 1.639 + 1.640 + session = pk11_GetNewSession(slot,&owner); 1.641 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.642 + crv = PK11_GETTAB(slot)->C_VerifyRecoverInit(session,&mech,id); 1.643 + if (crv != CKR_OK) { 1.644 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.645 + pk11_CloseSession(slot,session,owner); 1.646 + PORT_SetError( PK11_MapError(crv) ); 1.647 + PK11_FreeSlot(slot); 1.648 + return SECFailure; 1.649 + } 1.650 + len = dsig->len; 1.651 + crv = PK11_GETTAB(slot)->C_VerifyRecover(session,sig->data, 1.652 + sig->len, dsig->data, &len); 1.653 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.654 + pk11_CloseSession(slot,session,owner); 1.655 + dsig->len = len; 1.656 + if (crv != CKR_OK) { 1.657 + PORT_SetError( PK11_MapError(crv) ); 1.658 + PK11_FreeSlot(slot); 1.659 + return SECFailure; 1.660 + } 1.661 + PK11_FreeSlot(slot); 1.662 + return SECSuccess; 1.663 +} 1.664 + 1.665 +/* 1.666 + * verify a signature from its hash. 1.667 + */ 1.668 +SECStatus 1.669 +PK11_Verify(SECKEYPublicKey *key, const SECItem *sig, const SECItem *hash, 1.670 + void *wincx) 1.671 +{ 1.672 + PK11SlotInfo *slot = key->pkcs11Slot; 1.673 + CK_OBJECT_HANDLE id = key->pkcs11ID; 1.674 + CK_MECHANISM mech = {0, NULL, 0 }; 1.675 + PRBool owner = PR_TRUE; 1.676 + CK_SESSION_HANDLE session; 1.677 + CK_RV crv; 1.678 + 1.679 + mech.mechanism = PK11_MapSignKeyType(key->keyType); 1.680 + 1.681 + if (slot == NULL) { 1.682 + unsigned int length = 0; 1.683 + if ((mech.mechanism == CKM_DSA) && 1.684 + /* 129 is 1024 bits translated to bytes and 1.685 + * padded with an optional '0' to maintain a 1.686 + * positive sign */ 1.687 + (key->u.dsa.params.prime.len > 129)) { 1.688 + /* we need to get a slot that not only can do DSA, but can do DSA2 1.689 + * key lengths */ 1.690 + length = key->u.dsa.params.prime.len; 1.691 + if (key->u.dsa.params.prime.data[0] == 0) { 1.692 + length --; 1.693 + } 1.694 + /* convert keysize to bits for slot lookup */ 1.695 + length *= 8; 1.696 + } 1.697 + slot = PK11_GetBestSlotWithAttributes(mech.mechanism, 1.698 + CKF_VERIFY,length,wincx); 1.699 + if (slot == NULL) { 1.700 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.701 + return SECFailure; 1.702 + } 1.703 + id = PK11_ImportPublicKey(slot,key,PR_FALSE); 1.704 + 1.705 + } else { 1.706 + PK11_ReferenceSlot(slot); 1.707 + } 1.708 + 1.709 + if (id == CK_INVALID_HANDLE) { 1.710 + PK11_FreeSlot(slot); 1.711 + PORT_SetError( SEC_ERROR_BAD_KEY ); 1.712 + return SECFailure; 1.713 + } 1.714 + 1.715 + session = pk11_GetNewSession(slot,&owner); 1.716 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.717 + crv = PK11_GETTAB(slot)->C_VerifyInit(session,&mech,id); 1.718 + if (crv != CKR_OK) { 1.719 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.720 + pk11_CloseSession(slot,session,owner); 1.721 + PK11_FreeSlot(slot); 1.722 + PORT_SetError( PK11_MapError(crv) ); 1.723 + return SECFailure; 1.724 + } 1.725 + crv = PK11_GETTAB(slot)->C_Verify(session,hash->data, 1.726 + hash->len, sig->data, sig->len); 1.727 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.728 + pk11_CloseSession(slot,session,owner); 1.729 + PK11_FreeSlot(slot); 1.730 + if (crv != CKR_OK) { 1.731 + PORT_SetError( PK11_MapError(crv) ); 1.732 + return SECFailure; 1.733 + } 1.734 + return SECSuccess; 1.735 +} 1.736 + 1.737 +/* 1.738 + * sign a hash. The algorithm is determined by the key. 1.739 + */ 1.740 +SECStatus 1.741 +PK11_Sign(SECKEYPrivateKey *key, SECItem *sig, const SECItem *hash) 1.742 +{ 1.743 + PK11SlotInfo *slot = key->pkcs11Slot; 1.744 + CK_MECHANISM mech = {0, NULL, 0 }; 1.745 + PRBool owner = PR_TRUE; 1.746 + CK_SESSION_HANDLE session; 1.747 + PRBool haslock = PR_FALSE; 1.748 + CK_ULONG len; 1.749 + CK_RV crv; 1.750 + 1.751 + mech.mechanism = PK11_MapSignKeyType(key->keyType); 1.752 + 1.753 + if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) { 1.754 + PK11_HandlePasswordCheck(slot, key->wincx); 1.755 + } 1.756 + 1.757 + session = pk11_GetNewSession(slot,&owner); 1.758 + haslock = (!owner || !(slot->isThreadSafe)); 1.759 + if (haslock) PK11_EnterSlotMonitor(slot); 1.760 + crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,key->pkcs11ID); 1.761 + if (crv != CKR_OK) { 1.762 + if (haslock) PK11_ExitSlotMonitor(slot); 1.763 + pk11_CloseSession(slot,session,owner); 1.764 + PORT_SetError( PK11_MapError(crv) ); 1.765 + return SECFailure; 1.766 + } 1.767 + 1.768 + /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then 1.769 + * do C_Login with CKU_CONTEXT_SPECIFIC 1.770 + * between C_SignInit and C_Sign */ 1.771 + if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) { 1.772 + PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE); 1.773 + } 1.774 + 1.775 + len = sig->len; 1.776 + crv = PK11_GETTAB(slot)->C_Sign(session,hash->data, 1.777 + hash->len, sig->data, &len); 1.778 + if (haslock) PK11_ExitSlotMonitor(slot); 1.779 + pk11_CloseSession(slot,session,owner); 1.780 + sig->len = len; 1.781 + if (crv != CKR_OK) { 1.782 + PORT_SetError( PK11_MapError(crv) ); 1.783 + return SECFailure; 1.784 + } 1.785 + return SECSuccess; 1.786 +} 1.787 + 1.788 +/* 1.789 + * sign data with a MAC key. 1.790 + */ 1.791 +SECStatus 1.792 +PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism, 1.793 + SECItem *param, SECItem *sig, const SECItem *data) 1.794 +{ 1.795 + PK11SlotInfo *slot = symKey->slot; 1.796 + CK_MECHANISM mech = {0, NULL, 0 }; 1.797 + PRBool owner = PR_TRUE; 1.798 + CK_SESSION_HANDLE session; 1.799 + PRBool haslock = PR_FALSE; 1.800 + CK_ULONG len; 1.801 + CK_RV crv; 1.802 + 1.803 + mech.mechanism = mechanism; 1.804 + if (param) { 1.805 + mech.pParameter = param->data; 1.806 + mech.ulParameterLen = param->len; 1.807 + } 1.808 + 1.809 + session = pk11_GetNewSession(slot,&owner); 1.810 + haslock = (!owner || !(slot->isThreadSafe)); 1.811 + if (haslock) PK11_EnterSlotMonitor(slot); 1.812 + crv = PK11_GETTAB(slot)->C_SignInit(session,&mech,symKey->objectID); 1.813 + if (crv != CKR_OK) { 1.814 + if (haslock) PK11_ExitSlotMonitor(slot); 1.815 + pk11_CloseSession(slot,session,owner); 1.816 + PORT_SetError( PK11_MapError(crv) ); 1.817 + return SECFailure; 1.818 + } 1.819 + 1.820 + len = sig->len; 1.821 + crv = PK11_GETTAB(slot)->C_Sign(session,data->data, 1.822 + data->len, sig->data, &len); 1.823 + if (haslock) PK11_ExitSlotMonitor(slot); 1.824 + pk11_CloseSession(slot,session,owner); 1.825 + sig->len = len; 1.826 + if (crv != CKR_OK) { 1.827 + PORT_SetError( PK11_MapError(crv) ); 1.828 + return SECFailure; 1.829 + } 1.830 + return SECSuccess; 1.831 +} 1.832 + 1.833 +SECStatus 1.834 +PK11_Decrypt(PK11SymKey *symKey, 1.835 + CK_MECHANISM_TYPE mechanism, SECItem *param, 1.836 + unsigned char *out, unsigned int *outLen, 1.837 + unsigned int maxLen, 1.838 + const unsigned char *enc, unsigned encLen) 1.839 +{ 1.840 + PK11SlotInfo *slot = symKey->slot; 1.841 + CK_MECHANISM mech = {0, NULL, 0 }; 1.842 + CK_ULONG len = maxLen; 1.843 + PRBool owner = PR_TRUE; 1.844 + CK_SESSION_HANDLE session; 1.845 + PRBool haslock = PR_FALSE; 1.846 + CK_RV crv; 1.847 + 1.848 + mech.mechanism = mechanism; 1.849 + if (param) { 1.850 + mech.pParameter = param->data; 1.851 + mech.ulParameterLen = param->len; 1.852 + } 1.853 + 1.854 + session = pk11_GetNewSession(slot, &owner); 1.855 + haslock = (!owner || !slot->isThreadSafe); 1.856 + if (haslock) PK11_EnterSlotMonitor(slot); 1.857 + crv = PK11_GETTAB(slot)->C_DecryptInit(session, &mech, symKey->objectID); 1.858 + if (crv != CKR_OK) { 1.859 + if (haslock) PK11_ExitSlotMonitor(slot); 1.860 + pk11_CloseSession(slot, session, owner); 1.861 + PORT_SetError( PK11_MapError(crv) ); 1.862 + return SECFailure; 1.863 + } 1.864 + 1.865 + crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen, 1.866 + out, &len); 1.867 + if (haslock) PK11_ExitSlotMonitor(slot); 1.868 + pk11_CloseSession(slot, session, owner); 1.869 + *outLen = len; 1.870 + if (crv != CKR_OK) { 1.871 + PORT_SetError( PK11_MapError(crv) ); 1.872 + return SECFailure; 1.873 + } 1.874 + return SECSuccess; 1.875 +} 1.876 + 1.877 +SECStatus 1.878 +PK11_Encrypt(PK11SymKey *symKey, 1.879 + CK_MECHANISM_TYPE mechanism, SECItem *param, 1.880 + unsigned char *out, unsigned int *outLen, 1.881 + unsigned int maxLen, 1.882 + const unsigned char *data, unsigned int dataLen) 1.883 +{ 1.884 + PK11SlotInfo *slot = symKey->slot; 1.885 + CK_MECHANISM mech = {0, NULL, 0 }; 1.886 + CK_ULONG len = maxLen; 1.887 + PRBool owner = PR_TRUE; 1.888 + CK_SESSION_HANDLE session; 1.889 + PRBool haslock = PR_FALSE; 1.890 + CK_RV crv; 1.891 + 1.892 + mech.mechanism = mechanism; 1.893 + if (param) { 1.894 + mech.pParameter = param->data; 1.895 + mech.ulParameterLen = param->len; 1.896 + } 1.897 + 1.898 + session = pk11_GetNewSession(slot, &owner); 1.899 + haslock = (!owner || !slot->isThreadSafe); 1.900 + if (haslock) PK11_EnterSlotMonitor(slot); 1.901 + crv = PK11_GETTAB(slot)->C_EncryptInit(session, &mech, symKey->objectID); 1.902 + if (crv != CKR_OK) { 1.903 + if (haslock) PK11_ExitSlotMonitor(slot); 1.904 + pk11_CloseSession(slot,session,owner); 1.905 + PORT_SetError( PK11_MapError(crv) ); 1.906 + return SECFailure; 1.907 + } 1.908 + crv = PK11_GETTAB(slot)->C_Encrypt(session, (unsigned char *)data, 1.909 + dataLen, out, &len); 1.910 + if (haslock) PK11_ExitSlotMonitor(slot); 1.911 + pk11_CloseSession(slot,session,owner); 1.912 + *outLen = len; 1.913 + if (crv != CKR_OK) { 1.914 + PORT_SetError( PK11_MapError(crv) ); 1.915 + return SECFailure; 1.916 + } 1.917 + return SECSuccess; 1.918 +} 1.919 + 1.920 +static SECStatus 1.921 +pk11_PrivDecryptRaw(SECKEYPrivateKey *key, 1.922 + unsigned char *data, unsigned *outLen, unsigned int maxLen, 1.923 + const unsigned char *enc, unsigned encLen, 1.924 + CK_MECHANISM_PTR mech) 1.925 +{ 1.926 + PK11SlotInfo *slot = key->pkcs11Slot; 1.927 + CK_ULONG out = maxLen; 1.928 + PRBool owner = PR_TRUE; 1.929 + CK_SESSION_HANDLE session; 1.930 + PRBool haslock = PR_FALSE; 1.931 + CK_RV crv; 1.932 + 1.933 + if (key->keyType != rsaKey) { 1.934 + PORT_SetError( SEC_ERROR_INVALID_KEY ); 1.935 + return SECFailure; 1.936 + } 1.937 + 1.938 + /* Why do we do a PK11_handle check here? for simple 1.939 + * decryption? .. because the user may have asked for 'ask always' 1.940 + * and this is a private key operation. In practice, thought, it's mute 1.941 + * since only servers wind up using this function */ 1.942 + if (SECKEY_HAS_ATTRIBUTE_SET(key,CKA_PRIVATE)) { 1.943 + PK11_HandlePasswordCheck(slot, key->wincx); 1.944 + } 1.945 + session = pk11_GetNewSession(slot,&owner); 1.946 + haslock = (!owner || !(slot->isThreadSafe)); 1.947 + if (haslock) PK11_EnterSlotMonitor(slot); 1.948 + crv = PK11_GETTAB(slot)->C_DecryptInit(session, mech, key->pkcs11ID); 1.949 + if (crv != CKR_OK) { 1.950 + if (haslock) PK11_ExitSlotMonitor(slot); 1.951 + pk11_CloseSession(slot,session,owner); 1.952 + PORT_SetError( PK11_MapError(crv) ); 1.953 + return SECFailure; 1.954 + } 1.955 + 1.956 + /* PKCS11 2.20 says if CKA_ALWAYS_AUTHENTICATE then 1.957 + * do C_Login with CKU_CONTEXT_SPECIFIC 1.958 + * between C_DecryptInit and C_Decrypt 1.959 + * ... But see note above about servers */ 1.960 + if (SECKEY_HAS_ATTRIBUTE_SET_LOCK(key, CKA_ALWAYS_AUTHENTICATE, haslock)) { 1.961 + PK11_DoPassword(slot, session, PR_FALSE, key->wincx, haslock, PR_TRUE); 1.962 + } 1.963 + 1.964 + crv = PK11_GETTAB(slot)->C_Decrypt(session, (unsigned char *)enc, encLen, 1.965 + data, &out); 1.966 + if (haslock) PK11_ExitSlotMonitor(slot); 1.967 + pk11_CloseSession(slot,session,owner); 1.968 + *outLen = out; 1.969 + if (crv != CKR_OK) { 1.970 + PORT_SetError( PK11_MapError(crv) ); 1.971 + return SECFailure; 1.972 + } 1.973 + return SECSuccess; 1.974 +} 1.975 + 1.976 +SECStatus 1.977 +PK11_PubDecryptRaw(SECKEYPrivateKey *key, 1.978 + unsigned char *data, unsigned *outLen, unsigned int maxLen, 1.979 + const unsigned char *enc, unsigned encLen) 1.980 +{ 1.981 + CK_MECHANISM mech = {CKM_RSA_X_509, NULL, 0 }; 1.982 + return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech); 1.983 +} 1.984 + 1.985 +SECStatus 1.986 +PK11_PrivDecryptPKCS1(SECKEYPrivateKey *key, 1.987 + unsigned char *data, unsigned *outLen, unsigned int maxLen, 1.988 + const unsigned char *enc, unsigned encLen) 1.989 +{ 1.990 + CK_MECHANISM mech = {CKM_RSA_PKCS, NULL, 0 }; 1.991 + return pk11_PrivDecryptRaw(key, data, outLen, maxLen, enc, encLen, &mech); 1.992 +} 1.993 + 1.994 +static SECStatus 1.995 +pk11_PubEncryptRaw(SECKEYPublicKey *key, 1.996 + unsigned char *out, unsigned int *outLen, 1.997 + unsigned int maxLen, 1.998 + const unsigned char *data, unsigned dataLen, 1.999 + CK_MECHANISM_PTR mech, void *wincx) 1.1000 +{ 1.1001 + PK11SlotInfo *slot; 1.1002 + CK_OBJECT_HANDLE id; 1.1003 + CK_ULONG len = maxLen; 1.1004 + PRBool owner = PR_TRUE; 1.1005 + CK_SESSION_HANDLE session; 1.1006 + CK_RV crv; 1.1007 + 1.1008 + slot = PK11_GetBestSlotWithAttributes(mech->mechanism,CKF_ENCRYPT,0,wincx); 1.1009 + if (slot == NULL) { 1.1010 + PORT_SetError( SEC_ERROR_NO_MODULE ); 1.1011 + return SECFailure; 1.1012 + } 1.1013 + 1.1014 + id = PK11_ImportPublicKey(slot,key,PR_FALSE); 1.1015 + 1.1016 + if (id == CK_INVALID_HANDLE) { 1.1017 + PK11_FreeSlot(slot); 1.1018 + PORT_SetError( SEC_ERROR_BAD_KEY ); 1.1019 + return SECFailure; 1.1020 + } 1.1021 + 1.1022 + session = pk11_GetNewSession(slot,&owner); 1.1023 + if (!owner || !(slot->isThreadSafe)) PK11_EnterSlotMonitor(slot); 1.1024 + crv = PK11_GETTAB(slot)->C_EncryptInit(session, mech, id); 1.1025 + if (crv != CKR_OK) { 1.1026 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1027 + pk11_CloseSession(slot,session,owner); 1.1028 + PK11_FreeSlot(slot); 1.1029 + PORT_SetError( PK11_MapError(crv) ); 1.1030 + return SECFailure; 1.1031 + } 1.1032 + crv = PK11_GETTAB(slot)->C_Encrypt(session,(unsigned char *)data,dataLen, 1.1033 + out,&len); 1.1034 + if (!owner || !(slot->isThreadSafe)) PK11_ExitSlotMonitor(slot); 1.1035 + pk11_CloseSession(slot,session,owner); 1.1036 + PK11_FreeSlot(slot); 1.1037 + *outLen = len; 1.1038 + if (crv != CKR_OK) { 1.1039 + PORT_SetError( PK11_MapError(crv) ); 1.1040 + return SECFailure; 1.1041 + } 1.1042 + return SECSuccess; 1.1043 +} 1.1044 + 1.1045 +SECStatus 1.1046 +PK11_PubEncryptRaw(SECKEYPublicKey *key, 1.1047 + unsigned char *enc, 1.1048 + const unsigned char *data, unsigned dataLen, 1.1049 + void *wincx) 1.1050 +{ 1.1051 + CK_MECHANISM mech = {CKM_RSA_X_509, NULL, 0 }; 1.1052 + unsigned int outLen; 1.1053 + if (!key || key->keyType != rsaKey) { 1.1054 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.1055 + return SECFailure; 1.1056 + } 1.1057 + outLen = SECKEY_PublicKeyStrength(key); 1.1058 + return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech, 1.1059 + wincx); 1.1060 +} 1.1061 + 1.1062 +SECStatus 1.1063 +PK11_PubEncryptPKCS1(SECKEYPublicKey *key, 1.1064 + unsigned char *enc, 1.1065 + const unsigned char *data, unsigned dataLen, 1.1066 + void *wincx) 1.1067 +{ 1.1068 + CK_MECHANISM mech = {CKM_RSA_PKCS, NULL, 0 }; 1.1069 + unsigned int outLen; 1.1070 + if (!key || key->keyType != rsaKey) { 1.1071 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.1072 + return SECFailure; 1.1073 + } 1.1074 + outLen = SECKEY_PublicKeyStrength(key); 1.1075 + return pk11_PubEncryptRaw(key, enc, &outLen, outLen, data, dataLen, &mech, 1.1076 + wincx); 1.1077 +} 1.1078 + 1.1079 +SECStatus 1.1080 +PK11_PrivDecrypt(SECKEYPrivateKey *key, 1.1081 + CK_MECHANISM_TYPE mechanism, SECItem *param, 1.1082 + unsigned char *out, unsigned int *outLen, 1.1083 + unsigned int maxLen, 1.1084 + const unsigned char *enc, unsigned encLen) 1.1085 +{ 1.1086 + CK_MECHANISM mech = { mechanism, NULL, 0 }; 1.1087 + if (param) { 1.1088 + mech.pParameter = param->data; 1.1089 + mech.ulParameterLen = param->len; 1.1090 + } 1.1091 + return pk11_PrivDecryptRaw(key, out, outLen, maxLen, enc, encLen, &mech); 1.1092 +} 1.1093 + 1.1094 +SECStatus 1.1095 +PK11_PubEncrypt(SECKEYPublicKey *key, 1.1096 + CK_MECHANISM_TYPE mechanism, SECItem *param, 1.1097 + unsigned char *out, unsigned int *outLen, 1.1098 + unsigned int maxLen, 1.1099 + const unsigned char *data, unsigned dataLen, 1.1100 + void *wincx) 1.1101 +{ 1.1102 + CK_MECHANISM mech = { mechanism, NULL, 0 }; 1.1103 + if (param) { 1.1104 + mech.pParameter = param->data; 1.1105 + mech.ulParameterLen = param->len; 1.1106 + } 1.1107 + return pk11_PubEncryptRaw(key, out, outLen, maxLen, data, dataLen, &mech, 1.1108 + wincx); 1.1109 +} 1.1110 + 1.1111 +SECKEYPrivateKey * 1.1112 +PK11_UnwrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey, 1.1113 + CK_MECHANISM_TYPE wrapType, SECItem *param, 1.1114 + SECItem *wrappedKey, SECItem *label, 1.1115 + SECItem *idValue, PRBool perm, PRBool sensitive, 1.1116 + CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage, 1.1117 + int usageCount, void *wincx) 1.1118 +{ 1.1119 + CK_BBOOL cktrue = CK_TRUE; 1.1120 + CK_BBOOL ckfalse = CK_FALSE; 1.1121 + CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; 1.1122 + CK_ATTRIBUTE keyTemplate[15] ; 1.1123 + int templateCount = 0; 1.1124 + CK_OBJECT_HANDLE privKeyID; 1.1125 + CK_MECHANISM mechanism; 1.1126 + CK_ATTRIBUTE *attrs = keyTemplate; 1.1127 + SECItem *param_free = NULL, *ck_id = NULL; 1.1128 + CK_RV crv; 1.1129 + CK_SESSION_HANDLE rwsession; 1.1130 + PK11SymKey *newKey = NULL; 1.1131 + int i; 1.1132 + 1.1133 + if(!slot || !wrappedKey || !idValue) { 1.1134 + /* SET AN ERROR!!! */ 1.1135 + return NULL; 1.1136 + } 1.1137 + 1.1138 + ck_id = PK11_MakeIDFromPubKey(idValue); 1.1139 + if(!ck_id) { 1.1140 + return NULL; 1.1141 + } 1.1142 + 1.1143 + PK11_SETATTRS(attrs, CKA_TOKEN, perm ? &cktrue : &ckfalse, 1.1144 + sizeof(cktrue)); attrs++; 1.1145 + PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass)); attrs++; 1.1146 + PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType)); attrs++; 1.1147 + PK11_SETATTRS(attrs, CKA_PRIVATE, sensitive ? &cktrue : &ckfalse, 1.1148 + sizeof(cktrue)); attrs++; 1.1149 + PK11_SETATTRS(attrs, CKA_SENSITIVE, sensitive ? &cktrue : &ckfalse, 1.1150 + sizeof(cktrue)); attrs++; 1.1151 + if (label && label->data) { 1.1152 + PK11_SETATTRS(attrs, CKA_LABEL, label->data, label->len); attrs++; 1.1153 + } 1.1154 + PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len); attrs++; 1.1155 + for (i=0; i < usageCount; i++) { 1.1156 + PK11_SETATTRS(attrs, usage[i], &cktrue, sizeof(cktrue)); attrs++; 1.1157 + } 1.1158 + 1.1159 + if (PK11_IsInternal(slot)) { 1.1160 + PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, idValue->data, 1.1161 + idValue->len); attrs++; 1.1162 + } 1.1163 + 1.1164 + templateCount = attrs - keyTemplate; 1.1165 + PR_ASSERT(templateCount <= (sizeof(keyTemplate) / sizeof(CK_ATTRIBUTE)) ); 1.1166 + 1.1167 + mechanism.mechanism = wrapType; 1.1168 + if(!param) param = param_free= PK11_ParamFromIV(wrapType, NULL); 1.1169 + if(param) { 1.1170 + mechanism.pParameter = param->data; 1.1171 + mechanism.ulParameterLen = param->len; 1.1172 + } else { 1.1173 + mechanism.pParameter = NULL; 1.1174 + mechanism.ulParameterLen = 0; 1.1175 + } 1.1176 + 1.1177 + if (wrappingKey->slot != slot) { 1.1178 + newKey = pk11_CopyToSlot(slot,wrapType,CKA_UNWRAP,wrappingKey); 1.1179 + } else { 1.1180 + newKey = PK11_ReferenceSymKey(wrappingKey); 1.1181 + } 1.1182 + 1.1183 + if (newKey) { 1.1184 + if (perm) { 1.1185 + /* Get RW Session will either lock the monitor if necessary, 1.1186 + * or return a thread safe session handle, or fail. */ 1.1187 + rwsession = PK11_GetRWSession(slot); 1.1188 + } else { 1.1189 + rwsession = slot->session; 1.1190 + if (rwsession != CK_INVALID_SESSION) 1.1191 + PK11_EnterSlotMonitor(slot); 1.1192 + } 1.1193 + /* This is a lot a work to deal with fussy PKCS #11 modules 1.1194 + * that can't bother to return BAD_DATA when presented with an 1.1195 + * invalid session! */ 1.1196 + if (rwsession == CK_INVALID_SESSION) { 1.1197 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.1198 + goto loser; 1.1199 + } 1.1200 + crv = PK11_GETTAB(slot)->C_UnwrapKey(rwsession, &mechanism, 1.1201 + newKey->objectID, 1.1202 + wrappedKey->data, 1.1203 + wrappedKey->len, keyTemplate, 1.1204 + templateCount, &privKeyID); 1.1205 + 1.1206 + if (perm) { 1.1207 + PK11_RestoreROSession(slot, rwsession); 1.1208 + } else { 1.1209 + PK11_ExitSlotMonitor(slot); 1.1210 + } 1.1211 + PK11_FreeSymKey(newKey); 1.1212 + newKey = NULL; 1.1213 + } else { 1.1214 + crv = CKR_FUNCTION_NOT_SUPPORTED; 1.1215 + } 1.1216 + 1.1217 + if (ck_id) { 1.1218 + SECITEM_FreeItem(ck_id, PR_TRUE); 1.1219 + ck_id = NULL; 1.1220 + } 1.1221 + 1.1222 + if (crv != CKR_OK) { 1.1223 + /* we couldn't unwrap the key, use the internal module to do the 1.1224 + * unwrap, then load the new key into the token */ 1.1225 + PK11SlotInfo *int_slot = PK11_GetInternalSlot(); 1.1226 + 1.1227 + if (int_slot && (slot != int_slot)) { 1.1228 + SECKEYPrivateKey *privKey = PK11_UnwrapPrivKey(int_slot, 1.1229 + wrappingKey, wrapType, param, wrappedKey, label, 1.1230 + idValue, PR_FALSE, PR_FALSE, 1.1231 + keyType, usage, usageCount, wincx); 1.1232 + if (privKey) { 1.1233 + SECKEYPrivateKey *newPrivKey = PK11_LoadPrivKey(slot,privKey, 1.1234 + NULL,perm,sensitive); 1.1235 + SECKEY_DestroyPrivateKey(privKey); 1.1236 + PK11_FreeSlot(int_slot); 1.1237 + return newPrivKey; 1.1238 + } 1.1239 + } 1.1240 + if (int_slot) PK11_FreeSlot(int_slot); 1.1241 + PORT_SetError( PK11_MapError(crv) ); 1.1242 + return NULL; 1.1243 + } 1.1244 + return PK11_MakePrivKey(slot, nullKey, PR_FALSE, privKeyID, wincx); 1.1245 + 1.1246 +loser: 1.1247 + if (newKey) { 1.1248 + PK11_FreeSymKey(newKey); 1.1249 + } 1.1250 + if (ck_id) { 1.1251 + SECITEM_FreeItem(ck_id, PR_TRUE); 1.1252 + } 1.1253 + return NULL; 1.1254 +} 1.1255 + 1.1256 +/* 1.1257 + * Now we're going to wrap a SECKEYPrivateKey with a PK11SymKey 1.1258 + * The strategy is to get both keys to reside in the same slot, 1.1259 + * one that can perform the desired crypto mechanism and then 1.1260 + * call C_WrapKey after all the setup has taken place. 1.1261 + */ 1.1262 +SECStatus 1.1263 +PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey, 1.1264 + SECKEYPrivateKey *privKey, CK_MECHANISM_TYPE wrapType, 1.1265 + SECItem *param, SECItem *wrappedKey, void *wincx) 1.1266 +{ 1.1267 + PK11SlotInfo *privSlot = privKey->pkcs11Slot; /* The slot where 1.1268 + * the private key 1.1269 + * we are going to 1.1270 + * wrap lives. 1.1271 + */ 1.1272 + PK11SymKey *newSymKey = NULL; 1.1273 + SECKEYPrivateKey *newPrivKey = NULL; 1.1274 + SECItem *param_free = NULL; 1.1275 + CK_ULONG len = wrappedKey->len; 1.1276 + CK_MECHANISM mech; 1.1277 + CK_RV crv; 1.1278 + 1.1279 + if (!privSlot || !PK11_DoesMechanism(privSlot, wrapType)) { 1.1280 + /* Figure out a slot that does the mechanism and try to import 1.1281 + * the private key onto that slot. 1.1282 + */ 1.1283 + PK11SlotInfo *int_slot = PK11_GetInternalSlot(); 1.1284 + 1.1285 + privSlot = int_slot; /* The private key has a new home */ 1.1286 + newPrivKey = PK11_LoadPrivKey(privSlot,privKey,NULL,PR_FALSE,PR_FALSE); 1.1287 + /* newPrivKey has allocated its own reference to the slot, so it's 1.1288 + * safe until we destroy newPrivkey. 1.1289 + */ 1.1290 + PK11_FreeSlot(int_slot); 1.1291 + if (newPrivKey == NULL) { 1.1292 + return SECFailure; 1.1293 + } 1.1294 + privKey = newPrivKey; 1.1295 + } 1.1296 + 1.1297 + if (privSlot != wrappingKey->slot) { 1.1298 + newSymKey = pk11_CopyToSlot (privSlot, wrapType, CKA_WRAP, 1.1299 + wrappingKey); 1.1300 + wrappingKey = newSymKey; 1.1301 + } 1.1302 + 1.1303 + if (wrappingKey == NULL) { 1.1304 + if (newPrivKey) { 1.1305 + SECKEY_DestroyPrivateKey(newPrivKey); 1.1306 + } 1.1307 + return SECFailure; 1.1308 + } 1.1309 + mech.mechanism = wrapType; 1.1310 + if (!param) { 1.1311 + param = param_free = PK11_ParamFromIV(wrapType, NULL); 1.1312 + } 1.1313 + if (param) { 1.1314 + mech.pParameter = param->data; 1.1315 + mech.ulParameterLen = param->len; 1.1316 + } else { 1.1317 + mech.pParameter = NULL; 1.1318 + mech.ulParameterLen = 0; 1.1319 + } 1.1320 + 1.1321 + PK11_EnterSlotMonitor(privSlot); 1.1322 + crv = PK11_GETTAB(privSlot)->C_WrapKey(privSlot->session, &mech, 1.1323 + wrappingKey->objectID, 1.1324 + privKey->pkcs11ID, 1.1325 + wrappedKey->data, &len); 1.1326 + PK11_ExitSlotMonitor(privSlot); 1.1327 + 1.1328 + if (newSymKey) { 1.1329 + PK11_FreeSymKey(newSymKey); 1.1330 + } 1.1331 + if (newPrivKey) { 1.1332 + SECKEY_DestroyPrivateKey(newPrivKey); 1.1333 + } 1.1334 + if (param_free) { 1.1335 + SECITEM_FreeItem(param_free,PR_TRUE); 1.1336 + } 1.1337 + 1.1338 + if (crv != CKR_OK) { 1.1339 + PORT_SetError( PK11_MapError(crv) ); 1.1340 + return SECFailure; 1.1341 + } 1.1342 + 1.1343 + wrappedKey->len = len; 1.1344 + return SECSuccess; 1.1345 +} 1.1346 + 1.1347 +#if 0 1.1348 +/* 1.1349 + * Sample code relating to linked list returned by PK11_FindGenericObjects 1.1350 + */ 1.1351 + 1.1352 +/* 1.1353 + * You can walk the list with the following code: 1.1354 + */ 1.1355 + firstObj = PK11_FindGenericObjects(slot, objClass); 1.1356 + for (thisObj=firstObj; 1.1357 + thisObj; 1.1358 + thisObj=PK11_GetNextGenericObject(thisObj)) { 1.1359 + /* operate on thisObj */ 1.1360 + } 1.1361 +/* 1.1362 + * If you want a particular object from the list... 1.1363 + */ 1.1364 + firstObj = PK11_FindGenericObjects(slot, objClass); 1.1365 + for (thisObj=firstObj; 1.1366 + thisObj; 1.1367 + thisObj=PK11_GetNextGenericObject(thisObj)) { 1.1368 + if (isMyObj(thisObj)) { 1.1369 + if ( thisObj == firstObj) { 1.1370 + /* NOTE: firstObj could be NULL at this point */ 1.1371 + firstObj = PK11_GetNextGenericObject(thsObj); 1.1372 + } 1.1373 + PK11_UnlinkGenericObject(thisObj); 1.1374 + myObj = thisObj; 1.1375 + break; 1.1376 + } 1.1377 + } 1.1378 + 1.1379 + PK11_DestroyGenericObjects(firstObj); 1.1380 + 1.1381 + /* use myObj */ 1.1382 + 1.1383 + PK11_DestroyGenericObject(myObj); 1.1384 +#endif /* sample code */ 1.1385 + 1.1386 +/* 1.1387 + * return a linked, non-circular list of generic objects. 1.1388 + * If you are only interested 1.1389 + * in one object, just use the first object in the list. To find the 1.1390 + * rest of the list use PK11_GetNextGenericObject() to return the next object. 1.1391 + */ 1.1392 +PK11GenericObject * 1.1393 +PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass) 1.1394 +{ 1.1395 + CK_ATTRIBUTE template[1]; 1.1396 + CK_ATTRIBUTE *attrs = template; 1.1397 + CK_OBJECT_HANDLE *objectIDs = NULL; 1.1398 + PK11GenericObject *lastObj = NULL, *obj; 1.1399 + PK11GenericObject *firstObj = NULL; 1.1400 + int i, count = 0; 1.1401 + 1.1402 + 1.1403 + PK11_SETATTRS(attrs, CKA_CLASS, &objClass, sizeof(objClass)); attrs++; 1.1404 + 1.1405 + objectIDs = pk11_FindObjectsByTemplate(slot,template,1,&count); 1.1406 + if (objectIDs == NULL) { 1.1407 + return NULL; 1.1408 + } 1.1409 + 1.1410 + /* where we connect our object once we've created it.. */ 1.1411 + for (i=0; i < count; i++) { 1.1412 + obj = PORT_New(PK11GenericObject); 1.1413 + if ( !obj ) { 1.1414 + if (firstObj) { 1.1415 + PK11_DestroyGenericObjects(firstObj); 1.1416 + } 1.1417 + PORT_Free(objectIDs); 1.1418 + return NULL; 1.1419 + } 1.1420 + /* initialize it */ 1.1421 + obj->slot = PK11_ReferenceSlot(slot); 1.1422 + obj->objectID = objectIDs[i]; 1.1423 + obj->next = NULL; 1.1424 + obj->prev = NULL; 1.1425 + 1.1426 + /* link it in */ 1.1427 + if (firstObj == NULL) { 1.1428 + firstObj = obj; 1.1429 + } else { 1.1430 + PK11_LinkGenericObject(lastObj, obj); 1.1431 + } 1.1432 + lastObj = obj; 1.1433 + } 1.1434 + PORT_Free(objectIDs); 1.1435 + return firstObj; 1.1436 +} 1.1437 + 1.1438 +/* 1.1439 + * get the Next Object in the list. 1.1440 + */ 1.1441 +PK11GenericObject * 1.1442 +PK11_GetNextGenericObject(PK11GenericObject *object) 1.1443 +{ 1.1444 + return object->next; 1.1445 +} 1.1446 + 1.1447 +PK11GenericObject * 1.1448 +PK11_GetPrevGenericObject(PK11GenericObject *object) 1.1449 +{ 1.1450 + return object->prev; 1.1451 +} 1.1452 + 1.1453 +/* 1.1454 + * Link a single object into a new list. 1.1455 + * if the object is already in another list, remove it first. 1.1456 + */ 1.1457 +SECStatus 1.1458 +PK11_LinkGenericObject(PK11GenericObject *list, PK11GenericObject *object) 1.1459 +{ 1.1460 + PK11_UnlinkGenericObject(object); 1.1461 + object->prev = list; 1.1462 + object->next = list->next; 1.1463 + list->next = object; 1.1464 + if (object->next != NULL) { 1.1465 + object->next->prev = object; 1.1466 + } 1.1467 + return SECSuccess; 1.1468 +} 1.1469 + 1.1470 +/* 1.1471 + * remove an object from the list. If the object isn't already in 1.1472 + * a list unlink becomes a noop. 1.1473 + */ 1.1474 +SECStatus 1.1475 +PK11_UnlinkGenericObject(PK11GenericObject *object) 1.1476 +{ 1.1477 + if (object->prev != NULL) { 1.1478 + object->prev->next = object->next; 1.1479 + } 1.1480 + if (object->next != NULL) { 1.1481 + object->next->prev = object->prev; 1.1482 + } 1.1483 + 1.1484 + object->next = NULL; 1.1485 + object->prev = NULL; 1.1486 + return SECSuccess; 1.1487 +} 1.1488 + 1.1489 +/* 1.1490 + * This function removes a single object from the list and destroys it. 1.1491 + * For an already unlinked object there is no difference between 1.1492 + * PK11_DestroyGenericObject and PK11_DestroyGenericObjects 1.1493 + */ 1.1494 +SECStatus 1.1495 +PK11_DestroyGenericObject(PK11GenericObject *object) 1.1496 +{ 1.1497 + if (object == NULL) { 1.1498 + return SECSuccess; 1.1499 + } 1.1500 + 1.1501 + PK11_UnlinkGenericObject(object); 1.1502 + if (object->slot) { 1.1503 + PK11_FreeSlot(object->slot); 1.1504 + } 1.1505 + PORT_Free(object); 1.1506 + return SECSuccess; 1.1507 +} 1.1508 + 1.1509 +/* 1.1510 + * walk down a link list of generic objects destroying them. 1.1511 + * This will destroy all objects in a list that the object is linked into. 1.1512 + * (the list is traversed in both directions). 1.1513 + */ 1.1514 +SECStatus 1.1515 +PK11_DestroyGenericObjects(PK11GenericObject *objects) 1.1516 +{ 1.1517 + PK11GenericObject *nextObject; 1.1518 + PK11GenericObject *prevObject; 1.1519 + 1.1520 + if (objects == NULL) { 1.1521 + return SECSuccess; 1.1522 + } 1.1523 + 1.1524 + nextObject = objects->next; 1.1525 + prevObject = objects->prev; 1.1526 + 1.1527 + /* delete all the objects after it in the list */ 1.1528 + for (; objects; objects = nextObject) { 1.1529 + nextObject = objects->next; 1.1530 + PK11_DestroyGenericObject(objects); 1.1531 + } 1.1532 + /* delete all the objects before it in the list */ 1.1533 + for (objects = prevObject; objects; objects = prevObject) { 1.1534 + prevObject = objects->prev; 1.1535 + PK11_DestroyGenericObject(objects); 1.1536 + } 1.1537 + return SECSuccess; 1.1538 +} 1.1539 + 1.1540 + 1.1541 +/* 1.1542 + * Hand Create a new object and return the Generic object for our new object. 1.1543 + */ 1.1544 +PK11GenericObject * 1.1545 +PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate, 1.1546 + int count, PRBool token) 1.1547 +{ 1.1548 + CK_OBJECT_HANDLE objectID; 1.1549 + PK11GenericObject *obj; 1.1550 + CK_RV crv; 1.1551 + 1.1552 + PK11_EnterSlotMonitor(slot); 1.1553 + crv = PK11_CreateNewObject(slot, slot->session, pTemplate, count, 1.1554 + token, &objectID); 1.1555 + PK11_ExitSlotMonitor(slot); 1.1556 + if (crv != CKR_OK) { 1.1557 + PORT_SetError(PK11_MapError(crv)); 1.1558 + return NULL; 1.1559 + } 1.1560 + 1.1561 + obj = PORT_New(PK11GenericObject); 1.1562 + if ( !obj ) { 1.1563 + /* error set by PORT_New */ 1.1564 + return NULL; 1.1565 + } 1.1566 + 1.1567 + /* initialize it */ 1.1568 + obj->slot = PK11_ReferenceSlot(slot); 1.1569 + obj->objectID = objectID; 1.1570 + obj->next = NULL; 1.1571 + obj->prev = NULL; 1.1572 + return obj; 1.1573 +} 1.1574 + 1.1575 +/* 1.1576 + * Change an attribute on a raw object 1.1577 + */ 1.1578 +SECStatus 1.1579 +PK11_WriteRawAttribute(PK11ObjectType objType, void *objSpec, 1.1580 + CK_ATTRIBUTE_TYPE attrType, SECItem *item) 1.1581 +{ 1.1582 + PK11SlotInfo *slot = NULL; 1.1583 + CK_OBJECT_HANDLE handle; 1.1584 + CK_ATTRIBUTE setTemplate; 1.1585 + CK_RV crv; 1.1586 + CK_SESSION_HANDLE rwsession; 1.1587 + 1.1588 + switch (objType) { 1.1589 + case PK11_TypeGeneric: 1.1590 + slot = ((PK11GenericObject *)objSpec)->slot; 1.1591 + handle = ((PK11GenericObject *)objSpec)->objectID; 1.1592 + break; 1.1593 + case PK11_TypePrivKey: 1.1594 + slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot; 1.1595 + handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID; 1.1596 + break; 1.1597 + case PK11_TypePubKey: 1.1598 + slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot; 1.1599 + handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID; 1.1600 + break; 1.1601 + case PK11_TypeSymKey: 1.1602 + slot = ((PK11SymKey *)objSpec)->slot; 1.1603 + handle = ((PK11SymKey *)objSpec)->objectID; 1.1604 + break; 1.1605 + case PK11_TypeCert: /* don't handle cert case for now */ 1.1606 + default: 1.1607 + break; 1.1608 + } 1.1609 + if (slot == NULL) { 1.1610 + PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE); 1.1611 + return SECFailure; 1.1612 + } 1.1613 + 1.1614 + PK11_SETATTRS(&setTemplate, attrType, (CK_CHAR *) item->data, item->len); 1.1615 + rwsession = PK11_GetRWSession(slot); 1.1616 + if (rwsession == CK_INVALID_SESSION) { 1.1617 + PORT_SetError(SEC_ERROR_BAD_DATA); 1.1618 + return SECFailure; 1.1619 + } 1.1620 + crv = PK11_GETTAB(slot)->C_SetAttributeValue(rwsession, handle, 1.1621 + &setTemplate, 1); 1.1622 + PK11_RestoreROSession(slot, rwsession); 1.1623 + if (crv != CKR_OK) { 1.1624 + PORT_SetError(PK11_MapError(crv)); 1.1625 + return SECFailure; 1.1626 + } 1.1627 + return SECSuccess; 1.1628 +} 1.1629 + 1.1630 + 1.1631 +SECStatus 1.1632 +PK11_ReadRawAttribute(PK11ObjectType objType, void *objSpec, 1.1633 + CK_ATTRIBUTE_TYPE attrType, SECItem *item) 1.1634 +{ 1.1635 + PK11SlotInfo *slot = NULL; 1.1636 + CK_OBJECT_HANDLE handle; 1.1637 + 1.1638 + switch (objType) { 1.1639 + case PK11_TypeGeneric: 1.1640 + slot = ((PK11GenericObject *)objSpec)->slot; 1.1641 + handle = ((PK11GenericObject *)objSpec)->objectID; 1.1642 + break; 1.1643 + case PK11_TypePrivKey: 1.1644 + slot = ((SECKEYPrivateKey *)objSpec)->pkcs11Slot; 1.1645 + handle = ((SECKEYPrivateKey *)objSpec)->pkcs11ID; 1.1646 + break; 1.1647 + case PK11_TypePubKey: 1.1648 + slot = ((SECKEYPublicKey *)objSpec)->pkcs11Slot; 1.1649 + handle = ((SECKEYPublicKey *)objSpec)->pkcs11ID; 1.1650 + break; 1.1651 + case PK11_TypeSymKey: 1.1652 + slot = ((PK11SymKey *)objSpec)->slot; 1.1653 + handle = ((PK11SymKey *)objSpec)->objectID; 1.1654 + break; 1.1655 + case PK11_TypeCert: /* don't handle cert case for now */ 1.1656 + default: 1.1657 + break; 1.1658 + } 1.1659 + if (slot == NULL) { 1.1660 + PORT_SetError(SEC_ERROR_UNKNOWN_OBJECT_TYPE); 1.1661 + return SECFailure; 1.1662 + } 1.1663 + 1.1664 + return PK11_ReadAttribute(slot, handle, attrType, NULL, item); 1.1665 +} 1.1666 + 1.1667 + 1.1668 +/* 1.1669 + * return the object handle that matches the template 1.1670 + */ 1.1671 +CK_OBJECT_HANDLE 1.1672 +pk11_FindObjectByTemplate(PK11SlotInfo *slot,CK_ATTRIBUTE *theTemplate,int tsize) 1.1673 +{ 1.1674 + CK_OBJECT_HANDLE object; 1.1675 + CK_RV crv = CKR_SESSION_HANDLE_INVALID; 1.1676 + CK_ULONG objectCount; 1.1677 + 1.1678 + /* 1.1679 + * issue the find 1.1680 + */ 1.1681 + PK11_EnterSlotMonitor(slot); 1.1682 + if (slot->session != CK_INVALID_SESSION) { 1.1683 + crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, 1.1684 + theTemplate, tsize); 1.1685 + } 1.1686 + if (crv != CKR_OK) { 1.1687 + PK11_ExitSlotMonitor(slot); 1.1688 + PORT_SetError( PK11_MapError(crv) ); 1.1689 + return CK_INVALID_HANDLE; 1.1690 + } 1.1691 + 1.1692 + crv=PK11_GETTAB(slot)->C_FindObjects(slot->session,&object,1,&objectCount); 1.1693 + PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); 1.1694 + PK11_ExitSlotMonitor(slot); 1.1695 + if ((crv != CKR_OK) || (objectCount < 1)) { 1.1696 + /* shouldn't use SSL_ERROR... here */ 1.1697 + PORT_SetError( crv != CKR_OK ? PK11_MapError(crv) : 1.1698 + SSL_ERROR_NO_CERTIFICATE); 1.1699 + return CK_INVALID_HANDLE; 1.1700 + } 1.1701 + 1.1702 + /* blow up if the PKCS #11 module returns us and invalid object handle */ 1.1703 + PORT_Assert(object != CK_INVALID_HANDLE); 1.1704 + return object; 1.1705 +} 1.1706 + 1.1707 +/* 1.1708 + * return all the object handles that matches the template 1.1709 + */ 1.1710 +CK_OBJECT_HANDLE * 1.1711 +pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, 1.1712 + int templCount, int *object_count) 1.1713 +{ 1.1714 + CK_OBJECT_HANDLE *objID = NULL; 1.1715 + CK_ULONG returned_count = 0; 1.1716 + CK_RV crv = CKR_SESSION_HANDLE_INVALID; 1.1717 + 1.1718 + PK11_EnterSlotMonitor(slot); 1.1719 + if (slot->session != CK_INVALID_SESSION) { 1.1720 + crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, 1.1721 + findTemplate, templCount); 1.1722 + } 1.1723 + if (crv != CKR_OK) { 1.1724 + PK11_ExitSlotMonitor(slot); 1.1725 + PORT_SetError( PK11_MapError(crv) ); 1.1726 + *object_count = -1; 1.1727 + return NULL; 1.1728 + } 1.1729 + 1.1730 + 1.1731 + /* 1.1732 + * collect all the Matching Objects 1.1733 + */ 1.1734 + do { 1.1735 + CK_OBJECT_HANDLE *oldObjID = objID; 1.1736 + 1.1737 + if (objID == NULL) { 1.1738 + objID = (CK_OBJECT_HANDLE *) PORT_Alloc(sizeof(CK_OBJECT_HANDLE)* 1.1739 + (*object_count+ PK11_SEARCH_CHUNKSIZE)); 1.1740 + } else { 1.1741 + objID = (CK_OBJECT_HANDLE *) PORT_Realloc(objID, 1.1742 + sizeof(CK_OBJECT_HANDLE)*(*object_count+PK11_SEARCH_CHUNKSIZE)); 1.1743 + } 1.1744 + 1.1745 + if (objID == NULL) { 1.1746 + if (oldObjID) PORT_Free(oldObjID); 1.1747 + break; 1.1748 + } 1.1749 + crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, 1.1750 + &objID[*object_count],PK11_SEARCH_CHUNKSIZE,&returned_count); 1.1751 + if (crv != CKR_OK) { 1.1752 + PORT_SetError( PK11_MapError(crv) ); 1.1753 + PORT_Free(objID); 1.1754 + objID = NULL; 1.1755 + break; 1.1756 + } 1.1757 + *object_count += returned_count; 1.1758 + } while (returned_count == PK11_SEARCH_CHUNKSIZE); 1.1759 + 1.1760 + PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); 1.1761 + PK11_ExitSlotMonitor(slot); 1.1762 + 1.1763 + if (objID && (*object_count == 0)) { 1.1764 + PORT_Free(objID); 1.1765 + return NULL; 1.1766 + } 1.1767 + if (objID == NULL) *object_count = -1; 1.1768 + return objID; 1.1769 +} 1.1770 +/* 1.1771 + * given a PKCS #11 object, match it's peer based on the KeyID. searchID 1.1772 + * is typically a privateKey or a certificate while the peer is the opposite 1.1773 + */ 1.1774 +CK_OBJECT_HANDLE 1.1775 +PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE searchID, 1.1776 + CK_OBJECT_CLASS matchclass) 1.1777 +{ 1.1778 + CK_ATTRIBUTE theTemplate[] = { 1.1779 + { CKA_ID, NULL, 0 }, 1.1780 + { CKA_CLASS, NULL, 0 } 1.1781 + }; 1.1782 + /* if you change the array, change the variable below as well */ 1.1783 + CK_ATTRIBUTE *keyclass = &theTemplate[1]; 1.1784 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.1785 + /* if you change the array, change the variable below as well */ 1.1786 + CK_OBJECT_HANDLE peerID; 1.1787 + CK_OBJECT_HANDLE parent; 1.1788 + PLArenaPool *arena; 1.1789 + CK_RV crv; 1.1790 + 1.1791 + /* now we need to create space for the public key */ 1.1792 + arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); 1.1793 + if (arena == NULL) return CK_INVALID_HANDLE; 1.1794 + 1.1795 + crv = PK11_GetAttributes(arena,slot,searchID,theTemplate,tsize); 1.1796 + if (crv != CKR_OK) { 1.1797 + PORT_FreeArena(arena,PR_FALSE); 1.1798 + PORT_SetError( PK11_MapError(crv) ); 1.1799 + return CK_INVALID_HANDLE; 1.1800 + } 1.1801 + 1.1802 + if ((theTemplate[0].ulValueLen == 0) || (theTemplate[0].ulValueLen == -1)) { 1.1803 + PORT_FreeArena(arena,PR_FALSE); 1.1804 + if (matchclass == CKO_CERTIFICATE) 1.1805 + PORT_SetError(SEC_ERROR_BAD_KEY); 1.1806 + else 1.1807 + PORT_SetError(SEC_ERROR_NO_KEY); 1.1808 + return CK_INVALID_HANDLE; 1.1809 + } 1.1810 + 1.1811 + 1.1812 + 1.1813 + /* 1.1814 + * issue the find 1.1815 + */ 1.1816 + parent = *(CK_OBJECT_CLASS *)(keyclass->pValue); 1.1817 + *(CK_OBJECT_CLASS *)(keyclass->pValue) = matchclass; 1.1818 + 1.1819 + peerID = pk11_FindObjectByTemplate(slot,theTemplate,tsize); 1.1820 + PORT_FreeArena(arena,PR_FALSE); 1.1821 + 1.1822 + return peerID; 1.1823 +} 1.1824 + 1.1825 +/* 1.1826 + * count the number of objects that match the template. 1.1827 + */ 1.1828 +int 1.1829 +PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate, 1.1830 + int templCount) 1.1831 +{ 1.1832 + CK_OBJECT_HANDLE objID[PK11_SEARCH_CHUNKSIZE]; 1.1833 + int object_count = 0; 1.1834 + CK_ULONG returned_count = 0; 1.1835 + CK_RV crv = CKR_SESSION_HANDLE_INVALID; 1.1836 + 1.1837 + PK11_EnterSlotMonitor(slot); 1.1838 + if (slot->session != CK_INVALID_SESSION) { 1.1839 + crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session, 1.1840 + findTemplate, templCount); 1.1841 + } 1.1842 + if (crv != CKR_OK) { 1.1843 + PK11_ExitSlotMonitor(slot); 1.1844 + PORT_SetError( PK11_MapError(crv) ); 1.1845 + return object_count; 1.1846 + } 1.1847 + 1.1848 + /* 1.1849 + * collect all the Matching Objects 1.1850 + */ 1.1851 + do { 1.1852 + crv = PK11_GETTAB(slot)->C_FindObjects(slot->session, objID, 1.1853 + PK11_SEARCH_CHUNKSIZE, 1.1854 + &returned_count); 1.1855 + if (crv != CKR_OK) { 1.1856 + PORT_SetError( PK11_MapError(crv) ); 1.1857 + break; 1.1858 + } 1.1859 + object_count += returned_count; 1.1860 + } while (returned_count == PK11_SEARCH_CHUNKSIZE); 1.1861 + 1.1862 + PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session); 1.1863 + PK11_ExitSlotMonitor(slot); 1.1864 + return object_count; 1.1865 +} 1.1866 + 1.1867 +/* 1.1868 + * Traverse all the objects in a given slot. 1.1869 + */ 1.1870 +SECStatus 1.1871 +PK11_TraverseSlot(PK11SlotInfo *slot, void *arg) 1.1872 +{ 1.1873 + int i; 1.1874 + CK_OBJECT_HANDLE *objID = NULL; 1.1875 + int object_count = 0; 1.1876 + pk11TraverseSlot *slotcb = (pk11TraverseSlot*) arg; 1.1877 + 1.1878 + objID = pk11_FindObjectsByTemplate(slot,slotcb->findTemplate, 1.1879 + slotcb->templateCount,&object_count); 1.1880 + 1.1881 + /*Actually this isn't a failure... there just were no objs to be found*/ 1.1882 + if (object_count == 0) { 1.1883 + return SECSuccess; 1.1884 + } 1.1885 + 1.1886 + if (objID == NULL) { 1.1887 + return SECFailure; 1.1888 + } 1.1889 + 1.1890 + for (i=0; i < object_count; i++) { 1.1891 + (*slotcb->callback)(slot,objID[i],slotcb->callbackArg); 1.1892 + } 1.1893 + PORT_Free(objID); 1.1894 + return SECSuccess; 1.1895 +} 1.1896 + 1.1897 +/* 1.1898 + * Traverse all the objects in all slots. 1.1899 + */ 1.1900 +SECStatus 1.1901 +pk11_TraverseAllSlots( SECStatus (*callback)(PK11SlotInfo *,void *), 1.1902 + void *arg, PRBool forceLogin, void *wincx) { 1.1903 + PK11SlotList *list; 1.1904 + PK11SlotListElement *le; 1.1905 + SECStatus rv; 1.1906 + 1.1907 + /* get them all! */ 1.1908 + list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,wincx); 1.1909 + if (list == NULL) return SECFailure; 1.1910 + 1.1911 + /* look at each slot and authenticate as necessary */ 1.1912 + for (le = list->head ; le; le = le->next) { 1.1913 + if (forceLogin) { 1.1914 + rv = pk11_AuthenticateUnfriendly(le->slot, PR_FALSE, wincx); 1.1915 + if (rv != SECSuccess) { 1.1916 + continue; 1.1917 + } 1.1918 + } 1.1919 + if (callback) { 1.1920 + (*callback)(le->slot,arg); 1.1921 + } 1.1922 + } 1.1923 + 1.1924 + PK11_FreeSlotList(list); 1.1925 + 1.1926 + return SECSuccess; 1.1927 +} 1.1928 + 1.1929 +CK_OBJECT_HANDLE * 1.1930 +PK11_FindObjectsFromNickname(char *nickname,PK11SlotInfo **slotptr, 1.1931 + CK_OBJECT_CLASS objclass, int *returnCount, void *wincx) 1.1932 +{ 1.1933 + char *tokenName; 1.1934 + char *delimit; 1.1935 + PK11SlotInfo *slot; 1.1936 + CK_OBJECT_HANDLE *objID; 1.1937 + CK_ATTRIBUTE findTemplate[] = { 1.1938 + { CKA_LABEL, NULL, 0}, 1.1939 + { CKA_CLASS, NULL, 0}, 1.1940 + }; 1.1941 + int findCount = sizeof(findTemplate)/sizeof(findTemplate[0]); 1.1942 + SECStatus rv; 1.1943 + PK11_SETATTRS(&findTemplate[1], CKA_CLASS, &objclass, sizeof(objclass)); 1.1944 + 1.1945 + *slotptr = slot = NULL; 1.1946 + *returnCount = 0; 1.1947 + /* first find the slot associated with this nickname */ 1.1948 + if ((delimit = PORT_Strchr(nickname,':')) != NULL) { 1.1949 + int len = delimit - nickname; 1.1950 + tokenName = (char*)PORT_Alloc(len+1); 1.1951 + PORT_Memcpy(tokenName,nickname,len); 1.1952 + tokenName[len] = 0; 1.1953 + 1.1954 + slot = *slotptr = PK11_FindSlotByName(tokenName); 1.1955 + PORT_Free(tokenName); 1.1956 + /* if we couldn't find a slot, assume the nickname is an internal cert 1.1957 + * with no proceding slot name */ 1.1958 + if (slot == NULL) { 1.1959 + slot = *slotptr = PK11_GetInternalKeySlot(); 1.1960 + } else { 1.1961 + nickname = delimit+1; 1.1962 + } 1.1963 + } else { 1.1964 + *slotptr = slot = PK11_GetInternalKeySlot(); 1.1965 + } 1.1966 + if (slot == NULL) { 1.1967 + return CK_INVALID_HANDLE; 1.1968 + } 1.1969 + 1.1970 + rv = pk11_AuthenticateUnfriendly(slot, PR_TRUE, wincx); 1.1971 + if (rv != SECSuccess) { 1.1972 + PK11_FreeSlot(slot); 1.1973 + *slotptr = NULL; 1.1974 + return CK_INVALID_HANDLE; 1.1975 + } 1.1976 + 1.1977 + findTemplate[0].pValue = nickname; 1.1978 + findTemplate[0].ulValueLen = PORT_Strlen(nickname); 1.1979 + objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount,returnCount); 1.1980 + if (objID == NULL) { 1.1981 + /* PKCS #11 isn't clear on whether or not the NULL is 1.1982 + * stored in the template.... try the find again with the 1.1983 + * full null terminated string. */ 1.1984 + findTemplate[0].ulValueLen += 1; 1.1985 + objID = pk11_FindObjectsByTemplate(slot,findTemplate,findCount, 1.1986 + returnCount); 1.1987 + if (objID == NULL) { 1.1988 + /* Well that's the best we can do. It's just not here */ 1.1989 + /* what about faked nicknames? */ 1.1990 + PK11_FreeSlot(slot); 1.1991 + *slotptr = NULL; 1.1992 + *returnCount = 0; 1.1993 + } 1.1994 + } 1.1995 + 1.1996 + return objID; 1.1997 +} 1.1998 + 1.1999 +SECItem * 1.2000 +pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle) 1.2001 +{ 1.2002 + CK_ATTRIBUTE theTemplate[] = { 1.2003 + { CKA_ID, NULL, 0 }, 1.2004 + }; 1.2005 + int tsize = sizeof(theTemplate)/sizeof(theTemplate[0]); 1.2006 + CK_RV crv; 1.2007 + SECItem *item; 1.2008 + 1.2009 + item = SECITEM_AllocItem(NULL, NULL, 0); 1.2010 + 1.2011 + if (item == NULL) { 1.2012 + return NULL; 1.2013 + } 1.2014 + 1.2015 + crv = PK11_GetAttributes(NULL,slot,handle,theTemplate,tsize); 1.2016 + if (crv != CKR_OK) { 1.2017 + SECITEM_FreeItem(item,PR_TRUE); 1.2018 + PORT_SetError( PK11_MapError(crv) ); 1.2019 + return NULL; 1.2020 + } 1.2021 + 1.2022 + item->data = (unsigned char*) theTemplate[0].pValue; 1.2023 + item->len =theTemplate[0].ulValueLen; 1.2024 + 1.2025 + return item; 1.2026 +} 1.2027 +