pk11nobj.c (21777B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 /* 5 * This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects, 6 * etc). 7 */ 8 9 #include <stddef.h> 10 11 #include "secport.h" 12 #include "seccomon.h" 13 #include "secmod.h" 14 #include "secmodi.h" 15 #include "secmodti.h" 16 #include "pkcs11.h" 17 #include "pk11func.h" 18 #include "cert.h" 19 #include "certi.h" 20 #include "secitem.h" 21 #include "sechash.h" 22 #include "secoid.h" 23 24 #include "certdb.h" 25 #include "secerr.h" 26 27 #include "pki3hack.h" 28 #include "dev3hack.h" 29 30 #include "devm.h" 31 #include "pki.h" 32 #include "pkim.h" 33 34 extern const NSSError NSS_ERROR_NOT_FOUND; 35 36 PRBool 37 pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust) 38 { 39 return nssTrust_HandleTrustForCERTCert(cert, trust); 40 } 41 42 static SECStatus 43 pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg) 44 { 45 SECItem derCrl; 46 CERTCrlHeadNode *head = (CERTCrlHeadNode *)arg; 47 CERTCrlNode *new_node = NULL; 48 CK_ATTRIBUTE fetchCrl[3] = { 49 { CKA_VALUE, NULL, 0 }, 50 { CKA_NSS_KRL, NULL, 0 }, 51 { CKA_NSS_URL, NULL, 0 }, 52 }; 53 const int fetchCrlSize = sizeof(fetchCrl) / sizeof(fetchCrl[2]); 54 CK_RV crv; 55 SECStatus rv = SECFailure; 56 57 crv = PK11_GetAttributes(head->arena, slot, crlID, fetchCrl, fetchCrlSize); 58 if (CKR_OK != crv) { 59 PORT_SetError(PK11_MapError(crv)); 60 goto loser; 61 } 62 63 if (!fetchCrl[1].pValue) { 64 PORT_SetError(SEC_ERROR_CRL_INVALID); 65 goto loser; 66 } 67 68 new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode)); 69 if (new_node == NULL) { 70 goto loser; 71 } 72 73 if (*((CK_BBOOL *)fetchCrl[1].pValue)) 74 new_node->type = SEC_KRL_TYPE; 75 else 76 new_node->type = SEC_CRL_TYPE; 77 78 derCrl.type = siBuffer; 79 derCrl.data = (unsigned char *)fetchCrl[0].pValue; 80 derCrl.len = fetchCrl[0].ulValueLen; 81 new_node->crl = CERT_DecodeDERCrl(head->arena, &derCrl, new_node->type); 82 if (new_node->crl == NULL) { 83 goto loser; 84 } 85 86 if (fetchCrl[2].pValue) { 87 int nnlen = fetchCrl[2].ulValueLen; 88 new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen + 1); 89 if (!new_node->crl->url) { 90 goto loser; 91 } 92 PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); 93 new_node->crl->url[nnlen] = 0; 94 } else { 95 new_node->crl->url = NULL; 96 } 97 98 new_node->next = NULL; 99 if (head->last) { 100 head->last->next = new_node; 101 head->last = new_node; 102 } else { 103 head->first = head->last = new_node; 104 } 105 rv = SECSuccess; 106 107 loser: 108 return (rv); 109 } 110 111 /* 112 * Return a list of all the CRLs . 113 * CRLs are allocated in the list's arena. 114 */ 115 SECStatus 116 PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx) 117 { 118 pk11TraverseSlot creater; 119 CK_ATTRIBUTE theTemplate[2]; 120 CK_ATTRIBUTE *attrs; 121 CK_OBJECT_CLASS certClass = CKO_NSS_CRL; 122 CK_BBOOL isKrl = CK_FALSE; 123 124 attrs = theTemplate; 125 PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass)); 126 attrs++; 127 if (type != -1) { 128 isKrl = (CK_BBOOL)(type == SEC_KRL_TYPE); 129 PK11_SETATTRS(attrs, CKA_NSS_KRL, &isKrl, sizeof(isKrl)); 130 attrs++; 131 } 132 133 creater.callback = pk11_CollectCrls; 134 creater.callbackArg = (void *)nodes; 135 creater.findTemplate = theTemplate; 136 creater.templateCount = (attrs - theTemplate); 137 138 return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx); 139 } 140 141 struct crlOptionsStr { 142 CERTCrlHeadNode *head; 143 PRInt32 decodeOptions; 144 }; 145 146 typedef struct crlOptionsStr crlOptions; 147 148 static SECStatus 149 pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, 150 void *arg) 151 { 152 SECItem *derCrl = NULL; 153 crlOptions *options = (crlOptions *)arg; 154 CERTCrlHeadNode *head = options->head; 155 CERTCrlNode *new_node = NULL; 156 CK_ATTRIBUTE fetchCrl[3] = { 157 { CKA_VALUE, NULL, 0 }, 158 { CKA_NSS_KRL, NULL, 0 }, 159 { CKA_NSS_URL, NULL, 0 }, 160 }; 161 const int fetchCrlSize = sizeof(fetchCrl) / sizeof(fetchCrl[2]); 162 CK_RV crv; 163 SECStatus rv = SECFailure; 164 PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory 165 successfully */ 166 int i; 167 168 crv = PK11_GetAttributes(NULL, slot, crlID, fetchCrl, fetchCrlSize); 169 if (CKR_OK != crv) { 170 PORT_SetError(PK11_MapError(crv)); 171 goto loser; 172 } 173 174 if (!fetchCrl[1].pValue) { 175 /* reject KRLs */ 176 PORT_SetError(SEC_ERROR_CRL_INVALID); 177 goto loser; 178 } 179 180 new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, 181 sizeof(CERTCrlNode)); 182 if (new_node == NULL) { 183 goto loser; 184 } 185 186 new_node->type = SEC_CRL_TYPE; 187 188 derCrl = SECITEM_AllocItem(NULL, NULL, 0); 189 if (!derCrl) { 190 goto loser; 191 } 192 derCrl->type = siBuffer; 193 derCrl->data = (unsigned char *)fetchCrl[0].pValue; 194 derCrl->len = fetchCrl[0].ulValueLen; 195 new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, new_node->type, 196 options->decodeOptions); 197 if (new_node->crl == NULL) { 198 goto loser; 199 } 200 adopted = PR_TRUE; /* now that the CRL has adopted the DER memory, 201 we won't need to free it upon exit */ 202 203 if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) { 204 /* copy the URL if there is one */ 205 int nnlen = fetchCrl[2].ulValueLen; 206 new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena, 207 nnlen + 1); 208 if (!new_node->crl->url) { 209 goto loser; 210 } 211 PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen); 212 new_node->crl->url[nnlen] = 0; 213 } else { 214 new_node->crl->url = NULL; 215 } 216 217 new_node->next = NULL; 218 if (head->last) { 219 head->last->next = new_node; 220 head->last = new_node; 221 } else { 222 head->first = head->last = new_node; 223 } 224 rv = SECSuccess; 225 new_node->crl->slot = PK11_ReferenceSlot(slot); 226 new_node->crl->pkcs11ID = crlID; 227 228 loser: 229 /* free attributes that weren't adopted by the CRL */ 230 for (i = 1; i < fetchCrlSize; i++) { 231 if (fetchCrl[i].pValue) { 232 PORT_Free(fetchCrl[i].pValue); 233 } 234 } 235 /* free the DER if the CRL object didn't adopt it */ 236 if (fetchCrl[0].pValue && PR_FALSE == adopted) { 237 PORT_Free(fetchCrl[0].pValue); 238 } 239 if (derCrl && !adopted) { 240 /* clear the data fields, which we already took care of above */ 241 derCrl->data = NULL; 242 derCrl->len = 0; 243 /* free the memory for the SECItem structure itself */ 244 SECITEM_FreeItem(derCrl, PR_TRUE); 245 } 246 return (rv); 247 } 248 249 /* 250 * Return a list of CRLs matching specified issuer and type 251 * CRLs are not allocated in the list's arena, but rather in their own, 252 * arena, so that they can be used individually in the CRL cache . 253 * CRLs are always partially decoded for efficiency. 254 */ 255 SECStatus 256 pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem *issuer, 257 void *wincx) 258 { 259 pk11TraverseSlot creater; 260 CK_ATTRIBUTE theTemplate[2]; 261 CK_ATTRIBUTE *attrs; 262 CK_OBJECT_CLASS crlClass = CKO_NSS_CRL; 263 crlOptions options; 264 265 attrs = theTemplate; 266 PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass)); 267 attrs++; 268 269 options.head = nodes; 270 271 /* - do a partial decoding - we don't need to decode the entries while fetching 272 - don't copy the DER for optimal performance - CRL can be very large 273 - have the CRL objects adopt the DER, so SEC_DestroyCrl will free it 274 - keep bad CRL objects. The CRL cache is interested in them, for 275 security purposes. Bad CRL objects are a sign of something amiss. 276 */ 277 278 options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER | 279 CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL; 280 if (issuer) { 281 PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len); 282 attrs++; 283 } 284 285 creater.callback = pk11_RetrieveCrlsCallback; 286 creater.callbackArg = (void *)&options; 287 creater.findTemplate = theTemplate; 288 creater.templateCount = (attrs - theTemplate); 289 290 return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx); 291 } 292 293 /* 294 * return the crl associated with a derSubjectName 295 */ 296 SECItem * 297 PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle, 298 SECItem *name, int type, char **pUrl) 299 { 300 NSSCRL **crls, **crlp, *crl = NULL; 301 NSSDER subject; 302 SECItem *rvItem; 303 NSSTrustDomain *td = STAN_GetDefaultTrustDomain(); 304 char *url = NULL; 305 306 PORT_SetError(0); 307 NSSITEM_FROM_SECITEM(&subject, name); 308 if (*slot) { 309 nssCryptokiObject **instances; 310 nssPKIObjectCollection *collection; 311 nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly; 312 NSSToken *token = PK11Slot_GetNSSToken(*slot); 313 if (!token) { 314 goto loser; 315 } 316 collection = nssCRLCollection_Create(td, NULL); 317 if (!collection) { 318 (void)nssToken_Destroy(token); 319 goto loser; 320 } 321 instances = nssToken_FindCRLsBySubject(token, NULL, &subject, 322 tokenOnly, 0, NULL); 323 (void)nssToken_Destroy(token); 324 nssPKIObjectCollection_AddInstances(collection, instances, 0); 325 nss_ZFreeIf(instances); 326 crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL); 327 nssPKIObjectCollection_Destroy(collection); 328 } else { 329 crls = nssTrustDomain_FindCRLsBySubject(td, &subject); 330 } 331 if ((!crls) || (*crls == NULL)) { 332 if (crls) { 333 nssCRLArray_Destroy(crls); 334 } 335 if (NSS_GetError() == NSS_ERROR_NOT_FOUND) { 336 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); 337 } 338 goto loser; 339 } 340 for (crlp = crls; *crlp; crlp++) { 341 if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) || 342 ((*crlp)->isKRL && type != SEC_CRL_TYPE)) { 343 crl = nssCRL_AddRef(*crlp); 344 break; 345 } 346 } 347 nssCRLArray_Destroy(crls); 348 if (!crl) { 349 /* CRL collection was found, but no interesting CRL's were on it. 350 * Not an error */ 351 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); 352 goto loser; 353 } 354 if (crl->url) { 355 url = PORT_Strdup(crl->url); 356 if (!url) { 357 goto loser; 358 } 359 } 360 rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size); 361 if (!rvItem) { 362 goto loser; 363 } 364 memcpy(rvItem->data, crl->encoding.data, crl->encoding.size); 365 *slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot); 366 *crlHandle = crl->object.instances[0]->handle; 367 *pUrl = url; 368 nssCRL_Destroy(crl); 369 return rvItem; 370 371 loser: 372 if (url) 373 PORT_Free(url); 374 if (crl) 375 nssCRL_Destroy(crl); 376 if (PORT_GetError() == 0) { 377 PORT_SetError(SEC_ERROR_CRL_NOT_FOUND); 378 } 379 return NULL; 380 } 381 382 CK_OBJECT_HANDLE 383 PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name, 384 char *url, int type) 385 { 386 NSSItem derCRL, derSubject; 387 NSSToken *token; 388 nssCryptokiObject *object; 389 PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE; 390 CK_OBJECT_HANDLE rvH; 391 392 NSSITEM_FROM_SECITEM(&derSubject, name); 393 NSSITEM_FROM_SECITEM(&derCRL, crl); 394 token = PK11Slot_GetNSSToken(slot); 395 if (!token) { 396 PORT_SetError(SEC_ERROR_NO_TOKEN); 397 return CK_INVALID_HANDLE; 398 } 399 object = nssToken_ImportCRL(token, NULL, 400 &derSubject, &derCRL, isKRL, url, PR_TRUE); 401 (void)nssToken_Destroy(token); 402 403 if (object) { 404 rvH = object->handle; 405 nssCryptokiObject_Destroy(object); 406 } else { 407 rvH = CK_INVALID_HANDLE; 408 PORT_SetError(SEC_ERROR_CRL_IMPORT_FAILED); 409 } 410 return rvH; 411 } 412 413 /* 414 * delete a crl. 415 */ 416 SECStatus 417 SEC_DeletePermCRL(CERTSignedCrl *crl) 418 { 419 PRStatus status; 420 nssCryptokiObject *object; 421 NSSToken *token; 422 PK11SlotInfo *slot = crl->slot; 423 424 if (slot == NULL) { 425 PORT_Assert(slot); 426 /* shouldn't happen */ 427 PORT_SetError(SEC_ERROR_CRL_INVALID); 428 return SECFailure; 429 } 430 431 token = PK11Slot_GetNSSToken(slot); 432 if (!token) { 433 return SECFailure; 434 } 435 object = nss_ZNEW(NULL, nssCryptokiObject); 436 if (!object) { 437 (void)nssToken_Destroy(token); 438 return SECFailure; 439 } 440 object->token = token; /* object takes ownership */ 441 object->handle = crl->pkcs11ID; 442 object->isTokenObject = PR_TRUE; 443 444 status = nssToken_DeleteStoredObject(object); 445 446 nssCryptokiObject_Destroy(object); 447 return (status == PR_SUCCESS) ? SECSuccess : SECFailure; 448 } 449 450 /* search with email with and without NULL 451 * The sql database accepts the email with a NULL as it's written, 452 * the dbm database strips the NULL on write so won't match if 453 * it's there on find */ 454 static CK_OBJECT_HANDLE 455 pk11_FindSMimeObjectByTemplate(PK11SlotInfo *slot, 456 CK_ATTRIBUTE *theTemplate, size_t tsize) 457 { 458 CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; 459 CK_ATTRIBUTE *last; 460 461 PORT_Assert(tsize != 0); 462 463 smimeh = pk11_FindObjectByTemplate(slot, theTemplate, (int)tsize); 464 if (smimeh != CK_INVALID_HANDLE) { 465 return smimeh; 466 } 467 last = &theTemplate[tsize - 1]; 468 if ((last->type == CKA_NSS_EMAIL) && (last->ulValueLen != 0)) { 469 CK_ULONG save_len = last->ulValueLen; 470 last->ulValueLen--; 471 smimeh = pk11_FindObjectByTemplate(slot, theTemplate, (int)tsize); 472 last->ulValueLen = save_len; /* restore the original */ 473 return smimeh; 474 } 475 return CK_INVALID_HANDLE; 476 } 477 478 /* 479 * return the certificate associated with a derCert 480 */ 481 SECItem * 482 PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr, 483 SECItem *name, SECItem **profileTime) 484 { 485 CK_OBJECT_CLASS smimeClass = CKO_NSS_SMIME; 486 CK_ATTRIBUTE theTemplate[] = { 487 { CKA_CLASS, NULL, 0 }, 488 { CKA_SUBJECT, NULL, 0 }, 489 { CKA_NSS_EMAIL, NULL, 0 }, 490 }; 491 CK_ATTRIBUTE smimeData[] = { 492 { CKA_SUBJECT, NULL, 0 }, 493 { CKA_VALUE, NULL, 0 }, 494 }; 495 /* if you change the array, change the variable below as well */ 496 const size_t tsize = sizeof(theTemplate) / sizeof(theTemplate[0]); 497 CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; 498 CK_ATTRIBUTE *attrs = theTemplate; 499 CK_RV crv; 500 SECItem *emailProfile = NULL; 501 502 if (!emailAddr || !emailAddr[0]) { 503 PORT_SetError(SEC_ERROR_INVALID_ARGS); 504 return NULL; 505 } 506 507 PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); 508 attrs++; 509 PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len); 510 attrs++; 511 PK11_SETATTRS(attrs, CKA_NSS_EMAIL, emailAddr, strlen(emailAddr) + 1); 512 attrs++; 513 514 if (*slot) { 515 smimeh = pk11_FindSMimeObjectByTemplate(*slot, theTemplate, tsize); 516 } else { 517 PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM, 518 PR_FALSE, PR_TRUE, NULL); 519 PK11SlotListElement *le; 520 521 if (!list) { 522 return NULL; 523 } 524 /* loop through all the slots */ 525 for (le = list->head; le; le = le->next) { 526 smimeh = pk11_FindSMimeObjectByTemplate(le->slot, theTemplate, tsize); 527 if (smimeh != CK_INVALID_HANDLE) { 528 *slot = PK11_ReferenceSlot(le->slot); 529 break; 530 } 531 } 532 PK11_FreeSlotList(list); 533 } 534 535 if (smimeh == CK_INVALID_HANDLE) { 536 PORT_SetError(SEC_ERROR_NO_KRL); 537 return NULL; 538 } 539 540 if (profileTime) { 541 PK11_SETATTRS(smimeData, CKA_NSS_SMIME_TIMESTAMP, NULL, 0); 542 } 543 544 crv = PK11_GetAttributes(NULL, *slot, smimeh, smimeData, 2); 545 if (crv != CKR_OK) { 546 PORT_SetError(PK11_MapError(crv)); 547 goto loser; 548 } 549 550 if (!profileTime) { 551 SECItem profileSubject; 552 553 profileSubject.data = (unsigned char *)smimeData[0].pValue; 554 profileSubject.len = smimeData[0].ulValueLen; 555 if (!SECITEM_ItemsAreEqual(&profileSubject, name)) { 556 goto loser; 557 } 558 } 559 560 emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 561 if (emailProfile == NULL) { 562 goto loser; 563 } 564 565 emailProfile->data = (unsigned char *)smimeData[1].pValue; 566 emailProfile->len = smimeData[1].ulValueLen; 567 568 if (profileTime) { 569 *profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem)); 570 if (*profileTime) { 571 (*profileTime)->data = (unsigned char *)smimeData[0].pValue; 572 (*profileTime)->len = smimeData[0].ulValueLen; 573 } 574 } 575 576 loser: 577 if (emailProfile == NULL) { 578 if (smimeData[1].pValue) { 579 PORT_Free(smimeData[1].pValue); 580 } 581 } 582 if (profileTime == NULL || *profileTime == NULL) { 583 if (smimeData[0].pValue) { 584 PORT_Free(smimeData[0].pValue); 585 } 586 } 587 return emailProfile; 588 } 589 590 SECStatus 591 PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj, 592 SECItem *emailProfile, SECItem *profileTime) 593 { 594 CK_OBJECT_CLASS smimeClass = CKO_NSS_SMIME; 595 CK_BBOOL ck_true = CK_TRUE; 596 CK_ATTRIBUTE theTemplate[] = { 597 { CKA_CLASS, NULL, 0 }, 598 { CKA_TOKEN, NULL, 0 }, 599 { CKA_SUBJECT, NULL, 0 }, 600 { CKA_NSS_EMAIL, NULL, 0 }, 601 { CKA_NSS_SMIME_TIMESTAMP, NULL, 0 }, 602 { CKA_VALUE, NULL, 0 } 603 }; 604 /* if you change the array, change the variable below as well */ 605 int realSize = 0; 606 CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE; 607 CK_ATTRIBUTE *attrs = theTemplate; 608 CK_SESSION_HANDLE rwsession; 609 PK11SlotInfo *free_slot = NULL; 610 CK_RV crv; 611 #ifdef DEBUG 612 int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]); 613 #endif 614 615 PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass)); 616 attrs++; 617 PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true)); 618 attrs++; 619 PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len); 620 attrs++; 621 PK11_SETATTRS(attrs, CKA_NSS_EMAIL, 622 emailAddr, PORT_Strlen(emailAddr) + 1); 623 attrs++; 624 if (profileTime) { 625 PK11_SETATTRS(attrs, CKA_NSS_SMIME_TIMESTAMP, profileTime->data, 626 profileTime->len); 627 attrs++; 628 PK11_SETATTRS(attrs, CKA_VALUE, emailProfile->data, 629 emailProfile->len); 630 attrs++; 631 } 632 realSize = attrs - theTemplate; 633 PORT_Assert(realSize <= tsize); 634 635 if (slot == NULL) { 636 free_slot = slot = PK11_GetInternalKeySlot(); 637 /* we need to free the key slot in the end!!! */ 638 } 639 640 rwsession = PK11_GetRWSession(slot); 641 if (rwsession == CK_INVALID_HANDLE) { 642 PORT_SetError(SEC_ERROR_READ_ONLY); 643 if (free_slot) { 644 PK11_FreeSlot(free_slot); 645 } 646 return SECFailure; 647 } 648 649 crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, theTemplate, realSize, &smimeh); 650 if (crv != CKR_OK) { 651 PORT_SetError(PK11_MapError(crv)); 652 } 653 654 PK11_RestoreROSession(slot, rwsession); 655 656 if (free_slot) { 657 PK11_FreeSlot(free_slot); 658 } 659 return SECSuccess; 660 } 661 662 CERTSignedCrl *crl_storeCRL(PK11SlotInfo *slot, char *url, 663 CERTSignedCrl *newCrl, SECItem *derCrl, int type); 664 665 /* import the CRL into the token */ 666 667 CERTSignedCrl * 668 PK11_ImportCRL(PK11SlotInfo *slot, SECItem *derCRL, char *url, 669 int type, void *wincx, PRInt32 importOptions, PLArenaPool *arena, 670 PRInt32 decodeoptions) 671 { 672 CERTSignedCrl *newCrl, *crl; 673 SECStatus rv; 674 CERTCertificate *caCert = NULL; 675 676 newCrl = crl = NULL; 677 678 do { 679 newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type, 680 decodeoptions); 681 if (newCrl == NULL) { 682 if (type == SEC_CRL_TYPE) { 683 /* only promote error when the error code is too generic */ 684 if (PORT_GetError() == SEC_ERROR_BAD_DER) 685 PORT_SetError(SEC_ERROR_CRL_INVALID); 686 } else { 687 PORT_SetError(SEC_ERROR_KRL_INVALID); 688 } 689 break; 690 } 691 692 if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)) { 693 CERTCertDBHandle *handle = CERT_GetDefaultCertDB(); 694 PR_ASSERT(handle != NULL); 695 caCert = CERT_FindCertByName(handle, 696 &newCrl->crl.derName); 697 if (caCert == NULL) { 698 PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER); 699 break; 700 } 701 702 /* If caCert is a v3 certificate, make sure that it can be used for 703 crl signing purpose */ 704 rv = CERT_CheckCertUsage(caCert, KU_CRL_SIGN); 705 if (rv != SECSuccess) { 706 break; 707 } 708 709 rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert, 710 PR_Now(), wincx); 711 if (rv != SECSuccess) { 712 if (type == SEC_CRL_TYPE) { 713 PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE); 714 } else { 715 PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE); 716 } 717 break; 718 } 719 } 720 721 crl = crl_storeCRL(slot, url, newCrl, derCRL, type); 722 723 } while (0); 724 725 if (crl == NULL) { 726 SEC_DestroyCrl(newCrl); 727 } 728 if (caCert) { 729 CERT_DestroyCertificate(caCert); 730 } 731 return (crl); 732 }