lgattr.c (61837B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * Internal PKCS #11 functions. Should only be called by pkcs11.c 6 */ 7 #include "pkcs11.h" 8 #include "lgdb.h" 9 10 #include "pcertt.h" 11 #include "lowkeyi.h" 12 #include "pcert.h" 13 #include "blapi.h" 14 #include "secerr.h" 15 #include "secasn1.h" 16 17 /* 18 * Cache the object we are working on during Set's and Get's 19 */ 20 typedef struct LGObjectCacheStr { 21 CK_OBJECT_CLASS objclass; 22 CK_OBJECT_HANDLE handle; 23 SDB *sdb; 24 void *objectInfo; 25 LGFreeFunc infoFree; 26 SECItem dbKey; 27 } LGObjectCache; 28 29 static const CK_OBJECT_HANDLE lg_classArray[] = { 30 CKO_TRUST, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY, 31 CKO_NSS_TRUST, CKO_NSS_CRL, CKO_NSS_SMIME, 32 CKO_CERTIFICATE 33 }; 34 35 #define handleToClass(handle) \ 36 lg_classArray[((handle & LG_TOKEN_TYPE_MASK)) >> LG_TOKEN_TYPE_SHIFT] 37 38 static void lg_DestroyObjectCache(LGObjectCache *obj); 39 40 static LGObjectCache * 41 lg_NewObjectCache(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE handle) 42 { 43 LGObjectCache *obj = NULL; 44 SECStatus rv; 45 46 obj = PORT_New(LGObjectCache); 47 if (obj == NULL) { 48 return NULL; 49 } 50 51 obj->objclass = handleToClass(handle); 52 obj->handle = handle; 53 obj->sdb = sdb; 54 obj->objectInfo = NULL; 55 obj->infoFree = NULL; 56 obj->dbKey.data = NULL; 57 obj->dbKey.len = 0; 58 lg_DBLock(sdb); 59 if (dbKey == NULL) { 60 dbKey = lg_lookupTokenKeyByHandle(sdb, handle); 61 } 62 if (dbKey == NULL) { 63 lg_DBUnlock(sdb); 64 goto loser; 65 } 66 rv = SECITEM_CopyItem(NULL, &obj->dbKey, dbKey); 67 lg_DBUnlock(sdb); 68 if (rv != SECSuccess) { 69 goto loser; 70 } 71 72 return obj; 73 loser: 74 (void)lg_DestroyObjectCache(obj); 75 return NULL; 76 } 77 78 /* 79 * free all the data associated with an object. Object reference count must 80 * be 'zero'. 81 */ 82 static void 83 lg_DestroyObjectCache(LGObjectCache *obj) 84 { 85 if (obj->dbKey.data) { 86 PORT_Free(obj->dbKey.data); 87 obj->dbKey.data = NULL; 88 } 89 if (obj->objectInfo) { 90 (*obj->infoFree)(obj->objectInfo); 91 obj->objectInfo = NULL; 92 obj->infoFree = NULL; 93 } 94 PORT_Free(obj); 95 } 96 /* 97 * ******************** Attribute Utilities ******************************* 98 */ 99 100 static CK_RV 101 lg_ULongAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, CK_ULONG value) 102 { 103 unsigned char *data; 104 int i; 105 106 if (attr->pValue == NULL) { 107 attr->ulValueLen = 4; 108 return CKR_OK; 109 } 110 if (attr->ulValueLen < 4) { 111 attr->ulValueLen = (CK_ULONG)-1; 112 return CKR_BUFFER_TOO_SMALL; 113 } 114 115 data = (unsigned char *)attr->pValue; 116 for (i = 0; i < 4; i++) { 117 data[i] = (value >> ((3 - i) * 8)) & 0xff; 118 } 119 attr->ulValueLen = 4; 120 return CKR_OK; 121 } 122 123 static CK_RV 124 lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, 125 CK_VOID_PTR value, CK_ULONG len) 126 { 127 128 if (attr->pValue == NULL) { 129 attr->ulValueLen = len; 130 return CKR_OK; 131 } 132 if (attr->ulValueLen < len) { 133 attr->ulValueLen = (CK_ULONG)-1; 134 return CKR_BUFFER_TOO_SMALL; 135 } 136 if (len > 0 && value != NULL) { 137 PORT_Memcpy(attr->pValue, value, len); 138 } 139 attr->ulValueLen = len; 140 return CKR_OK; 141 } 142 143 static CK_RV 144 lg_CopyAttributeSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, 145 void *value, CK_ULONG len) 146 { 147 unsigned char *dval = (unsigned char *)value; 148 if (*dval == 0) { 149 dval++; 150 len--; 151 } 152 return lg_CopyAttribute(attribute, type, dval, len); 153 } 154 155 static CK_RV 156 lg_CopyPrivAttribute(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, 157 void *value, CK_ULONG len, SDB *sdbpw) 158 { 159 SECItem plainText, *cipherText = NULL; 160 CK_RV crv = CKR_USER_NOT_LOGGED_IN; 161 SECStatus rv; 162 163 plainText.data = value; 164 plainText.len = len; 165 rv = lg_util_encrypt(NULL, sdbpw, &plainText, &cipherText); 166 if (rv != SECSuccess) { 167 goto loser; 168 } 169 crv = lg_CopyAttribute(attribute, type, cipherText->data, cipherText->len); 170 loser: 171 if (cipherText) { 172 SECITEM_FreeItem(cipherText, PR_TRUE); 173 } 174 return crv; 175 } 176 177 static CK_RV 178 lg_CopyPrivAttrSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, 179 void *value, CK_ULONG len, SDB *sdbpw) 180 { 181 unsigned char *dval = (unsigned char *)value; 182 183 if (*dval == 0) { 184 dval++; 185 len--; 186 } 187 return lg_CopyPrivAttribute(attribute, type, dval, len, sdbpw); 188 } 189 190 static CK_RV 191 lg_invalidAttribute(CK_ATTRIBUTE *attr) 192 { 193 attr->ulValueLen = (CK_ULONG)-1; 194 return CKR_ATTRIBUTE_TYPE_INVALID; 195 } 196 197 #define LG_DEF_ATTRIBUTE(value, len) \ 198 { \ 199 0, value, len \ 200 } 201 202 #define LG_CLONE_ATTR(attribute, type, staticAttr) \ 203 lg_CopyAttribute(attribute, type, staticAttr.pValue, staticAttr.ulValueLen) 204 205 CK_BBOOL lg_staticTrueValue = CK_TRUE; 206 CK_BBOOL lg_staticFalseValue = CK_FALSE; 207 static const CK_ATTRIBUTE lg_StaticTrueAttr = 208 LG_DEF_ATTRIBUTE(&lg_staticTrueValue, sizeof(lg_staticTrueValue)); 209 static const CK_ATTRIBUTE lg_StaticFalseAttr = 210 LG_DEF_ATTRIBUTE(&lg_staticFalseValue, sizeof(lg_staticFalseValue)); 211 static const CK_ATTRIBUTE lg_StaticNullAttr = LG_DEF_ATTRIBUTE(NULL, 0); 212 char lg_StaticOneValue = 1; 213 214 /* 215 * helper functions which get the database and call the underlying 216 * low level database function. 217 */ 218 static char * 219 lg_FindKeyNicknameByPublicKey(SDB *sdb, SECItem *dbKey) 220 { 221 NSSLOWKEYDBHandle *keyHandle; 222 char *label; 223 224 keyHandle = lg_getKeyDB(sdb); 225 if (!keyHandle) { 226 return NULL; 227 } 228 229 label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey, 230 sdb); 231 return label; 232 } 233 234 NSSLOWKEYPrivateKey * 235 lg_FindKeyByPublicKey(SDB *sdb, SECItem *dbKey) 236 { 237 NSSLOWKEYPrivateKey *privKey; 238 NSSLOWKEYDBHandle *keyHandle; 239 240 keyHandle = lg_getKeyDB(sdb); 241 if (keyHandle == NULL) { 242 return NULL; 243 } 244 privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, sdb); 245 if (privKey == NULL) { 246 return NULL; 247 } 248 return privKey; 249 } 250 251 static certDBEntrySMime * 252 lg_getSMime(LGObjectCache *obj) 253 { 254 certDBEntrySMime *entry; 255 NSSLOWCERTCertDBHandle *certHandle; 256 257 if (obj->objclass != CKO_NSS_SMIME) { 258 return NULL; 259 } 260 if (obj->objectInfo) { 261 return (certDBEntrySMime *)obj->objectInfo; 262 } 263 264 certHandle = lg_getCertDB(obj->sdb); 265 if (!certHandle) { 266 return NULL; 267 } 268 entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)obj->dbKey.data); 269 obj->objectInfo = (void *)entry; 270 obj->infoFree = (LGFreeFunc)nsslowcert_DestroyDBEntry; 271 return entry; 272 } 273 274 static certDBEntryRevocation * 275 lg_getCrl(LGObjectCache *obj) 276 { 277 certDBEntryRevocation *crl; 278 PRBool isKrl; 279 NSSLOWCERTCertDBHandle *certHandle; 280 281 if (obj->objclass != CKO_NSS_CRL) { 282 return NULL; 283 } 284 if (obj->objectInfo) { 285 return (certDBEntryRevocation *)obj->objectInfo; 286 } 287 288 isKrl = (PRBool)(obj->handle == LG_TOKEN_KRL_HANDLE); 289 certHandle = lg_getCertDB(obj->sdb); 290 if (!certHandle) { 291 return NULL; 292 } 293 294 crl = nsslowcert_FindCrlByKey(certHandle, &obj->dbKey, isKrl); 295 obj->objectInfo = (void *)crl; 296 obj->infoFree = (LGFreeFunc)nsslowcert_DestroyDBEntry; 297 return crl; 298 } 299 300 static NSSLOWCERTCertificate * 301 lg_getCert(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle) 302 { 303 NSSLOWCERTCertificate *cert; 304 CK_OBJECT_CLASS objClass = obj->objclass; 305 306 if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NSS_TRUST) && 307 (objClass != CKO_TRUST)) { 308 return NULL; 309 } 310 if (objClass == CKO_CERTIFICATE && obj->objectInfo) { 311 return (NSSLOWCERTCertificate *)obj->objectInfo; 312 } 313 cert = nsslowcert_FindCertByKey(certHandle, &obj->dbKey); 314 if (objClass == CKO_CERTIFICATE) { 315 obj->objectInfo = (void *)cert; 316 obj->infoFree = (LGFreeFunc)nsslowcert_DestroyCertificate; 317 } 318 return cert; 319 } 320 321 static NSSLOWCERTTrust * 322 lg_getTrust(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle) 323 { 324 NSSLOWCERTTrust *trust; 325 326 if ((obj->objclass != CKO_NSS_TRUST) || (obj->objclass != CKO_TRUST)) { 327 return NULL; 328 } 329 if (obj->objectInfo) { 330 return (NSSLOWCERTTrust *)obj->objectInfo; 331 } 332 trust = nsslowcert_FindTrustByKey(certHandle, &obj->dbKey); 333 obj->objectInfo = (void *)trust; 334 obj->infoFree = (LGFreeFunc)nsslowcert_DestroyTrust; 335 return trust; 336 } 337 338 static NSSLOWKEYPublicKey * 339 lg_GetPublicKey(LGObjectCache *obj) 340 { 341 NSSLOWKEYPublicKey *pubKey; 342 NSSLOWKEYPrivateKey *privKey; 343 344 if (obj->objclass != CKO_PUBLIC_KEY) { 345 return NULL; 346 } 347 if (obj->objectInfo) { 348 return (NSSLOWKEYPublicKey *)obj->objectInfo; 349 } 350 privKey = lg_FindKeyByPublicKey(obj->sdb, &obj->dbKey); 351 if (privKey == NULL) { 352 return NULL; 353 } 354 pubKey = lg_nsslowkey_ConvertToPublicKey(privKey); 355 lg_nsslowkey_DestroyPrivateKey(privKey); 356 obj->objectInfo = (void *)pubKey; 357 obj->infoFree = (LGFreeFunc)lg_nsslowkey_DestroyPublicKey; 358 return pubKey; 359 } 360 361 /* 362 * we need two versions of lg_GetPrivateKey. One version that takes the 363 * DB handle so we can pass the handle we have already acquired in, 364 * rather than going through the 'getKeyDB' code again, 365 * which may fail the second time and another which just aquires 366 * the key handle from the sdb (where we don't already have a key handle. 367 * This version does the former. 368 */ 369 static NSSLOWKEYPrivateKey * 370 lg_GetPrivateKeyWithDB(LGObjectCache *obj, NSSLOWKEYDBHandle *keyHandle) 371 { 372 NSSLOWKEYPrivateKey *privKey; 373 374 if ((obj->objclass != CKO_PRIVATE_KEY) && 375 (obj->objclass != CKO_SECRET_KEY)) { 376 return NULL; 377 } 378 if (obj->objectInfo) { 379 return (NSSLOWKEYPrivateKey *)obj->objectInfo; 380 } 381 privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &obj->dbKey, obj->sdb); 382 if (privKey == NULL) { 383 return NULL; 384 } 385 obj->objectInfo = (void *)privKey; 386 obj->infoFree = (LGFreeFunc)lg_nsslowkey_DestroyPrivateKey; 387 return privKey; 388 } 389 390 /* this version does the latter */ 391 static NSSLOWKEYPrivateKey * 392 lg_GetPrivateKey(LGObjectCache *obj) 393 { 394 NSSLOWKEYDBHandle *keyHandle; 395 NSSLOWKEYPrivateKey *privKey; 396 397 keyHandle = lg_getKeyDB(obj->sdb); 398 if (!keyHandle) { 399 return NULL; 400 } 401 privKey = lg_GetPrivateKeyWithDB(obj, keyHandle); 402 return privKey; 403 } 404 405 /* lg_GetPubItem returns data associated with the public key. 406 * one only needs to free the public key. This comment is here 407 * because this sematic would be non-obvious otherwise. All callers 408 * should include this comment. 409 */ 410 static SECItem * 411 lg_GetPubItem(NSSLOWKEYPublicKey *pubKey) 412 { 413 SECItem *pubItem = NULL; 414 /* get value to compare from the cert's public key */ 415 switch (pubKey->keyType) { 416 case NSSLOWKEYRSAKey: 417 pubItem = &pubKey->u.rsa.modulus; 418 break; 419 case NSSLOWKEYDSAKey: 420 pubItem = &pubKey->u.dsa.publicValue; 421 break; 422 case NSSLOWKEYDHKey: 423 pubItem = &pubKey->u.dh.publicValue; 424 break; 425 case NSSLOWKEYECKey: 426 pubItem = &pubKey->u.ec.publicValue; 427 break; 428 default: 429 break; 430 } 431 return pubItem; 432 } 433 434 static CK_RV 435 lg_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, 436 CK_ATTRIBUTE *attribute) 437 { 438 unsigned char hash[SHA1_LENGTH]; 439 CK_KEY_TYPE keyType = CKK_RSA; 440 441 switch (type) { 442 case CKA_KEY_TYPE: 443 return lg_ULongAttribute(attribute, type, keyType); 444 case CKA_ID: 445 SHA1_HashBuf(hash, key->u.rsa.modulus.data, key->u.rsa.modulus.len); 446 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 447 case CKA_DERIVE: 448 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 449 case CKA_ENCRYPT: 450 case CKA_VERIFY: 451 case CKA_VERIFY_RECOVER: 452 case CKA_WRAP: 453 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 454 case CKA_MODULUS: 455 return lg_CopyAttributeSigned(attribute, type, key->u.rsa.modulus.data, 456 key->u.rsa.modulus.len); 457 case CKA_PUBLIC_EXPONENT: 458 return lg_CopyAttributeSigned(attribute, type, 459 key->u.rsa.publicExponent.data, 460 key->u.rsa.publicExponent.len); 461 default: 462 break; 463 } 464 return lg_invalidAttribute(attribute); 465 } 466 467 static CK_RV 468 lg_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, 469 CK_ATTRIBUTE *attribute) 470 { 471 unsigned char hash[SHA1_LENGTH]; 472 CK_KEY_TYPE keyType = CKK_DSA; 473 474 switch (type) { 475 case CKA_KEY_TYPE: 476 return lg_ULongAttribute(attribute, type, keyType); 477 case CKA_ID: 478 SHA1_HashBuf(hash, key->u.dsa.publicValue.data, 479 key->u.dsa.publicValue.len); 480 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 481 case CKA_DERIVE: 482 case CKA_ENCRYPT: 483 case CKA_VERIFY_RECOVER: 484 case CKA_WRAP: 485 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 486 case CKA_VERIFY: 487 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 488 case CKA_VALUE: 489 return lg_CopyAttributeSigned(attribute, type, 490 key->u.dsa.publicValue.data, 491 key->u.dsa.publicValue.len); 492 case CKA_PRIME: 493 return lg_CopyAttributeSigned(attribute, type, 494 key->u.dsa.params.prime.data, 495 key->u.dsa.params.prime.len); 496 case CKA_SUBPRIME: 497 return lg_CopyAttributeSigned(attribute, type, 498 key->u.dsa.params.subPrime.data, 499 key->u.dsa.params.subPrime.len); 500 case CKA_BASE: 501 return lg_CopyAttributeSigned(attribute, type, 502 key->u.dsa.params.base.data, 503 key->u.dsa.params.base.len); 504 default: 505 break; 506 } 507 return lg_invalidAttribute(attribute); 508 } 509 510 static CK_RV 511 lg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, 512 CK_ATTRIBUTE *attribute) 513 { 514 unsigned char hash[SHA1_LENGTH]; 515 CK_KEY_TYPE keyType = CKK_DH; 516 517 switch (type) { 518 case CKA_KEY_TYPE: 519 return lg_ULongAttribute(attribute, type, keyType); 520 case CKA_ID: 521 SHA1_HashBuf(hash, key->u.dh.publicValue.data, key->u.dh.publicValue.len); 522 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 523 case CKA_DERIVE: 524 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 525 case CKA_ENCRYPT: 526 case CKA_VERIFY: 527 case CKA_VERIFY_RECOVER: 528 case CKA_WRAP: 529 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 530 case CKA_VALUE: 531 return lg_CopyAttributeSigned(attribute, type, 532 key->u.dh.publicValue.data, 533 key->u.dh.publicValue.len); 534 case CKA_PRIME: 535 return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data, 536 key->u.dh.prime.len); 537 case CKA_BASE: 538 return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data, 539 key->u.dh.base.len); 540 default: 541 break; 542 } 543 return lg_invalidAttribute(attribute); 544 } 545 546 static CK_RV 547 lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, 548 CK_ATTRIBUTE *attribute) 549 { 550 unsigned char hash[SHA1_LENGTH]; 551 CK_KEY_TYPE keyType = CKK_EC; 552 553 switch (type) { 554 case CKA_KEY_TYPE: 555 return lg_ULongAttribute(attribute, type, keyType); 556 case CKA_ID: 557 SHA1_HashBuf(hash, key->u.ec.publicValue.data, 558 key->u.ec.publicValue.len); 559 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 560 case CKA_DERIVE: 561 case CKA_VERIFY: 562 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 563 case CKA_ENCRYPT: 564 case CKA_VERIFY_RECOVER: 565 case CKA_WRAP: 566 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 567 case CKA_EC_PARAMS: 568 return lg_CopyAttributeSigned(attribute, type, 569 key->u.ec.ecParams.DEREncoding.data, 570 key->u.ec.ecParams.DEREncoding.len); 571 case CKA_EC_POINT: 572 if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT")) { 573 return lg_CopyAttributeSigned(attribute, type, 574 key->u.ec.publicValue.data, 575 key->u.ec.publicValue.len); 576 } else { 577 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 578 &(key->u.ec.publicValue), 579 SEC_ASN1_GET(SEC_OctetStringTemplate)); 580 CK_RV crv; 581 if (!pubValue) { 582 return CKR_HOST_MEMORY; 583 } 584 crv = lg_CopyAttributeSigned(attribute, type, 585 pubValue->data, 586 pubValue->len); 587 SECITEM_FreeItem(pubValue, PR_TRUE); 588 return crv; 589 } 590 default: 591 break; 592 } 593 return lg_invalidAttribute(attribute); 594 } 595 596 static CK_RV 597 lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 598 CK_ATTRIBUTE *attribute) 599 { 600 NSSLOWKEYPublicKey *key; 601 CK_RV crv; 602 char *label; 603 604 switch (type) { 605 case CKA_PRIVATE: 606 case CKA_SENSITIVE: 607 case CKA_ALWAYS_SENSITIVE: 608 case CKA_NEVER_EXTRACTABLE: 609 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 610 case CKA_MODIFIABLE: 611 case CKA_EXTRACTABLE: 612 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 613 case CKA_SUBJECT: 614 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 615 case CKA_START_DATE: 616 case CKA_END_DATE: 617 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 618 case CKA_LABEL: 619 label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); 620 if (label == NULL) { 621 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 622 } 623 crv = lg_CopyAttribute(attribute, type, label, PORT_Strlen(label)); 624 PORT_Free(label); 625 return crv; 626 default: 627 break; 628 } 629 630 key = lg_GetPublicKey(obj); 631 if (key == NULL) { 632 if (type == CKA_ID) { 633 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 634 } 635 return CKR_OBJECT_HANDLE_INVALID; 636 } 637 638 switch (key->keyType) { 639 case NSSLOWKEYRSAKey: 640 return lg_FindRSAPublicKeyAttribute(key, type, attribute); 641 case NSSLOWKEYDSAKey: 642 return lg_FindDSAPublicKeyAttribute(key, type, attribute); 643 case NSSLOWKEYDHKey: 644 return lg_FindDHPublicKeyAttribute(key, type, attribute); 645 case NSSLOWKEYECKey: 646 return lg_FindECPublicKeyAttribute(key, type, attribute); 647 default: 648 break; 649 } 650 651 return lg_invalidAttribute(attribute); 652 } 653 654 static CK_RV 655 lg_FindSecretKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 656 CK_ATTRIBUTE *attribute) 657 { 658 NSSLOWKEYPrivateKey *key; 659 char *label; 660 unsigned char *keyString; 661 CK_RV crv; 662 int keyTypeLen; 663 CK_ULONG keyLen; 664 CK_KEY_TYPE keyType; 665 PRUint32 keyTypeStorage; 666 667 switch (type) { 668 case CKA_PRIVATE: 669 case CKA_SENSITIVE: 670 case CKA_ALWAYS_SENSITIVE: 671 case CKA_EXTRACTABLE: 672 case CKA_DERIVE: 673 case CKA_ENCRYPT: 674 case CKA_DECRYPT: 675 case CKA_SIGN: 676 case CKA_VERIFY: 677 case CKA_WRAP: 678 case CKA_UNWRAP: 679 case CKA_MODIFIABLE: 680 case CKA_LOCAL: 681 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 682 case CKA_NEVER_EXTRACTABLE: 683 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 684 case CKA_START_DATE: 685 case CKA_END_DATE: 686 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 687 case CKA_LABEL: 688 label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); 689 if (label == NULL) { 690 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 691 } 692 crv = lg_CopyAttribute(attribute, type, label, PORT_Strlen(label)); 693 PORT_Free(label); 694 return crv; 695 case CKA_ID: 696 return lg_CopyAttribute(attribute, type, obj->dbKey.data, 697 obj->dbKey.len); 698 case CKA_KEY_TYPE: 699 case CKA_VALUE_LEN: 700 case CKA_VALUE: 701 break; 702 default: 703 return lg_invalidAttribute(attribute); 704 } 705 706 key = lg_GetPrivateKey(obj); 707 if (key == NULL) { 708 return CKR_OBJECT_HANDLE_INVALID; 709 } 710 switch (type) { 711 case CKA_KEY_TYPE: 712 /* handle legacy databases. In legacy databases key_type was stored 713 * in host order, with any leading zeros stripped off. Only key types 714 * under 0x1f (AES) were stored. We assume that any values which are 715 * either 1 byte long (big endian), or have byte[0] between 0 and 716 * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other 717 * values are assumed to be from the new database, which is always 4 718 * bytes in network order */ 719 keyType = 0; 720 keyString = key->u.rsa.coefficient.data; 721 keyTypeLen = key->u.rsa.coefficient.len; 722 723 /* 724 * Because of various endian and word lengths The database may have 725 * stored the keyType value in one of the following formats: 726 * (kt) <= 0x1f 727 * length data 728 * Big Endian, pre-3.9, all lengths: 1 (kt) 729 * Little Endian, pre-3.9, 32 bits: 4 (kt) 0 0 0 730 * Little Endian, pre-3.9, 64 bits: 8 (kt) 0 0 0 0 0 0 0 731 * All platforms, 3.9, 32 bits: 4 0 0 0 (kt) 732 * Big Endian, 3.9, 64 bits: 8 0 0 0 (kt) 0 0 0 0 733 * Little Endian, 3.9, 64 bits: 8 0 0 0 0 0 0 0 (kt) 734 * All platforms, >= 3.9.1, all lengths: 4 (a) k1 k2 k3 735 * where (a) is 0 or >= 0x80. currently (a) can only be 0. 736 */ 737 /* 738 * this key was written on a 64 bit platform with a using NSS 3.9 739 * or earlier. Reduce the 64 bit possibilities above. When we are 740 * through, we will only have: 741 * 742 * Big Endian, pre-3.9, all lengths: 1 (kt) 743 * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 744 * All platforms, 3.9, all lengths: 4 0 0 0 (kt) 745 * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3 746 */ 747 if (keyTypeLen == 8) { 748 keyTypeStorage = *(PRUint32 *)keyString; 749 if (keyTypeStorage == 0) { 750 keyString += sizeof(PRUint32); 751 } 752 keyTypeLen = 4; 753 } 754 /* 755 * Now Handle: 756 * 757 * All platforms, 3.9, all lengths: 4 0 0 0 (kt) 758 * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3 759 * 760 * NOTE: if kt == 0 or ak1k2k3 == 0, the test fails and 761 * we handle it as: 762 * 763 * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 764 */ 765 if (keyTypeLen == sizeof(keyTypeStorage) && 766 (((keyString[0] & 0x80) == 0x80) || 767 !((keyString[1] == 0) && (keyString[2] == 0) && (keyString[3] == 0)))) { 768 PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage)); 769 keyType = (CK_KEY_TYPE)PR_ntohl(keyTypeStorage); 770 } else { 771 /* 772 * Now Handle: 773 * 774 * Big Endian, pre-3.9, all lengths: 1 (kt) 775 * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 776 * -- KeyType == 0 all other cases ---: 4 0 0 0 0 777 */ 778 keyType = (CK_KEY_TYPE)keyString[0]; 779 } 780 return lg_ULongAttribute(attribute, type, keyType); 781 case CKA_VALUE: 782 return lg_CopyPrivAttribute(attribute, type, key->u.rsa.privateExponent.data, 783 key->u.rsa.privateExponent.len, obj->sdb); 784 case CKA_VALUE_LEN: 785 keyLen = key->u.rsa.privateExponent.len; 786 return lg_ULongAttribute(attribute, type, keyLen); 787 } 788 return lg_invalidAttribute(attribute); 789 } 790 791 static CK_RV 792 lg_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, 793 CK_ATTRIBUTE *attribute, SDB *sdbpw) 794 { 795 unsigned char hash[SHA1_LENGTH]; 796 CK_KEY_TYPE keyType = CKK_RSA; 797 798 switch (type) { 799 case CKA_KEY_TYPE: 800 return lg_ULongAttribute(attribute, type, keyType); 801 case CKA_ID: 802 SHA1_HashBuf(hash, key->u.rsa.modulus.data, key->u.rsa.modulus.len); 803 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 804 case CKA_DERIVE: 805 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 806 case CKA_DECRYPT: 807 case CKA_SIGN: 808 case CKA_SIGN_RECOVER: 809 case CKA_UNWRAP: 810 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 811 case CKA_MODULUS: 812 return lg_CopyAttributeSigned(attribute, type, key->u.rsa.modulus.data, 813 key->u.rsa.modulus.len); 814 case CKA_PUBLIC_EXPONENT: 815 return lg_CopyAttributeSigned(attribute, type, 816 key->u.rsa.publicExponent.data, 817 key->u.rsa.publicExponent.len); 818 case CKA_PRIVATE_EXPONENT: 819 return lg_CopyPrivAttrSigned(attribute, type, 820 key->u.rsa.privateExponent.data, 821 key->u.rsa.privateExponent.len, sdbpw); 822 case CKA_PRIME_1: 823 return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime1.data, 824 key->u.rsa.prime1.len, sdbpw); 825 case CKA_PRIME_2: 826 return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime2.data, 827 key->u.rsa.prime2.len, sdbpw); 828 case CKA_EXPONENT_1: 829 return lg_CopyPrivAttrSigned(attribute, type, 830 key->u.rsa.exponent1.data, 831 key->u.rsa.exponent1.len, sdbpw); 832 case CKA_EXPONENT_2: 833 return lg_CopyPrivAttrSigned(attribute, type, 834 key->u.rsa.exponent2.data, 835 key->u.rsa.exponent2.len, sdbpw); 836 case CKA_COEFFICIENT: 837 return lg_CopyPrivAttrSigned(attribute, type, 838 key->u.rsa.coefficient.data, 839 key->u.rsa.coefficient.len, sdbpw); 840 default: 841 break; 842 } 843 return lg_invalidAttribute(attribute); 844 } 845 846 static CK_RV 847 lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, 848 CK_ATTRIBUTE *attribute, SDB *sdbpw) 849 { 850 unsigned char hash[SHA1_LENGTH]; 851 CK_KEY_TYPE keyType = CKK_DSA; 852 853 switch (type) { 854 case CKA_KEY_TYPE: 855 return lg_ULongAttribute(attribute, type, keyType); 856 case CKA_ID: 857 SHA1_HashBuf(hash, key->u.dsa.publicValue.data, 858 key->u.dsa.publicValue.len); 859 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 860 case CKA_DERIVE: 861 case CKA_DECRYPT: 862 case CKA_SIGN_RECOVER: 863 case CKA_UNWRAP: 864 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 865 case CKA_SIGN: 866 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 867 case CKA_VALUE: 868 return lg_CopyPrivAttrSigned(attribute, type, 869 key->u.dsa.privateValue.data, 870 key->u.dsa.privateValue.len, sdbpw); 871 case CKA_PRIME: 872 return lg_CopyAttributeSigned(attribute, type, 873 key->u.dsa.params.prime.data, 874 key->u.dsa.params.prime.len); 875 case CKA_SUBPRIME: 876 return lg_CopyAttributeSigned(attribute, type, 877 key->u.dsa.params.subPrime.data, 878 key->u.dsa.params.subPrime.len); 879 case CKA_BASE: 880 return lg_CopyAttributeSigned(attribute, type, 881 key->u.dsa.params.base.data, 882 key->u.dsa.params.base.len); 883 case CKA_NSS_DB: 884 return lg_CopyAttributeSigned(attribute, type, 885 key->u.dsa.publicValue.data, 886 key->u.dsa.publicValue.len); 887 default: 888 break; 889 } 890 return lg_invalidAttribute(attribute); 891 } 892 893 static CK_RV 894 lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, 895 CK_ATTRIBUTE *attribute, SDB *sdbpw) 896 { 897 unsigned char hash[SHA1_LENGTH]; 898 CK_KEY_TYPE keyType = CKK_DH; 899 900 switch (type) { 901 case CKA_KEY_TYPE: 902 return lg_ULongAttribute(attribute, type, keyType); 903 case CKA_ID: 904 SHA1_HashBuf(hash, key->u.dh.publicValue.data, key->u.dh.publicValue.len); 905 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 906 case CKA_DERIVE: 907 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 908 case CKA_DECRYPT: 909 case CKA_SIGN: 910 case CKA_SIGN_RECOVER: 911 case CKA_UNWRAP: 912 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 913 case CKA_VALUE: 914 return lg_CopyPrivAttrSigned(attribute, type, 915 key->u.dh.privateValue.data, 916 key->u.dh.privateValue.len, sdbpw); 917 case CKA_PRIME: 918 return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data, 919 key->u.dh.prime.len); 920 case CKA_BASE: 921 return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data, 922 key->u.dh.base.len); 923 case CKA_NSS_DB: 924 return lg_CopyAttributeSigned(attribute, type, 925 key->u.dh.publicValue.data, 926 key->u.dh.publicValue.len); 927 default: 928 break; 929 } 930 return lg_invalidAttribute(attribute); 931 } 932 933 static CK_RV 934 lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, 935 CK_ATTRIBUTE *attribute, SDB *sdbpw) 936 { 937 unsigned char hash[SHA1_LENGTH]; 938 CK_KEY_TYPE keyType = CKK_EC; 939 940 switch (type) { 941 case CKA_KEY_TYPE: 942 return lg_ULongAttribute(attribute, type, keyType); 943 case CKA_ID: 944 SHA1_HashBuf(hash, key->u.ec.publicValue.data, key->u.ec.publicValue.len); 945 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 946 case CKA_DERIVE: 947 case CKA_SIGN: 948 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 949 case CKA_DECRYPT: 950 case CKA_SIGN_RECOVER: 951 case CKA_UNWRAP: 952 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 953 case CKA_VALUE: 954 return lg_CopyPrivAttribute(attribute, type, 955 key->u.ec.privateValue.data, 956 key->u.ec.privateValue.len, sdbpw); 957 case CKA_EC_PARAMS: 958 return lg_CopyAttributeSigned(attribute, type, 959 key->u.ec.ecParams.DEREncoding.data, 960 key->u.ec.ecParams.DEREncoding.len); 961 case CKA_NSS_DB: 962 return lg_CopyAttributeSigned(attribute, type, 963 key->u.ec.publicValue.data, 964 key->u.ec.publicValue.len); 965 default: 966 break; 967 } 968 return lg_invalidAttribute(attribute); 969 } 970 971 static CK_RV 972 lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 973 CK_ATTRIBUTE *attribute) 974 { 975 NSSLOWKEYPrivateKey *key; 976 char *label; 977 CK_RV crv; 978 979 switch (type) { 980 case CKA_PRIVATE: 981 case CKA_SENSITIVE: 982 case CKA_ALWAYS_SENSITIVE: 983 case CKA_EXTRACTABLE: 984 case CKA_MODIFIABLE: 985 case CKA_LOCAL: 986 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 987 case CKA_NEVER_EXTRACTABLE: 988 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 989 case CKA_SUBJECT: 990 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 991 case CKA_START_DATE: 992 case CKA_END_DATE: 993 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 994 case CKA_LABEL: 995 label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); 996 if (label == NULL) { 997 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 998 } 999 crv = lg_CopyAttribute(attribute, type, label, PORT_Strlen(label)); 1000 PORT_Free(label); 1001 return crv; 1002 default: 1003 break; 1004 } 1005 key = lg_GetPrivateKey(obj); 1006 if (key == NULL) { 1007 return CKR_OBJECT_HANDLE_INVALID; 1008 } 1009 switch (key->keyType) { 1010 case NSSLOWKEYRSAKey: 1011 return lg_FindRSAPrivateKeyAttribute(key, type, attribute, obj->sdb); 1012 case NSSLOWKEYDSAKey: 1013 return lg_FindDSAPrivateKeyAttribute(key, type, attribute, obj->sdb); 1014 case NSSLOWKEYDHKey: 1015 return lg_FindDHPrivateKeyAttribute(key, type, attribute, obj->sdb); 1016 case NSSLOWKEYECKey: 1017 return lg_FindECPrivateKeyAttribute(key, type, attribute, obj->sdb); 1018 default: 1019 break; 1020 } 1021 1022 return lg_invalidAttribute(attribute); 1023 } 1024 1025 static CK_RV 1026 lg_FindSMIMEAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1027 CK_ATTRIBUTE *attribute) 1028 { 1029 certDBEntrySMime *entry; 1030 switch (type) { 1031 case CKA_PRIVATE: 1032 case CKA_MODIFIABLE: 1033 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 1034 case CKA_NSS_EMAIL: 1035 return lg_CopyAttribute(attribute, type, obj->dbKey.data, 1036 obj->dbKey.len - 1); 1037 case CKA_NSS_SMIME_TIMESTAMP: 1038 case CKA_SUBJECT: 1039 case CKA_VALUE: 1040 break; 1041 default: 1042 return lg_invalidAttribute(attribute); 1043 } 1044 entry = lg_getSMime(obj); 1045 if (entry == NULL) { 1046 return CKR_OBJECT_HANDLE_INVALID; 1047 } 1048 switch (type) { 1049 case CKA_NSS_SMIME_TIMESTAMP: 1050 return lg_CopyAttribute(attribute, type, entry->optionsDate.data, 1051 entry->optionsDate.len); 1052 case CKA_SUBJECT: 1053 return lg_CopyAttribute(attribute, type, entry->subjectName.data, 1054 entry->subjectName.len); 1055 case CKA_VALUE: 1056 return lg_CopyAttribute(attribute, type, entry->smimeOptions.data, 1057 entry->smimeOptions.len); 1058 default: 1059 break; 1060 } 1061 return lg_invalidAttribute(attribute); 1062 } 1063 1064 static CK_RV 1065 lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1066 CK_ATTRIBUTE *attribute) 1067 { 1068 NSSLOWCERTTrust *trust; 1069 NSSLOWCERTCertDBHandle *certHandle; 1070 NSSLOWCERTCertificate *cert; 1071 unsigned char hash[SHA1_LENGTH]; 1072 unsigned int trustFlags; 1073 CK_RV crv = CKR_CANCEL; 1074 PRBool isPKCS; 1075 1076 switch (type) { 1077 case CKA_PRIVATE: 1078 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 1079 case CKA_MODIFIABLE: 1080 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 1081 case CKA_NSS_CERT_SHA1_HASH: 1082 case CKA_NSS_CERT_MD5_HASH: 1083 case CKA_HASH_OF_CERTIFICATE: 1084 case CKA_NAME_HASH_ALGORITHM: 1085 case CKA_NSS_TRUST_CLIENT_AUTH: 1086 case CKA_NSS_TRUST_SERVER_AUTH: 1087 case CKA_NSS_TRUST_EMAIL_PROTECTION: 1088 case CKA_NSS_TRUST_CODE_SIGNING: 1089 case CKA_NSS_TRUST_STEP_UP_APPROVED: 1090 case CKA_PKCS_TRUST_CLIENT_AUTH: 1091 case CKA_PKCS_TRUST_SERVER_AUTH: 1092 case CKA_PKCS_TRUST_EMAIL_PROTECTION: 1093 case CKA_PKCS_TRUST_CODE_SIGNING: 1094 case CKA_ISSUER: 1095 case CKA_SERIAL_NUMBER: 1096 break; 1097 default: 1098 return lg_invalidAttribute(attribute); 1099 } 1100 certHandle = lg_getCertDB(obj->sdb); 1101 if (!certHandle) { 1102 return CKR_OBJECT_HANDLE_INVALID; 1103 } 1104 trust = lg_getTrust(obj, certHandle); 1105 if (trust == NULL) { 1106 return CKR_OBJECT_HANDLE_INVALID; 1107 } 1108 isPKCS = PR_TRUE; 1109 switch (type) { 1110 case CKA_NAME_HASH_ALGORITHM: 1111 return lg_ULongAttribute(attribute, type, CKM_SHA_1); 1112 case CKA_NSS_CERT_SHA1_HASH: 1113 case CKA_HASH_OF_CERTIFICATE: 1114 SHA1_HashBuf(hash, trust->derCert->data, trust->derCert->len); 1115 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 1116 case CKA_NSS_CERT_MD5_HASH: 1117 MD5_HashBuf(hash, trust->derCert->data, trust->derCert->len); 1118 return lg_CopyAttribute(attribute, type, hash, MD5_LENGTH); 1119 case CKA_NSS_TRUST_CLIENT_AUTH: 1120 isPKCS = PR_FALSE; 1121 case CKA_PKCS_TRUST_CLIENT_AUTH: 1122 trustFlags = trust->trust->sslFlags & 1123 CERTDB_TRUSTED_CLIENT_CA 1124 ? trust->trust->sslFlags | CERTDB_TRUSTED_CA 1125 : 0; 1126 goto trust; 1127 case CKA_NSS_TRUST_SERVER_AUTH: 1128 isPKCS = PR_FALSE; 1129 case CKA_PKCS_TRUST_SERVER_AUTH: 1130 trustFlags = trust->trust->sslFlags; 1131 goto trust; 1132 case CKA_NSS_TRUST_EMAIL_PROTECTION: 1133 isPKCS = PR_FALSE; 1134 case CKA_PKCS_TRUST_EMAIL_PROTECTION: 1135 trustFlags = trust->trust->emailFlags; 1136 goto trust; 1137 case CKA_NSS_TRUST_CODE_SIGNING: 1138 isPKCS = PR_FALSE; 1139 case CKA_PKCS_TRUST_CODE_SIGNING: 1140 trustFlags = trust->trust->objectSigningFlags; 1141 trust: 1142 if (trustFlags & CERTDB_TRUSTED_CA) { 1143 return lg_ULongAttribute(attribute, type, 1144 isPKCS ? CKT_TRUST_ANCHOR : CKT_NSS_TRUSTED_DELEGATOR); 1145 } 1146 if (trustFlags & CERTDB_TRUSTED) { 1147 return lg_ULongAttribute(attribute, type, isPKCS ? CKT_TRUSTED : CKT_NSS_TRUSTED); 1148 } 1149 if (trustFlags & CERTDB_MUST_VERIFY) { 1150 return lg_ULongAttribute(attribute, type, 1151 isPKCS ? CKT_TRUST_MUST_VERIFY_TRUST : CKT_NSS_MUST_VERIFY_TRUST); 1152 } 1153 if (trustFlags & CERTDB_TRUSTED_UNKNOWN) { 1154 return lg_ULongAttribute(attribute, type, 1155 isPKCS ? CKT_TRUST_UNKNOWN : CKT_NSS_TRUST_UNKNOWN); 1156 } 1157 if (trustFlags & CERTDB_VALID_CA) { 1158 return lg_ULongAttribute(attribute, type, 1159 isPKCS ? CKT_TRUST_MUST_VERIFY_TRUST : CKT_NSS_VALID_DELEGATOR); 1160 } 1161 if (trustFlags & CERTDB_TERMINAL_RECORD) { 1162 return lg_ULongAttribute(attribute, type, 1163 isPKCS ? CKT_NOT_TRUSTED : CKT_NSS_NOT_TRUSTED); 1164 } 1165 return lg_ULongAttribute(attribute, type, isPKCS ? CKT_TRUST_UNKNOWN : CKT_NSS_TRUST_UNKNOWN); 1166 case CKA_NSS_TRUST_STEP_UP_APPROVED: 1167 if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) { 1168 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 1169 } else { 1170 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 1171 } 1172 default: 1173 break; 1174 } 1175 1176 switch (type) { 1177 case CKA_ISSUER: 1178 cert = lg_getCert(obj, certHandle); 1179 if (cert == NULL) 1180 break; 1181 crv = lg_CopyAttribute(attribute, type, cert->derIssuer.data, 1182 cert->derIssuer.len); 1183 break; 1184 case CKA_SERIAL_NUMBER: 1185 cert = lg_getCert(obj, certHandle); 1186 if (cert == NULL) 1187 break; 1188 crv = lg_CopyAttribute(attribute, type, cert->derSN.data, 1189 cert->derSN.len); 1190 break; 1191 default: 1192 cert = NULL; 1193 break; 1194 } 1195 if (cert) { 1196 nsslowcert_DestroyCertificate(cert); 1197 return crv; 1198 } 1199 return lg_invalidAttribute(attribute); 1200 } 1201 1202 static CK_RV 1203 lg_FindCrlAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1204 CK_ATTRIBUTE *attribute) 1205 { 1206 certDBEntryRevocation *crl; 1207 1208 switch (type) { 1209 case CKA_PRIVATE: 1210 case CKA_MODIFIABLE: 1211 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 1212 case CKA_NSS_KRL: 1213 return ((obj->handle == LG_TOKEN_KRL_HANDLE) 1214 ? LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr) 1215 : LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr)); 1216 case CKA_SUBJECT: 1217 return lg_CopyAttribute(attribute, type, obj->dbKey.data, 1218 obj->dbKey.len); 1219 case CKA_NSS_URL: 1220 case CKA_VALUE: 1221 break; 1222 default: 1223 return lg_invalidAttribute(attribute); 1224 } 1225 crl = lg_getCrl(obj); 1226 if (!crl) { 1227 return CKR_OBJECT_HANDLE_INVALID; 1228 } 1229 switch (type) { 1230 case CKA_NSS_URL: 1231 if (crl->url == NULL) { 1232 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 1233 } 1234 return lg_CopyAttribute(attribute, type, crl->url, 1235 PORT_Strlen(crl->url) + 1); 1236 case CKA_VALUE: 1237 return lg_CopyAttribute(attribute, type, crl->derCrl.data, 1238 crl->derCrl.len); 1239 default: 1240 break; 1241 } 1242 return lg_invalidAttribute(attribute); 1243 } 1244 1245 static CK_RV 1246 lg_FindCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1247 CK_ATTRIBUTE *attribute) 1248 { 1249 NSSLOWCERTCertificate *cert; 1250 NSSLOWCERTCertDBHandle *certHandle; 1251 NSSLOWKEYPublicKey *pubKey; 1252 unsigned char hash[SHA1_LENGTH]; 1253 SECItem *item; 1254 1255 switch (type) { 1256 case CKA_PRIVATE: 1257 return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr); 1258 case CKA_MODIFIABLE: 1259 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 1260 case CKA_CERTIFICATE_TYPE: 1261 /* hardcoding X.509 into here */ 1262 return lg_ULongAttribute(attribute, type, CKC_X_509); 1263 case CKA_VALUE: 1264 case CKA_ID: 1265 case CKA_LABEL: 1266 case CKA_SUBJECT: 1267 case CKA_ISSUER: 1268 case CKA_SERIAL_NUMBER: 1269 case CKA_NSS_EMAIL: 1270 break; 1271 default: 1272 return lg_invalidAttribute(attribute); 1273 } 1274 1275 certHandle = lg_getCertDB(obj->sdb); 1276 if (certHandle == NULL) { 1277 return CKR_OBJECT_HANDLE_INVALID; 1278 } 1279 1280 cert = lg_getCert(obj, certHandle); 1281 if (cert == NULL) { 1282 return CKR_OBJECT_HANDLE_INVALID; 1283 } 1284 switch (type) { 1285 case CKA_VALUE: 1286 return lg_CopyAttribute(attribute, type, cert->derCert.data, 1287 cert->derCert.len); 1288 case CKA_ID: 1289 if (((cert->trust->sslFlags & CERTDB_USER) == 0) && 1290 ((cert->trust->emailFlags & CERTDB_USER) == 0) && 1291 ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) { 1292 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 1293 } 1294 pubKey = nsslowcert_ExtractPublicKey(cert); 1295 if (pubKey == NULL) 1296 break; 1297 item = lg_GetPubItem(pubKey); 1298 if (item == NULL) { 1299 lg_nsslowkey_DestroyPublicKey(pubKey); 1300 break; 1301 } 1302 SHA1_HashBuf(hash, item->data, item->len); 1303 /* item is imbedded in pubKey, just free the key */ 1304 lg_nsslowkey_DestroyPublicKey(pubKey); 1305 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); 1306 case CKA_LABEL: 1307 return cert->nickname 1308 ? lg_CopyAttribute(attribute, type, cert->nickname, 1309 PORT_Strlen(cert->nickname)) 1310 : LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 1311 case CKA_SUBJECT: 1312 return lg_CopyAttribute(attribute, type, cert->derSubject.data, 1313 cert->derSubject.len); 1314 case CKA_ISSUER: 1315 return lg_CopyAttribute(attribute, type, cert->derIssuer.data, 1316 cert->derIssuer.len); 1317 case CKA_SERIAL_NUMBER: 1318 return lg_CopyAttribute(attribute, type, cert->derSN.data, 1319 cert->derSN.len); 1320 case CKA_NSS_EMAIL: 1321 return (cert->emailAddr && cert->emailAddr[0]) 1322 ? lg_CopyAttribute(attribute, type, cert->emailAddr, 1323 PORT_Strlen(cert->emailAddr)) 1324 : LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 1325 default: 1326 break; 1327 } 1328 return lg_invalidAttribute(attribute); 1329 } 1330 1331 CK_RV 1332 lg_GetSingleAttribute(LGObjectCache *obj, CK_ATTRIBUTE *attribute) 1333 { 1334 /* handle the common ones */ 1335 CK_ATTRIBUTE_TYPE type = attribute->type; 1336 switch (type) { 1337 case CKA_CLASS: 1338 return lg_ULongAttribute(attribute, type, obj->objclass); 1339 case CKA_TOKEN: 1340 return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr); 1341 case CKA_LABEL: 1342 if ((obj->objclass == CKO_CERTIFICATE) || 1343 (obj->objclass == CKO_PRIVATE_KEY) || 1344 (obj->objclass == CKO_PUBLIC_KEY) || 1345 (obj->objclass == CKO_SECRET_KEY)) { 1346 break; 1347 } 1348 return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr); 1349 default: 1350 break; 1351 } 1352 switch (obj->objclass) { 1353 case CKO_CERTIFICATE: 1354 return lg_FindCertAttribute(obj, type, attribute); 1355 case CKO_NSS_CRL: 1356 return lg_FindCrlAttribute(obj, type, attribute); 1357 case CKO_NSS_TRUST: 1358 case CKO_TRUST: 1359 return lg_FindTrustAttribute(obj, type, attribute); 1360 case CKO_NSS_SMIME: 1361 return lg_FindSMIMEAttribute(obj, type, attribute); 1362 case CKO_PUBLIC_KEY: 1363 return lg_FindPublicKeyAttribute(obj, type, attribute); 1364 case CKO_PRIVATE_KEY: 1365 return lg_FindPrivateKeyAttribute(obj, type, attribute); 1366 case CKO_SECRET_KEY: 1367 return lg_FindSecretKeyAttribute(obj, type, attribute); 1368 default: 1369 break; 1370 } 1371 return lg_invalidAttribute(attribute); 1372 } 1373 1374 /* 1375 * Fill in the attribute template based on the data in the database. 1376 */ 1377 CK_RV 1378 lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *templ, 1379 CK_ULONG count) 1380 { 1381 LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK); 1382 CK_RV crv, crvCollect = CKR_OK; 1383 unsigned int i; 1384 1385 if (obj == NULL) { 1386 return CKR_OBJECT_HANDLE_INVALID; 1387 } 1388 1389 for (i = 0; i < count; i++) { 1390 crv = lg_GetSingleAttribute(obj, &templ[i]); 1391 if (crvCollect == CKR_OK) 1392 crvCollect = crv; 1393 } 1394 1395 lg_DestroyObjectCache(obj); 1396 return crvCollect; 1397 } 1398 1399 PRBool 1400 lg_cmpAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attribute) 1401 { 1402 unsigned char buf[LG_BUF_SPACE]; 1403 CK_ATTRIBUTE testAttr; 1404 unsigned char *tempBuf = NULL; 1405 PRBool match = PR_TRUE; 1406 CK_RV crv; 1407 1408 /* we're going to compare 'attribute' with the actual attribute from 1409 * the object. We'll use the length of 'attribute' to decide how much 1410 * space we need to read the test attribute. If 'attribute' doesn't give 1411 * enough space, then we know the values don't match and that will 1412 * show up as ckr != CKR_OK */ 1413 testAttr = *attribute; 1414 testAttr.pValue = buf; 1415 1416 /* if we don't have enough space, malloc it */ 1417 if (attribute->ulValueLen > LG_BUF_SPACE) { 1418 tempBuf = PORT_Alloc(attribute->ulValueLen); 1419 if (!tempBuf) { 1420 return PR_FALSE; 1421 } 1422 testAttr.pValue = tempBuf; 1423 } 1424 1425 /* get the attribute */ 1426 crv = lg_GetSingleAttribute(obj, &testAttr); 1427 /* if the attribute was read OK, compare it */ 1428 if ((crv != CKR_OK) || 1429 (attribute->pValue == NULL) || 1430 (attribute->ulValueLen != testAttr.ulValueLen) || 1431 (PORT_Memcmp(attribute->pValue, testAttr.pValue, testAttr.ulValueLen) != 0)) { 1432 /* something didn't match, this isn't the object we are looking for */ 1433 match = PR_FALSE; 1434 } 1435 /* free the buffer we may have allocated */ 1436 if (tempBuf) { 1437 PORT_Free(tempBuf); 1438 } 1439 return match; 1440 } 1441 1442 PRBool 1443 lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class, 1444 const CK_ATTRIBUTE *templ, CK_ULONG count) 1445 { 1446 PRBool match = PR_TRUE; 1447 LGObjectCache *obj = lg_NewObjectCache(sdb, dbKey, class); 1448 unsigned int i; 1449 1450 if (obj == NULL) { 1451 return PR_FALSE; 1452 } 1453 1454 for (i = 0; i < count; i++) { 1455 match = lg_cmpAttribute(obj, &templ[i]); 1456 if (!match) { 1457 break; 1458 } 1459 } 1460 1461 /* done looking, free up our cache */ 1462 lg_DestroyObjectCache(obj); 1463 1464 /* if we get through the whole list without finding a mismatched attribute, 1465 * then this object fits the criteria we are matching */ 1466 return match; 1467 } 1468 1469 static CK_RV 1470 lg_SetCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1471 const void *value, unsigned int len) 1472 { 1473 NSSLOWCERTCertificate *cert; 1474 NSSLOWCERTCertDBHandle *certHandle; 1475 char *nickname = NULL; 1476 SECStatus rv; 1477 CK_RV crv; 1478 1479 /* we can't change the EMAIL values, but let the 1480 * upper layers feel better about the fact we tried to set these */ 1481 if (type == CKA_NSS_EMAIL) { 1482 return CKR_OK; 1483 } 1484 1485 certHandle = lg_getCertDB(obj->sdb); 1486 if (certHandle == NULL) { 1487 crv = CKR_TOKEN_WRITE_PROTECTED; 1488 goto done; 1489 } 1490 1491 if ((type != CKA_LABEL) && (type != CKA_ID)) { 1492 crv = CKR_ATTRIBUTE_READ_ONLY; 1493 goto done; 1494 } 1495 1496 cert = lg_getCert(obj, certHandle); 1497 if (cert == NULL) { 1498 crv = CKR_OBJECT_HANDLE_INVALID; 1499 goto done; 1500 } 1501 1502 /* if the app is trying to set CKA_ID, it's probably because it just 1503 * imported the key. Look to see if we need to set the CERTDB_USER bits. 1504 */ 1505 if (type == CKA_ID) { 1506 if (((cert->trust->sslFlags & CERTDB_USER) == 0) && 1507 ((cert->trust->emailFlags & CERTDB_USER) == 0) && 1508 ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) { 1509 NSSLOWKEYDBHandle *keyHandle; 1510 1511 keyHandle = lg_getKeyDB(obj->sdb); 1512 if (keyHandle) { 1513 if (nsslowkey_KeyForCertExists(keyHandle, cert)) { 1514 NSSLOWCERTCertTrust trust = *cert->trust; 1515 trust.sslFlags |= CERTDB_USER; 1516 trust.emailFlags |= CERTDB_USER; 1517 trust.objectSigningFlags |= CERTDB_USER; 1518 nsslowcert_ChangeCertTrust(certHandle, cert, &trust); 1519 } 1520 } 1521 } 1522 crv = CKR_OK; 1523 goto done; 1524 } 1525 1526 /* must be CKA_LABEL */ 1527 if (value != NULL) { 1528 nickname = PORT_ZAlloc(len + 1); 1529 if (nickname == NULL) { 1530 crv = CKR_HOST_MEMORY; 1531 goto done; 1532 } 1533 PORT_Memcpy(nickname, value, len); 1534 nickname[len] = 0; 1535 } 1536 rv = nsslowcert_AddPermNickname(certHandle, cert, nickname); 1537 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; 1538 1539 done: 1540 if (nickname) { 1541 PORT_Free(nickname); 1542 } 1543 return crv; 1544 } 1545 1546 static CK_RV 1547 lg_SetPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1548 const void *value, unsigned int len, 1549 PRBool *writePrivate) 1550 { 1551 NSSLOWKEYPrivateKey *privKey; 1552 NSSLOWKEYDBHandle *keyHandle; 1553 char *nickname = NULL; 1554 SECStatus rv; 1555 CK_RV crv; 1556 1557 /* we can't change the ID and we don't store the subject, but let the 1558 * upper layers feel better about the fact we tried to set these */ 1559 if ((type == CKA_ID) || (type == CKA_SUBJECT) || 1560 (type == CKA_LOCAL) || (type == CKA_NEVER_EXTRACTABLE) || 1561 (type == CKA_ALWAYS_SENSITIVE)) { 1562 return CKR_OK; 1563 } 1564 1565 keyHandle = lg_getKeyDB(obj->sdb); 1566 if (keyHandle == NULL) { 1567 crv = CKR_TOKEN_WRITE_PROTECTED; 1568 goto done; 1569 } 1570 1571 privKey = lg_GetPrivateKeyWithDB(obj, keyHandle); 1572 if (privKey == NULL) { 1573 crv = CKR_OBJECT_HANDLE_INVALID; 1574 goto done; 1575 } 1576 1577 crv = CKR_ATTRIBUTE_READ_ONLY; 1578 switch (type) { 1579 case CKA_LABEL: 1580 if (value != NULL) { 1581 nickname = PORT_ZAlloc(len + 1); 1582 if (nickname == NULL) { 1583 crv = CKR_HOST_MEMORY; 1584 goto done; 1585 } 1586 PORT_Memcpy(nickname, value, len); 1587 nickname[len] = 0; 1588 } 1589 rv = nsslowkey_UpdateNickname(keyHandle, privKey, &obj->dbKey, 1590 nickname, obj->sdb); 1591 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; 1592 break; 1593 case CKA_UNWRAP: 1594 case CKA_SIGN: 1595 case CKA_DERIVE: 1596 case CKA_SIGN_RECOVER: 1597 case CKA_DECRYPT: 1598 /* ignore attempts to change restrict these. 1599 * legacyDB ignore these flags and always presents all of them 1600 * that are valid as true. 1601 * NOTE: We only get here if the current value and the new value do 1602 * not match. */ 1603 if (*(char *)value == 0) { 1604 crv = CKR_OK; 1605 } 1606 break; 1607 case CKA_VALUE: 1608 case CKA_PRIVATE_EXPONENT: 1609 case CKA_PRIME_1: 1610 case CKA_PRIME_2: 1611 case CKA_EXPONENT_1: 1612 case CKA_EXPONENT_2: 1613 case CKA_COEFFICIENT: 1614 /* We aren't really changing these values, we are just triggering 1615 * the database to update it's entry */ 1616 *writePrivate = PR_TRUE; 1617 crv = CKR_OK; 1618 break; 1619 default: 1620 crv = CKR_ATTRIBUTE_READ_ONLY; 1621 break; 1622 } 1623 done: 1624 if (nickname) { 1625 PORT_Free(nickname); 1626 } 1627 return crv; 1628 } 1629 1630 static CK_RV 1631 lg_SetPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 1632 const void *value, unsigned int len, 1633 PRBool *writePrivate) 1634 { 1635 /* we can't change the ID and we don't store the subject, but let the 1636 * upper layers feel better about the fact we tried to set these */ 1637 if ((type == CKA_ID) || (type == CKA_SUBJECT) || (type == CKA_LABEL)) { 1638 return CKR_OK; 1639 } 1640 return CKR_ATTRIBUTE_READ_ONLY; 1641 } 1642 1643 static CK_RV 1644 lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr) 1645 { 1646 unsigned int flags; 1647 CK_TRUST trust; 1648 NSSLOWCERTCertificate *cert = NULL; 1649 NSSLOWCERTCertDBHandle *certHandle; 1650 NSSLOWCERTCertTrust dbTrust; 1651 SECStatus rv; 1652 CK_RV crv; 1653 1654 if (attr->type == CKA_LABEL) { 1655 return CKR_OK; 1656 } 1657 1658 crv = lg_GetULongAttribute(attr->type, attr, 1, &trust); 1659 if (crv != CKR_OK) { 1660 return crv; 1661 } 1662 flags = lg_MapTrust(trust, (PRBool)((attr->type == CKA_NSS_TRUST_CLIENT_AUTH) || 1663 (attr->type == CKA_PKCS_TRUST_CLIENT_AUTH))); 1664 1665 certHandle = lg_getCertDB(obj->sdb); 1666 1667 if (certHandle == NULL) { 1668 crv = CKR_TOKEN_WRITE_PROTECTED; 1669 goto done; 1670 } 1671 1672 cert = lg_getCert(obj, certHandle); 1673 if (cert == NULL) { 1674 crv = CKR_OBJECT_HANDLE_INVALID; 1675 goto done; 1676 } 1677 dbTrust = *cert->trust; 1678 1679 switch (attr->type) { 1680 case CKA_TRUST_EMAIL_PROTECTION: 1681 dbTrust.emailFlags = flags | 1682 (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS); 1683 break; 1684 case CKA_TRUST_CODE_SIGNING: 1685 dbTrust.objectSigningFlags = flags | 1686 (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS); 1687 break; 1688 case CKA_TRUST_CLIENT_AUTH: 1689 dbTrust.sslFlags = flags | (cert->trust->sslFlags & 1690 (CERTDB_PRESERVE_TRUST_BITS | CERTDB_TRUSTED_CA)); 1691 break; 1692 case CKA_TRUST_SERVER_AUTH: 1693 dbTrust.sslFlags = flags | (cert->trust->sslFlags & 1694 (CERTDB_PRESERVE_TRUST_BITS | CERTDB_TRUSTED_CLIENT_CA)); 1695 break; 1696 default: 1697 crv = CKR_ATTRIBUTE_READ_ONLY; 1698 goto done; 1699 } 1700 1701 rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust); 1702 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; 1703 done: 1704 if (cert) { 1705 nsslowcert_DestroyCertificate(cert); 1706 } 1707 return crv; 1708 } 1709 1710 static CK_RV 1711 lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr, 1712 PRBool *writePrivate) 1713 { 1714 CK_ATTRIBUTE attribLocal; 1715 CK_RV crv; 1716 1717 if ((attr->type == CKA_NSS_DB) && (obj->objclass == CKO_PRIVATE_KEY)) { 1718 *writePrivate = PR_TRUE; 1719 return CKR_OK; 1720 } 1721 1722 /* Make sure the attribute exists first */ 1723 attribLocal.type = attr->type; 1724 attribLocal.pValue = NULL; 1725 attribLocal.ulValueLen = 0; 1726 crv = lg_GetSingleAttribute(obj, &attribLocal); 1727 if (crv != CKR_OK) { 1728 return crv; 1729 } 1730 1731 /* if we are just setting it to the value we already have, 1732 * allow it to happen. Let label setting go through so 1733 * we have the opportunity to repair any database corruption. */ 1734 if (attr->type != CKA_LABEL) { 1735 if (lg_cmpAttribute(obj, attr)) { 1736 return CKR_OK; 1737 } 1738 } 1739 1740 crv = CKR_ATTRIBUTE_READ_ONLY; 1741 switch (obj->objclass) { 1742 case CKO_CERTIFICATE: 1743 /* change NICKNAME, EMAIL, */ 1744 crv = lg_SetCertAttribute(obj, attr->type, 1745 attr->pValue, attr->ulValueLen); 1746 break; 1747 case CKO_NSS_CRL: 1748 /* change URL */ 1749 break; 1750 case CKO_NSS_TRUST: 1751 case CKO_TRUST: 1752 crv = lg_SetTrustAttribute(obj, attr); 1753 break; 1754 case CKO_PRIVATE_KEY: 1755 case CKO_SECRET_KEY: 1756 crv = lg_SetPrivateKeyAttribute(obj, attr->type, 1757 attr->pValue, attr->ulValueLen, writePrivate); 1758 break; 1759 case CKO_PUBLIC_KEY: 1760 crv = lg_SetPublicKeyAttribute(obj, attr->type, 1761 attr->pValue, attr->ulValueLen, writePrivate); 1762 break; 1763 } 1764 return crv; 1765 } 1766 1767 /* 1768 * Fill in the attribute template based on the data in the database. 1769 */ 1770 CK_RV 1771 lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, 1772 const CK_ATTRIBUTE *templ, CK_ULONG count) 1773 { 1774 LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK); 1775 CK_RV crv, crvCollect = CKR_OK; 1776 PRBool writePrivate = PR_FALSE; 1777 unsigned int i; 1778 1779 if (obj == NULL) { 1780 return CKR_OBJECT_HANDLE_INVALID; 1781 } 1782 1783 for (i = 0; i < count; i++) { 1784 crv = lg_SetSingleAttribute(obj, &templ[i], &writePrivate); 1785 if (crvCollect == CKR_OK) 1786 crvCollect = crv; 1787 } 1788 1789 /* Write any collected changes out for private and secret keys. 1790 * don't do the write for just the label */ 1791 if (writePrivate) { 1792 NSSLOWKEYPrivateKey *privKey = lg_GetPrivateKey(obj); 1793 SECStatus rv = SECFailure; 1794 char *label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); 1795 1796 if (privKey) { 1797 rv = nsslowkey_StoreKeyByPublicKeyAlg(lg_getKeyDB(sdb), privKey, 1798 &obj->dbKey, label, sdb, PR_TRUE); 1799 } 1800 if (rv != SECSuccess) { 1801 crv = CKR_DEVICE_ERROR; 1802 } 1803 PORT_Free(label); 1804 } 1805 1806 lg_DestroyObjectCache(obj); 1807 return crvCollect; 1808 }