security/nss/lib/softoken/legacydb/lgattr.c

Wed, 31 Dec 2014 06:55:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:55:50 +0100
changeset 2
7e26c7da4463
permissions
-rw-r--r--

Added tag UPSTREAM_283F7C6 for changeset ca08bd8f51b2

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

mercurial