lgfind.c (30448B)
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 #include "secitem.h" 5 #include "pkcs11.h" 6 #include "lgdb.h" 7 #include "lowkeyi.h" 8 #include "pcert.h" 9 #include "blapi.h" 10 11 #include "keydbi.h" 12 13 /* 14 * This code maps PKCS #11 Finds to legacy database searches. This code 15 * was orginally in pkcs11.c in previous versions of NSS. 16 */ 17 18 struct SDBFindStr { 19 CK_OBJECT_HANDLE *handles; 20 int size; 21 int index; 22 int array_size; 23 }; 24 25 /* 26 * free a search structure 27 */ 28 void 29 lg_FreeSearch(SDBFind *search) 30 { 31 if (search->handles) { 32 PORT_Free(search->handles); 33 } 34 PORT_Free(search); 35 } 36 37 void 38 lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle) 39 { 40 if (search->handles == NULL) { 41 return; 42 } 43 if (search->size >= search->array_size) { 44 search->array_size += LG_SEARCH_BLOCK_SIZE; 45 search->handles = (CK_OBJECT_HANDLE *)PORT_Realloc(search->handles, 46 sizeof(CK_OBJECT_HANDLE) * search->array_size); 47 if (search->handles == NULL) { 48 return; 49 } 50 } 51 search->handles[search->size] = handle; 52 search->size++; 53 } 54 55 /* 56 * find any certs that may match the template and load them. 57 */ 58 #define LG_CERT 0x00000001 59 #define LG_TRUST 0x00000002 60 #define LG_CRL 0x00000004 61 #define LG_SMIME 0x00000008 62 #define LG_PRIVATE 0x00000010 63 #define LG_PUBLIC 0x00000020 64 #define LG_KEY 0x00000040 65 #define LG_NSS_TRUST 0x00000080 66 67 /* 68 * structure to collect key handles. 69 */ 70 typedef struct lgEntryDataStr { 71 SDB *sdb; 72 SDBFind *searchHandles; 73 const CK_ATTRIBUTE *template; 74 CK_ULONG templ_count; 75 } lgEntryData; 76 77 static SECStatus 78 lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg) 79 { 80 lgEntryData *crlData; 81 CK_OBJECT_HANDLE class_handle; 82 SDB *sdb; 83 84 crlData = (lgEntryData *)arg; 85 sdb = crlData->sdb; 86 87 class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL : LG_TOKEN_KRL_HANDLE; 88 if (lg_tokenMatch(sdb, key, class_handle, 89 crlData->template, crlData->templ_count)) { 90 lg_addHandle(crlData->searchHandles, 91 lg_mkHandle(sdb, key, class_handle)); 92 } 93 return (SECSuccess); 94 } 95 96 static void 97 lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl, 98 unsigned long classFlags, SDBFind *search, 99 const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) 100 { 101 NSSLOWCERTCertDBHandle *certHandle = NULL; 102 103 certHandle = lg_getCertDB(sdb); 104 if (certHandle == NULL) { 105 return; 106 } 107 if (derSubject->data != NULL) { 108 certDBEntryRevocation *crl = 109 nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl); 110 111 if (crl != NULL) { 112 lg_addHandle(search, lg_mkHandle(sdb, derSubject, 113 isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL)); 114 nsslowcert_DestroyDBEntry((certDBEntry *)crl); 115 } 116 } else { 117 lgEntryData crlData; 118 119 /* traverse */ 120 crlData.sdb = sdb; 121 crlData.searchHandles = search; 122 crlData.template = pTemplate; 123 crlData.templ_count = ulCount; 124 nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation, 125 lg_crl_collect, (void *)&crlData); 126 nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation, 127 lg_crl_collect, (void *)&crlData); 128 } 129 } 130 131 /* 132 * structure to collect key handles. 133 */ 134 typedef struct lgKeyDataStr { 135 SDB *sdb; 136 NSSLOWKEYDBHandle *keyHandle; 137 SDBFind *searchHandles; 138 SECItem *id; 139 const CK_ATTRIBUTE *template; 140 CK_ULONG templ_count; 141 unsigned long classFlags; 142 PRBool strict; 143 } lgKeyData; 144 145 static PRBool 146 isSecretKey(NSSLOWKEYPrivateKey *privKey) 147 { 148 if (privKey->keyType == NSSLOWKEYRSAKey && 149 privKey->u.rsa.publicExponent.len == 1 && 150 privKey->u.rsa.publicExponent.data[0] == 0) 151 return PR_TRUE; 152 153 return PR_FALSE; 154 } 155 156 static SECStatus 157 lg_key_collect(DBT *key, DBT *data, void *arg) 158 { 159 lgKeyData *keyData; 160 NSSLOWKEYPrivateKey *privKey = NULL; 161 SECItem tmpDBKey; 162 SDB *sdb; 163 unsigned long classFlags; 164 165 keyData = (lgKeyData *)arg; 166 sdb = keyData->sdb; 167 classFlags = keyData->classFlags; 168 169 tmpDBKey.data = key->data; 170 tmpDBKey.len = key->size; 171 tmpDBKey.type = siBuffer; 172 173 PORT_Assert(keyData->keyHandle); 174 if (!keyData->strict && keyData->id && keyData->id->data) { 175 SECItem result; 176 PRBool haveMatch = PR_FALSE; 177 unsigned char hashKey[SHA1_LENGTH]; 178 result.data = hashKey; 179 result.len = sizeof(hashKey); 180 181 if (keyData->id->len == 0) { 182 /* Make sure this isn't a LG_KEY */ 183 privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, 184 &tmpDBKey, keyData->sdb /*->password*/); 185 if (privKey) { 186 /* turn off the unneeded class flags */ 187 classFlags &= isSecretKey(privKey) ? ~(LG_PRIVATE | LG_PUBLIC) : ~LG_KEY; 188 haveMatch = (PRBool)((classFlags & (LG_KEY | LG_PRIVATE | LG_PUBLIC)) != 0); 189 lg_nsslowkey_DestroyPrivateKey(privKey); 190 } 191 } else { 192 SHA1_HashBuf(hashKey, key->data, key->size); /* match id */ 193 haveMatch = SECITEM_ItemsAreEqual(keyData->id, &result); 194 if (!haveMatch && ((unsigned char *)key->data)[0] == 0) { 195 /* This is a fix for backwards compatibility. The key 196 * database indexes private keys by the public key, and 197 * versions of NSS prior to 3.4 stored the public key as 198 * a signed integer. The public key is now treated as an 199 * unsigned integer, with no leading zero. In order to 200 * correctly compute the hash of an old key, it is necessary 201 * to fallback and detect the leading zero. 202 */ 203 SHA1_HashBuf(hashKey, 204 (unsigned char *)key->data + 1, key->size - 1); 205 haveMatch = SECITEM_ItemsAreEqual(keyData->id, &result); 206 } 207 } 208 if (haveMatch) { 209 if (classFlags & LG_PRIVATE) { 210 lg_addHandle(keyData->searchHandles, 211 lg_mkHandle(sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV)); 212 } 213 if (classFlags & LG_PUBLIC) { 214 lg_addHandle(keyData->searchHandles, 215 lg_mkHandle(sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB)); 216 } 217 if (classFlags & LG_KEY) { 218 lg_addHandle(keyData->searchHandles, 219 lg_mkHandle(sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY)); 220 } 221 } 222 return SECSuccess; 223 } 224 225 privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey, 226 keyData->sdb /*->password*/); 227 if (privKey == NULL) { 228 goto loser; 229 } 230 231 if (isSecretKey(privKey)) { 232 if ((classFlags & LG_KEY) && 233 lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY, 234 keyData->template, keyData->templ_count)) { 235 lg_addHandle(keyData->searchHandles, 236 lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY)); 237 } 238 } else { 239 if ((classFlags & LG_PRIVATE) && 240 lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV, 241 keyData->template, keyData->templ_count)) { 242 lg_addHandle(keyData->searchHandles, 243 lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV)); 244 } 245 if ((classFlags & LG_PUBLIC) && 246 lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB, 247 keyData->template, keyData->templ_count)) { 248 lg_addHandle(keyData->searchHandles, 249 lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB)); 250 } 251 } 252 253 loser: 254 if (privKey) { 255 lg_nsslowkey_DestroyPrivateKey(privKey); 256 } 257 return (SECSuccess); 258 } 259 260 static void 261 lg_searchKeys(SDB *sdb, SECItem *key_id, 262 unsigned long classFlags, SDBFind *search, PRBool mustStrict, 263 const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount) 264 { 265 NSSLOWKEYDBHandle *keyHandle = NULL; 266 NSSLOWKEYPrivateKey *privKey; 267 lgKeyData keyData; 268 PRBool found = PR_FALSE; 269 270 keyHandle = lg_getKeyDB(sdb); 271 if (keyHandle == NULL) { 272 return; 273 } 274 275 if (key_id->data) { 276 privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb); 277 if (privKey) { 278 if ((classFlags & LG_KEY) && isSecretKey(privKey)) { 279 lg_addHandle(search, 280 lg_mkHandle(sdb, key_id, LG_TOKEN_TYPE_KEY)); 281 found = PR_TRUE; 282 } 283 if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) { 284 lg_addHandle(search, 285 lg_mkHandle(sdb, key_id, LG_TOKEN_TYPE_PRIV)); 286 found = PR_TRUE; 287 } 288 if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) { 289 lg_addHandle(search, 290 lg_mkHandle(sdb, key_id, LG_TOKEN_TYPE_PUB)); 291 found = PR_TRUE; 292 } 293 lg_nsslowkey_DestroyPrivateKey(privKey); 294 } 295 /* don't do the traversal if we have an up to date db */ 296 if (keyHandle->version != 3) { 297 goto loser; 298 } 299 /* don't do the traversal if it can't possibly be the correct id */ 300 /* all soft token id's are SHA1_HASH_LEN's */ 301 if (key_id->len != SHA1_LENGTH) { 302 goto loser; 303 } 304 if (found) { 305 /* if we already found some keys, don't do the traversal */ 306 goto loser; 307 } 308 } 309 keyData.sdb = sdb; 310 keyData.keyHandle = keyHandle; 311 keyData.searchHandles = search; 312 keyData.id = key_id; 313 keyData.template = pTemplate; 314 keyData.templ_count = ulCount; 315 keyData.classFlags = classFlags; 316 keyData.strict = mustStrict ? mustStrict : LG_STRICT; 317 318 nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData); 319 320 loser: 321 return; 322 } 323 324 /* 325 * structure to collect certs into 326 */ 327 typedef struct lgCertDataStr { 328 SDB *sdb; 329 int cert_count; 330 int max_cert_count; 331 NSSLOWCERTCertificate **certs; 332 const CK_ATTRIBUTE *template; 333 CK_ULONG templ_count; 334 unsigned long classFlags; 335 PRBool strict; 336 } lgCertData; 337 338 /* 339 * collect all the certs from the traverse call. 340 */ 341 static SECStatus 342 lg_cert_collect(NSSLOWCERTCertificate *cert, void *arg) 343 { 344 lgCertData *cd = (lgCertData *)arg; 345 346 if (cert == NULL) { 347 return SECSuccess; 348 } 349 350 if (cd->certs == NULL) { 351 return SECFailure; 352 } 353 354 if (cd->strict) { 355 if ((cd->classFlags & LG_CERT) && 356 !lg_tokenMatch(cd->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT, cd->template, cd->templ_count)) { 357 return SECSuccess; 358 } 359 if ((cd->classFlags & LG_TRUST) && 360 !lg_tokenMatch(cd->sdb, &cert->certKey, LG_TOKEN_TYPE_TRUST, cd->template, cd->templ_count)) { 361 return SECSuccess; 362 } 363 if ((cd->classFlags & LG_NSS_TRUST) && 364 !lg_tokenMatch(cd->sdb, &cert->certKey, LG_TOKEN_TYPE_NSS_TRUST, cd->template, cd->templ_count)) { 365 return SECSuccess; 366 } 367 } 368 369 /* allocate more space if we need it. This should only happen in 370 * the general traversal case */ 371 if (cd->cert_count >= cd->max_cert_count) { 372 int size; 373 cd->max_cert_count += LG_SEARCH_BLOCK_SIZE; 374 size = cd->max_cert_count * sizeof(NSSLOWCERTCertificate *); 375 cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs, size); 376 if (cd->certs == NULL) { 377 return SECFailure; 378 } 379 } 380 381 cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert); 382 return SECSuccess; 383 } 384 385 /* provide impedence matching ... */ 386 static SECStatus 387 lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg) 388 { 389 return lg_cert_collect(cert, arg); 390 } 391 392 static void 393 lg_searchSingleCert(lgCertData *certData, NSSLOWCERTCertificate *cert) 394 { 395 if (cert == NULL) { 396 return; 397 } 398 if (certData->strict && 399 !lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT, 400 certData->template, certData->templ_count)) { 401 nsslowcert_DestroyCertificate(cert); 402 return; 403 } 404 certData->certs = (NSSLOWCERTCertificate **) 405 PORT_Alloc(sizeof(NSSLOWCERTCertificate *)); 406 if (certData->certs == NULL) { 407 nsslowcert_DestroyCertificate(cert); 408 return; 409 } 410 certData->certs[0] = cert; 411 certData->cert_count = 1; 412 } 413 414 static void 415 lg_CertSetupData(lgCertData *certData, int count) 416 { 417 certData->max_cert_count = count; 418 419 if (certData->max_cert_count <= 0) { 420 return; 421 } 422 certData->certs = (NSSLOWCERTCertificate **) 423 PORT_Alloc(count * sizeof(NSSLOWCERTCertificate *)); 424 return; 425 } 426 427 static void 428 lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name, 429 SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN, 430 SECItem *email, 431 unsigned long classFlags, SDBFind *handles, 432 const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) 433 { 434 NSSLOWCERTCertDBHandle *certHandle = NULL; 435 lgCertData certData; 436 int i; 437 438 certHandle = lg_getCertDB(sdb); 439 if (certHandle == NULL) 440 return; 441 442 certData.sdb = sdb; 443 certData.max_cert_count = 0; 444 certData.certs = NULL; 445 certData.cert_count = 0; 446 certData.template = pTemplate; 447 certData.templ_count = ulCount; 448 certData.classFlags = classFlags; 449 certData.strict = LG_STRICT; 450 451 /* 452 * Find the Cert. 453 */ 454 if (derCert->data != NULL) { 455 NSSLOWCERTCertificate *cert = 456 nsslowcert_FindCertByDERCert(certHandle, derCert); 457 lg_searchSingleCert(&certData, cert); 458 } else if (name->data != NULL) { 459 char *tmp_name = (char *)PORT_Alloc(name->len + 1); 460 int count; 461 462 if (tmp_name == NULL) { 463 return; 464 } 465 PORT_Memcpy(tmp_name, name->data, name->len); 466 tmp_name[name->len] = 0; 467 468 count = nsslowcert_NumPermCertsForNickname(certHandle, tmp_name); 469 lg_CertSetupData(&certData, count); 470 nsslowcert_TraversePermCertsForNickname(certHandle, tmp_name, 471 lg_cert_collect, &certData); 472 PORT_Free(tmp_name); 473 } else if (derSubject->data != NULL) { 474 int count; 475 476 count = nsslowcert_NumPermCertsForSubject(certHandle, derSubject); 477 lg_CertSetupData(&certData, count); 478 nsslowcert_TraversePermCertsForSubject(certHandle, derSubject, 479 lg_cert_collect, &certData); 480 } else if ((issuerSN->derIssuer.data != NULL) && 481 (issuerSN->serialNumber.data != NULL)) { 482 if (classFlags & LG_CERT) { 483 NSSLOWCERTCertificate *cert = 484 nsslowcert_FindCertByIssuerAndSN(certHandle, issuerSN); 485 486 lg_searchSingleCert(&certData, cert); 487 } 488 if (classFlags & LG_TRUST) { 489 NSSLOWCERTTrust *trust = 490 nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN); 491 492 if (trust) { 493 lg_addHandle(handles, 494 lg_mkHandle(sdb, &trust->dbKey, LG_TOKEN_TYPE_TRUST)); 495 nsslowcert_DestroyTrust(trust); 496 } 497 } 498 if (classFlags & LG_NSS_TRUST) { 499 NSSLOWCERTTrust *trust = 500 nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN); 501 502 if (trust) { 503 lg_addHandle(handles, 504 lg_mkHandle(sdb, &trust->dbKey, LG_TOKEN_TYPE_NSS_TRUST)); 505 nsslowcert_DestroyTrust(trust); 506 } 507 } 508 } else if (email->data != NULL) { 509 char *tmp_name = (char *)PORT_Alloc(email->len + 1); 510 certDBEntrySMime *entry = NULL; 511 512 if (tmp_name == NULL) { 513 return; 514 } 515 PORT_Memcpy(tmp_name, email->data, email->len); 516 tmp_name[email->len] = 0; 517 518 entry = nsslowcert_ReadDBSMimeEntry(certHandle, tmp_name); 519 if (entry) { 520 int count; 521 SECItem *subjectName = &entry->subjectName; 522 523 count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName); 524 lg_CertSetupData(&certData, count); 525 nsslowcert_TraversePermCertsForSubject(certHandle, subjectName, 526 lg_cert_collect, &certData); 527 528 nsslowcert_DestroyDBEntry((certDBEntry *)entry); 529 } 530 PORT_Free(tmp_name); 531 } else { 532 /* we aren't filtering the certs, we are working on all, so turn 533 * on the strict filters. */ 534 certData.strict = PR_TRUE; 535 lg_CertSetupData(&certData, LG_SEARCH_BLOCK_SIZE); 536 nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData); 537 } 538 539 /* 540 * build the handles 541 */ 542 for (i = 0; i < certData.cert_count; i++) { 543 NSSLOWCERTCertificate *cert = certData.certs[i]; 544 545 /* if we filtered it would have been on the stuff above */ 546 if (classFlags & LG_CERT) { 547 lg_addHandle(handles, 548 lg_mkHandle(sdb, &cert->certKey, LG_TOKEN_TYPE_CERT)); 549 } 550 if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) { 551 lg_addHandle(handles, 552 lg_mkHandle(sdb, &cert->certKey, LG_TOKEN_TYPE_TRUST)); 553 } 554 if ((classFlags & LG_NSS_TRUST) && nsslowcert_hasTrust(cert->trust)) { 555 lg_addHandle(handles, 556 lg_mkHandle(sdb, &cert->certKey, LG_TOKEN_TYPE_NSS_TRUST)); 557 } 558 nsslowcert_DestroyCertificate(cert); 559 } 560 561 if (certData.certs) 562 PORT_Free(certData.certs); 563 return; 564 } 565 566 static SECStatus 567 lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg) 568 { 569 lgEntryData *smimeData; 570 SDB *sdb; 571 572 smimeData = (lgEntryData *)arg; 573 sdb = smimeData->sdb; 574 575 if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME, 576 smimeData->template, smimeData->templ_count)) { 577 lg_addHandle(smimeData->searchHandles, 578 lg_mkHandle(sdb, key, LG_TOKEN_TYPE_SMIME)); 579 } 580 return (SECSuccess); 581 } 582 583 static void 584 lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles, 585 const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) 586 { 587 NSSLOWCERTCertDBHandle *certHandle = NULL; 588 certDBEntrySMime *entry; 589 590 certHandle = lg_getCertDB(sdb); 591 if (certHandle == NULL) 592 return; 593 594 if (email->data != NULL) { 595 char *tmp_name = (char *)PORT_Alloc(email->len + 1); 596 597 if (tmp_name == NULL) { 598 return; 599 } 600 PORT_Memcpy(tmp_name, email->data, email->len); 601 tmp_name[email->len] = 0; 602 603 entry = nsslowcert_ReadDBSMimeEntry(certHandle, tmp_name); 604 if (entry) { 605 SECItem emailKey; 606 607 emailKey.data = (unsigned char *)tmp_name; 608 emailKey.len = PORT_Strlen(tmp_name) + 1; 609 emailKey.type = 0; 610 lg_addHandle(handles, 611 lg_mkHandle(sdb, &emailKey, LG_TOKEN_TYPE_SMIME)); 612 nsslowcert_DestroyDBEntry((certDBEntry *)entry); 613 } 614 PORT_Free(tmp_name); 615 } else { 616 /* traverse */ 617 lgEntryData smimeData; 618 619 /* traverse */ 620 smimeData.sdb = sdb; 621 smimeData.searchHandles = handles; 622 smimeData.template = pTemplate; 623 smimeData.templ_count = ulCount; 624 nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile, 625 lg_smime_collect, (void *)&smimeData); 626 } 627 return; 628 } 629 630 static CK_RV 631 lg_searchTokenList(SDB *sdb, SDBFind *search, 632 const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount) 633 { 634 int i; 635 PRBool isKrl = PR_FALSE; 636 SECItem derCert = { siBuffer, NULL, 0 }; 637 SECItem derSubject = { siBuffer, NULL, 0 }; 638 SECItem name = { siBuffer, NULL, 0 }; 639 SECItem email = { siBuffer, NULL, 0 }; 640 SECItem key_id = { siBuffer, NULL, 0 }; 641 SECItem cert_sha1_hash = { siBuffer, NULL, 0 }; 642 SECItem cert_md5_hash = { siBuffer, NULL, 0 }; 643 NSSLOWCERTIssuerAndSN issuerSN = { 644 { siBuffer, NULL, 0 }, 645 { siBuffer, NULL, 0 } 646 }; 647 SECItem *copy = NULL; 648 CK_CERTIFICATE_TYPE certType; 649 CK_OBJECT_CLASS objectClass; 650 CK_RV crv; 651 unsigned long classFlags; 652 653 if (lg_getCertDB(sdb) == NULL) { 654 classFlags = LG_PRIVATE | LG_KEY; 655 } else { 656 classFlags = LG_CERT | LG_TRUST | LG_NSS_TRUST | LG_PUBLIC | LG_SMIME | LG_CRL; 657 } 658 659 /* 660 * look for things to search on token objects for. If the right options 661 * are specified, we can use them as direct indeces into the database 662 * (rather than using linear searches. We can also use the attributes to 663 * limit the kinds of objects we are searching for. Later we can use this 664 * array to filter the remaining objects more finely. 665 */ 666 for (i = 0; classFlags && i < (int)ulCount; i++) { 667 668 switch (pTemplate[i].type) { 669 case CKA_SUBJECT: 670 copy = &derSubject; 671 classFlags &= (LG_CERT | LG_PRIVATE | LG_PUBLIC | LG_SMIME | LG_CRL); 672 break; 673 case CKA_ISSUER: 674 copy = &issuerSN.derIssuer; 675 classFlags &= (LG_CERT | LG_NSS_TRUST | LG_TRUST); 676 break; 677 case CKA_SERIAL_NUMBER: 678 copy = &issuerSN.serialNumber; 679 classFlags &= (LG_CERT | LG_NSS_TRUST | LG_TRUST); 680 break; 681 case CKA_VALUE: 682 copy = &derCert; 683 classFlags &= (LG_CERT | LG_CRL | LG_SMIME); 684 break; 685 case CKA_LABEL: 686 copy = &name; 687 break; 688 case CKA_NSS_EMAIL: 689 copy = &email; 690 classFlags &= LG_SMIME | LG_CERT; 691 break; 692 case CKA_NSS_SMIME_TIMESTAMP: 693 classFlags &= LG_SMIME; 694 break; 695 case CKA_CLASS: 696 crv = lg_GetULongAttribute(CKA_CLASS, &pTemplate[i], 1, &objectClass); 697 if (crv != CKR_OK) { 698 classFlags = 0; 699 break; 700 } 701 switch (objectClass) { 702 case CKO_CERTIFICATE: 703 classFlags &= LG_CERT; 704 break; 705 case CKO_NSS_TRUST: 706 classFlags &= LG_NSS_TRUST; 707 break; 708 case CKO_TRUST: 709 classFlags &= LG_TRUST; 710 break; 711 case CKO_NSS_CRL: 712 classFlags &= LG_CRL; 713 break; 714 case CKO_NSS_SMIME: 715 classFlags &= LG_SMIME; 716 break; 717 case CKO_PRIVATE_KEY: 718 classFlags &= LG_PRIVATE; 719 break; 720 case CKO_PUBLIC_KEY: 721 classFlags &= LG_PUBLIC; 722 break; 723 case CKO_SECRET_KEY: 724 classFlags &= LG_KEY; 725 break; 726 default: 727 classFlags = 0; 728 break; 729 } 730 break; 731 case CKA_PRIVATE: 732 if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { 733 classFlags = 0; 734 break; 735 } 736 if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { 737 classFlags &= (LG_PRIVATE | LG_KEY); 738 } else { 739 classFlags &= ~(LG_PRIVATE | LG_KEY); 740 } 741 break; 742 case CKA_SENSITIVE: 743 if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { 744 classFlags = 0; 745 break; 746 } 747 if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) { 748 classFlags &= (LG_PRIVATE | LG_KEY); 749 } else { 750 classFlags = 0; 751 } 752 break; 753 case CKA_TOKEN: 754 if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { 755 classFlags = 0; 756 break; 757 } 758 if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) { 759 classFlags = 0; 760 } 761 break; 762 case CKA_NSS_CERT_SHA1_HASH: 763 classFlags &= LG_NSS_TRUST; 764 copy = &cert_sha1_hash; 765 break; 766 case CKA_HASH_OF_CERTIFICATE: 767 classFlags &= LG_NSS_TRUST; 768 copy = &cert_sha1_hash; 769 break; 770 case CKA_NSS_CERT_MD5_HASH: 771 classFlags &= LG_NSS_TRUST; 772 copy = &cert_md5_hash; 773 break; 774 case CKA_CERTIFICATE_TYPE: 775 crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE, &pTemplate[i], 776 1, &certType); 777 if (crv != CKR_OK) { 778 classFlags = 0; 779 break; 780 } 781 classFlags &= LG_CERT; 782 if (certType != CKC_X_509) { 783 classFlags = 0; 784 } 785 break; 786 case CKA_ID: 787 copy = &key_id; 788 classFlags &= (LG_CERT | LG_PRIVATE | LG_KEY | LG_PUBLIC); 789 break; 790 case CKA_NSS_KRL: 791 if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) { 792 classFlags = 0; 793 break; 794 } 795 classFlags &= LG_CRL; 796 isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE); 797 break; 798 case CKA_MODIFIABLE: 799 break; 800 case CKA_KEY_TYPE: 801 case CKA_DERIVE: 802 classFlags &= LG_PUBLIC | LG_PRIVATE | LG_KEY; 803 break; 804 case CKA_VERIFY_RECOVER: 805 classFlags &= LG_PUBLIC; 806 break; 807 case CKA_SIGN_RECOVER: 808 classFlags &= LG_PRIVATE; 809 break; 810 case CKA_ENCRYPT: 811 case CKA_VERIFY: 812 case CKA_WRAP: 813 classFlags &= LG_PUBLIC | LG_KEY; 814 break; 815 case CKA_DECRYPT: 816 case CKA_SIGN: 817 case CKA_UNWRAP: 818 case CKA_ALWAYS_SENSITIVE: 819 case CKA_EXTRACTABLE: 820 case CKA_NEVER_EXTRACTABLE: 821 classFlags &= LG_PRIVATE | LG_KEY; 822 break; 823 /* can't be a certificate if it doesn't match one of the above 824 * attributes */ 825 default: 826 classFlags = 0; 827 break; 828 } 829 if (copy) { 830 copy->data = (unsigned char *)pTemplate[i].pValue; 831 copy->len = pTemplate[i].ulValueLen; 832 } 833 copy = NULL; 834 } 835 836 /* certs */ 837 if (classFlags & (LG_CERT | LG_TRUST | LG_NSS_TRUST)) { 838 lg_searchCertsAndTrust(sdb, &derCert, &name, &derSubject, 839 &issuerSN, &email, classFlags, search, 840 pTemplate, ulCount); 841 } 842 843 /* keys */ 844 if (classFlags & (LG_PRIVATE | LG_PUBLIC | LG_KEY)) { 845 PRBool mustStrict = (name.len != 0); 846 lg_searchKeys(sdb, &key_id, classFlags, search, 847 mustStrict, pTemplate, ulCount); 848 } 849 850 /* crl's */ 851 if (classFlags & LG_CRL) { 852 lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search, 853 pTemplate, ulCount); 854 } 855 /* Add S/MIME entry stuff */ 856 if (classFlags & LG_SMIME) { 857 lg_searchSMime(sdb, &email, search, pTemplate, ulCount); 858 } 859 return CKR_OK; 860 } 861 862 /* lg_FindObjectsInit initializes a search for token and session objects 863 * that match a template. */ 864 CK_RV 865 lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate, 866 CK_ULONG ulCount, SDBFind **retSearch) 867 { 868 SDBFind *search; 869 CK_RV crv = CKR_OK; 870 871 *retSearch = NULL; 872 873 search = (SDBFind *)PORT_Alloc(sizeof(SDBFind)); 874 if (search == NULL) { 875 crv = CKR_HOST_MEMORY; 876 goto loser; 877 } 878 search->handles = (CK_OBJECT_HANDLE *) 879 PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE); 880 if (search->handles == NULL) { 881 crv = CKR_HOST_MEMORY; 882 goto loser; 883 } 884 search->index = 0; 885 search->size = 0; 886 search->array_size = LG_SEARCH_BLOCK_SIZE; 887 /* FIXME - do we still need to get Login state? */ 888 889 crv = lg_searchTokenList(sdb, search, pTemplate, ulCount); 890 if (crv != CKR_OK) { 891 goto loser; 892 } 893 894 *retSearch = search; 895 return CKR_OK; 896 897 loser: 898 if (search) { 899 lg_FreeSearch(search); 900 } 901 return crv; 902 } 903 904 /* lg_FindObjects continues a search for token and session objects 905 * that match a template, obtaining additional object handles. */ 906 CK_RV 907 lg_FindObjects(SDB *sdb, SDBFind *search, 908 CK_OBJECT_HANDLE *phObject, CK_ULONG ulMaxObjectCount, 909 CK_ULONG *pulObjectCount) 910 { 911 int transfer; 912 int left; 913 914 *pulObjectCount = 0; 915 left = search->size - search->index; 916 transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount; 917 if (transfer > 0) { 918 PORT_Memcpy(phObject, &search->handles[search->index], 919 transfer * sizeof(CK_OBJECT_HANDLE)); 920 } else { 921 *phObject = CK_INVALID_HANDLE; 922 } 923 924 search->index += transfer; 925 *pulObjectCount = transfer; 926 return CKR_OK; 927 } 928 929 /* lg_FindObjectsFinal finishes a search for token and session objects. */ 930 CK_RV 931 lg_FindObjectsFinal(SDB *lgdb, SDBFind *search) 932 { 933 934 if (search != NULL) { 935 lg_FreeSearch(search); 936 } 937 return CKR_OK; 938 }