nss_spi.c revision 5051:cbbb7c8b40a9
1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* 22 * NSS keystore wrapper 23 * 24 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28#pragma ident "%Z%%M% %I% %E% SMI" 29 30#include <sys/types.h> 31#include <sys/stat.h> 32#include <errno.h> 33#include <fcntl.h> 34#include <synch.h> 35 36#include <kmfapiP.h> 37#include <ber_der.h> 38/* NSS related headers */ 39 40#include <mps/nss.h> 41#include <mps/cert.h> 42#include <mps/certdb.h> 43#include <mps/secoid.h> 44#include <mps/secder.h> 45#include <mps/secerr.h> 46#include <mps/cryptohi.h> 47#include <mps/keyhi.h> 48#include <mps/keythi.h> 49#include <mps/pk11func.h> 50#include <mps/pk11pqg.h> 51#include <mps/pkcs12.h> 52#include <mps/p12plcy.h> 53#include <mps/prerror.h> 54 55#define NSS_OK 0 56 57mutex_t init_lock = DEFAULTMUTEX; 58static int nss_initialized = 0; 59 60KMF_RETURN 61NSS_ConfigureKeystore(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 62 63KMF_RETURN 64NSS_FindCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 65 66void 67NSS_FreeKMFCert(KMF_HANDLE_T, KMF_X509_DER_CERT *); 68 69KMF_RETURN 70NSS_StoreCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 71 72KMF_RETURN 73NSS_ImportCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 74 75KMF_RETURN 76NSS_DeleteCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 77 78KMF_RETURN 79NSS_CreateKeypair(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 80 81KMF_RETURN 82NSS_StoreKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 83 84KMF_RETURN 85NSS_EncodePubKeyData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_DATA *); 86 87KMF_RETURN 88NSS_SignData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 89 KMF_DATA *, KMF_DATA *); 90 91KMF_RETURN 92NSS_ImportCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 93 94KMF_RETURN 95NSS_DeleteCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 96 97KMF_RETURN 98NSS_FindCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 99 100KMF_RETURN 101NSS_FindKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 102 103KMF_RETURN 104NSS_FindCertInCRL(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 105 106KMF_RETURN 107NSS_GetErrorString(KMF_HANDLE_T, char **); 108 109KMF_RETURN 110NSS_DeleteKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 111 112KMF_RETURN 113NSS_FindPrikeyByCert(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 114 115KMF_RETURN 116NSS_DecryptData(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_OID *, 117 KMF_DATA *, KMF_DATA *); 118 119KMF_RETURN 120NSS_ExportPK12(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 121 122KMF_RETURN 123NSS_CreateSymKey(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 124 125KMF_RETURN 126NSS_GetSymKeyValue(KMF_HANDLE_T, KMF_KEY_HANDLE *, KMF_RAW_SYM_KEY *); 127 128KMF_RETURN 129NSS_SetTokenPin(KMF_HANDLE_T, int, KMF_ATTRIBUTE *); 130 131static 132KMF_PLUGIN_FUNCLIST nss_plugin_table = 133{ 134 1, /* Version */ 135 NSS_ConfigureKeystore, 136 NSS_FindCert, 137 NSS_FreeKMFCert, 138 NSS_StoreCert, 139 NSS_ImportCert, 140 NSS_ImportCRL, 141 NSS_DeleteCert, 142 NSS_DeleteCRL, 143 NSS_CreateKeypair, 144 NSS_FindKey, 145 NSS_EncodePubKeyData, 146 NSS_SignData, 147 NSS_DeleteKey, 148 NULL /* ListCRL */, 149 NSS_FindCRL, 150 NSS_FindCertInCRL, 151 NSS_GetErrorString, 152 NSS_FindPrikeyByCert, 153 NSS_DecryptData, 154 NSS_ExportPK12, 155 NSS_CreateSymKey, 156 NSS_GetSymKeyValue, 157 NSS_SetTokenPin, 158 NULL, /* VerifyData */ 159 NSS_StoreKey, 160 NULL /* Finalize */ 161}; 162 163/* additions for importing and exporting PKCS 12 files */ 164typedef struct p12uContextStr { 165 char *filename; /* name of file */ 166 PRFileDesc *file; /* pointer to file */ 167 PRBool error; /* error occurred? */ 168 int errorValue; /* which error occurred? */ 169} p12uContext; 170 171#define SET_ERROR(h, c) h->lasterr.kstype = KMF_KEYSTORE_NSS; \ 172 h->lasterr.errcode = c; 173 174KMF_PLUGIN_FUNCLIST * 175KMF_Plugin_Initialize() 176{ 177 SEC_PKCS12EnableCipher(PKCS12_RC4_40, 1); 178 SEC_PKCS12EnableCipher(PKCS12_RC4_128, 1); 179 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_40, 1); 180 SEC_PKCS12EnableCipher(PKCS12_RC2_CBC_128, 1); 181 SEC_PKCS12EnableCipher(PKCS12_DES_56, 1); 182 SEC_PKCS12EnableCipher(PKCS12_DES_EDE3_168, 1); 183 SEC_PKCS12SetPreferredCipher(PKCS12_DES_EDE3_168, 1); 184 185 return (&nss_plugin_table); 186} 187 188static char * 189/*ARGSUSED*/ 190nss_getpassword(PK11SlotInfo *slot, PRBool retry, void *arg) 191{ 192 if (retry) 193 return (NULL); 194 if (arg != NULL) 195 return ((char *)strdup(arg)); 196 else 197 return (NULL); 198} 199 200static KMF_RETURN 201nss_authenticate(KMF_HANDLE_T handle, 202 PK11SlotInfo *nss_slot, KMF_CREDENTIAL *cred) 203{ 204 205 SECStatus nssrv = SECSuccess; 206 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 207 208 /* If a password was given, try to login to the slot */ 209 if (cred == NULL || cred->cred == NULL || cred->credlen == 0 || 210 nss_slot == NULL) { 211 return (KMF_ERR_BAD_PARAMETER); 212 } 213 214 if (PK11_IsLoggedIn(nss_slot, NULL)) { 215 return (KMF_OK); 216 } 217 218 PK11_SetPasswordFunc(nss_getpassword); 219 nssrv = PK11_Authenticate(nss_slot, PR_TRUE, (void *)cred->cred); 220 221 if (nssrv != SECSuccess) { 222 SET_ERROR(kmfh, nssrv); 223 PK11_FreeSlot(nss_slot); 224 return (KMF_ERR_AUTH_FAILED); 225 } 226 227 return (KMF_OK); 228} 229 230static SECStatus 231Init_NSS_DBs(const char *configdir, 232 const char *certPrefix, 233 const char *keyPrefix, 234 const char *secmodName) 235{ 236 SECStatus rv = NSS_OK; 237 238 (void) mutex_lock(&init_lock); 239 240 /* If another thread already did it, return OK. */ 241 if (nss_initialized) { 242 (void) mutex_unlock(&init_lock); 243 return (SECSuccess); 244 } 245 246 rv = NSS_Initialize((configdir && strlen(configdir)) ? 247 configdir : "./", certPrefix, keyPrefix, 248 secmodName ? secmodName : "secmod.db", NSS_INIT_COOPERATE); 249 if (rv != SECSuccess) { 250 goto end; 251 } 252 253 nss_initialized++; 254end: 255 (void) mutex_unlock(&init_lock); 256 return (rv); 257} 258 259/* 260 * When it is called the first time, it will intialize NSS. Once the NSS 261 * is initialized, this function returns KMF_KEYSTORE_ALREADY_INITIALIZED 262 * if it is called again. 263 */ 264KMF_RETURN 265NSS_ConfigureKeystore(KMF_HANDLE_T handle, 266 int numattr, KMF_ATTRIBUTE *attrlist) 267{ 268 KMF_RETURN rv = KMF_OK; 269 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 270 char *configdir; 271 char *certPrefix; 272 char *keyPrefix; 273 char *secModName; 274 275 configdir = kmf_get_attr_ptr(KMF_DIRPATH_ATTR, attrlist, numattr); 276 certPrefix = kmf_get_attr_ptr(KMF_CERTPREFIX_ATTR, attrlist, numattr); 277 keyPrefix = kmf_get_attr_ptr(KMF_KEYPREFIX_ATTR, attrlist, numattr); 278 secModName = kmf_get_attr_ptr(KMF_SECMODNAME_ATTR, attrlist, numattr); 279 280 (void) mutex_lock(&init_lock); 281 if (nss_initialized == 0) { 282 SECStatus err; 283 284 (void) mutex_unlock(&init_lock); 285 err = Init_NSS_DBs(configdir, certPrefix, 286 keyPrefix, secModName); 287 if (err != SECSuccess) { 288 SET_ERROR(kmfh, err); 289 return (KMF_ERR_INTERNAL); 290 } 291 } else { 292 rv = KMF_KEYSTORE_ALREADY_INITIALIZED; 293 (void) mutex_unlock(&init_lock); 294 } 295 296 return (rv); 297} 298 299/* 300 * This function sets up the slot to be used for other operations. 301 * This function is basically called by every NSS SPI function. 302 * For those functions that can only be performed in the internal slot, the 303 * boolean "internal_slot_only" argument needs to be TRUE. 304 * A slot pointer will be returned when this function is executed successfully. 305 */ 306KMF_RETURN 307do_nss_init(void *handle, int numattr, 308 KMF_ATTRIBUTE *attrlist, 309 boolean_t internal_slot_only, 310 PK11SlotInfo **nss_slot) 311{ 312 KMF_RETURN rv = KMF_OK; 313 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 314 char *slotlabel = NULL; 315 316 if (!nss_initialized) 317 return (KMF_ERR_PLUGIN_INIT); 318 319 slotlabel = kmf_get_attr_ptr(KMF_TOKEN_LABEL_ATTR, attrlist, numattr); 320 /* 321 * NSS Is already initialized, but we need to find 322 * the right slot. 323 */ 324 if (slotlabel == NULL || 325 strcmp(slotlabel, "internal") == 0) { 326 *nss_slot = PK11_GetInternalKeySlot(); 327 } else if (internal_slot_only == TRUE) { 328 rv = KMF_ERR_SLOTNAME; 329 goto end; 330 } else { 331 *nss_slot = PK11_FindSlotByName(slotlabel); 332 } 333 334 if (*nss_slot == NULL) { 335 SET_ERROR(kmfh, PORT_GetError()); 336 rv = KMF_ERR_SLOTNAME; 337 goto end; 338 } 339 340 /* 341 * If the token was not yet initialized, return an error. 342 */ 343 if (PK11_NeedUserInit(*nss_slot)) { 344 rv = KMF_ERR_UNINITIALIZED_TOKEN; 345 } 346 347end: 348 return (rv); 349} 350 351static KMF_RETURN 352nss2kmf_cert(CERTCertificate *nss_cert, KMF_X509_DER_CERT *kmf_cert) 353{ 354 kmf_cert->kmf_private.keystore_type = KMF_KEYSTORE_NSS; 355 kmf_cert->kmf_private.flags = KMF_FLAG_CERT_VALID; 356 357 kmf_cert->certificate.Length = nss_cert->derCert.len; 358 359 if ((kmf_cert->certificate.Data = malloc(nss_cert->derCert.len)) == 360 NULL) { 361 kmf_cert->certificate.Length = 0; 362 return (KMF_ERR_MEMORY); 363 } 364 (void) memcpy(kmf_cert->certificate.Data, nss_cert->derCert.data, 365 nss_cert->derCert.len); 366 if (nss_cert->nickname != NULL) 367 kmf_cert->kmf_private.label = 368 (char *)strdup(nss_cert->nickname); 369 return (KMF_OK); 370} 371 372static KMF_RETURN 373nss_getcert_by_label(KMF_HANDLE *kmfh, 374 char *name, KMF_X509_DER_CERT *kmf_cert, 375 uint32_t *num_certs, KMF_CERT_VALIDITY find_criteria) 376{ 377 KMF_RETURN rv = KMF_OK; 378 CERTCertificate *nss_cert; 379 SECCertTimeValidity validity; 380 381 nss_cert = PK11_FindCertFromNickname(name, NULL); 382 if (nss_cert == NULL) { 383 *num_certs = 0; 384 SET_ERROR(kmfh, PORT_GetError()); 385 *num_certs = 0; 386 return (KMF_ERR_CERT_NOT_FOUND); 387 } else { 388 *num_certs = 1; 389 } 390 391 switch (find_criteria) { 392 case KMF_ALL_CERTS: 393 break; 394 case KMF_NONEXPIRED_CERTS: 395 validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(), 396 PR_FALSE); 397 if (validity != secCertTimeValid) { 398 /* this is an invalid cert, reject it */ 399 *num_certs = 0; 400 CERT_DestroyCertificate(nss_cert); 401 return (KMF_OK); 402 } 403 break; 404 case KMF_EXPIRED_CERTS: 405 validity = CERT_CheckCertValidTimes(nss_cert, PR_Now(), 406 PR_FALSE); 407 if (validity == secCertTimeValid) { 408 /* this is a valid cert, reject it in this case. */ 409 *num_certs = 0; 410 CERT_DestroyCertificate(nss_cert); 411 return (KMF_OK); 412 } 413 break; 414 default: 415 return (KMF_ERR_BAD_PARAMETER); 416 } 417 418 if (kmf_cert != NULL) 419 rv = nss2kmf_cert(nss_cert, kmf_cert); 420 421 /* We copied the data we need, so cleanup the internal record */ 422 CERT_DestroyCertificate(nss_cert); 423 424 if (rv != KMF_OK) 425 *num_certs = 0; 426 427 return (rv); 428} 429 430static KMF_RETURN 431nss_find_matching_certs(PK11SlotInfo *slot, 432 char *issuer, char *subject, KMF_BIGINT *serial, 433 CERTCertList **certlist, KMF_CERT_VALIDITY find_criteria) 434{ 435 KMF_RETURN rv = KMF_OK; 436 SECStatus ret; 437 CERTCertList *list; 438 CERTCertListNode *node; 439 KMF_X509_NAME issuerDN, subjectDN; 440 boolean_t findIssuer = FALSE; 441 boolean_t findSubject = FALSE; 442 boolean_t findSerial = FALSE; 443 444 if (issuer != NULL && strlen(issuer)) { 445 rv = kmf_dn_parser(issuer, &issuerDN); 446 if (rv != KMF_OK) 447 return (rv); 448 findIssuer = TRUE; 449 } 450 if (subject != NULL && strlen(subject)) { 451 rv = kmf_dn_parser(subject, &subjectDN); 452 if (rv != KMF_OK) 453 return (rv); 454 findSubject = TRUE; 455 } 456 if (serial != 0 && serial->val != NULL && serial->len > 0) 457 findSerial = TRUE; 458 459 list = PK11_ListCertsInSlot(slot); 460 if (list) { 461 node = CERT_LIST_HEAD(list); 462 while (!CERT_LIST_END(node, list)) { 463 KMF_X509_NAME cmpDN; 464 KMF_DATA der; 465 boolean_t match; 466 CERTCertListNode *freenode; 467 468 if (findIssuer) { 469 der.Data = node->cert->derIssuer.data; 470 der.Length = node->cert->derIssuer.len; 471 rv = DerDecodeName(&der, &cmpDN); 472 if (rv == KMF_OK) { 473 match = !KMF_CompareRDNs(&issuerDN, 474 &cmpDN); 475 kmf_free_dn(&cmpDN); 476 if (!match) 477 goto delete_and_cont; 478 } else { 479 goto delete_and_cont; 480 } 481 } 482 if (findSubject) { 483 der.Data = node->cert->derSubject.data; 484 der.Length = node->cert->derSubject.len; 485 rv = DerDecodeName(&der, &cmpDN); 486 if (rv == KMF_OK) { 487 match = !KMF_CompareRDNs(&subjectDN, 488 &cmpDN); 489 kmf_free_dn(&cmpDN); 490 if (!match) 491 goto delete_and_cont; 492 } else { 493 goto delete_and_cont; 494 } 495 } 496 if (findSerial) { 497 SECItem *sernum; 498 499 sernum = &node->cert->serialNumber; 500 501 if (serial->len != sernum->len) 502 goto delete_and_cont; 503 504 if (memcmp(sernum->data, serial->val, 505 serial->len)) 506 goto delete_and_cont; 507 } 508 509 /* select the certs using find criteria */ 510 switch (find_criteria) { 511 case KMF_ALL_CERTS: 512 break; 513 case KMF_NONEXPIRED_CERTS: 514 ret = CERT_CertTimesValid(node->cert); 515 if (ret == SECFailure) { 516 /* this is an invalid cert */ 517 goto skip; 518 } 519 break; 520 521 case KMF_EXPIRED_CERTS: 522 ret = CERT_CertTimesValid(node->cert); 523 if (ret != SECFailure) { 524 /* this is a valid cert */ 525 goto skip; 526 } 527 break; 528 } 529skip: 530 node = CERT_LIST_NEXT(node); 531 continue; 532delete_and_cont: 533 freenode = node; 534 node = CERT_LIST_NEXT(node); 535 CERT_RemoveCertListNode(freenode); 536 } 537 } 538 539 if (rv == KMF_OK && certlist != NULL) { 540 *certlist = list; 541 } else { 542 CERT_DestroyCertList(list); 543 } 544 return (rv); 545} 546 547static KMF_RETURN 548convertCertList(void *kmfhandle, 549 CERTCertList *nsscerts, KMF_X509_DER_CERT *kmfcerts, 550 uint32_t *numcerts) 551{ 552 KMF_RETURN rv = KMF_OK; 553 CERTCertListNode *node; 554 uint32_t maxcerts = *numcerts; 555 556 maxcerts = *numcerts; 557 if (maxcerts == 0) 558 maxcerts = 0xFFFFFFFF; 559 560 *numcerts = 0; 561 562 /* 563 * Don't copy more certs than the caller wanted. 564 */ 565 for (node = CERT_LIST_HEAD(nsscerts); 566 !CERT_LIST_END(node, nsscerts) && rv == KMF_OK && 567 (*numcerts) < maxcerts; 568 node = CERT_LIST_NEXT(node), (*numcerts)++) { 569 if (kmfcerts != NULL) 570 rv = nss2kmf_cert(node->cert, &kmfcerts[*numcerts]); 571 } 572 573 /* 574 * If we failed, delete any certs allocated so far. 575 */ 576 if (rv != KMF_OK) { 577 int i; 578 for (i = 0; i < *numcerts; i++) 579 kmf_free_kmf_cert(kmfhandle, &kmfcerts[i]); 580 581 *numcerts = 0; 582 } 583 return (rv); 584} 585 586KMF_RETURN 587NSS_FindCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 588{ 589 KMF_RETURN rv = KMF_OK; 590 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 591 PK11SlotInfo *nss_slot = NULL; 592 CERTCertList *certlist = NULL; 593 uint32_t maxcerts; 594 uint32_t *num_certs; 595 KMF_X509_DER_CERT *kmfcerts = NULL; 596 char *certlabel = NULL; 597 char *issuer = NULL; 598 char *subject = NULL; 599 KMF_BIGINT *serial = NULL; 600 KMF_CERT_VALIDITY validity; 601 602 if (handle == NULL || attrlist == NULL || numattr == 0) { 603 return (KMF_ERR_BAD_PARAMETER); 604 } 605 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 606 if (rv != KMF_OK) 607 return (rv); 608 609 num_certs = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 610 if (num_certs == NULL) 611 return (KMF_ERR_BAD_PARAMETER); 612 613 maxcerts = *num_certs; 614 if (maxcerts == 0) 615 maxcerts = 0xFFFFFFFF; 616 *num_certs = 0; 617 618 /* Get the optional returned certificate list */ 619 kmfcerts = kmf_get_attr_ptr(KMF_X509_DER_CERT_ATTR, attrlist, numattr); 620 621 /* Get optional search criteria attributes */ 622 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr); 623 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 624 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 625 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 626 627 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 628 &validity, NULL); 629 if (rv != KMF_OK) { 630 validity = KMF_ALL_CERTS; 631 rv = KMF_OK; 632 } 633 634 if (certlabel != NULL) { 635 /* This will only find 1 certificate */ 636 rv = nss_getcert_by_label(kmfh, certlabel, kmfcerts, num_certs, 637 validity); 638 } else { 639 /* 640 * Build a list of matching certs. 641 */ 642 rv = nss_find_matching_certs(nss_slot, issuer, subject, serial, 643 &certlist, validity); 644 645 /* 646 * If the caller supplied a pointer to storage for 647 * a list of certs, convert up to 'maxcerts' of the 648 * matching certs. 649 */ 650 if (rv == KMF_OK && certlist != NULL) { 651 rv = convertCertList(handle, certlist, kmfcerts, 652 &maxcerts); 653 CERT_DestroyCertList(certlist); 654 if (rv == KMF_OK) 655 *num_certs = maxcerts; 656 } 657 } 658 659 if (nss_slot != NULL) { 660 PK11_FreeSlot(nss_slot); 661 } 662 663 if (rv == KMF_OK && *num_certs == 0) 664 rv = KMF_ERR_CERT_NOT_FOUND; 665 666 return (rv); 667} 668 669void 670/*ARGSUSED*/ 671NSS_FreeKMFCert(KMF_HANDLE_T handle, 672 KMF_X509_DER_CERT *kmf_cert) 673{ 674 if (kmf_cert != NULL) { 675 if (kmf_cert->certificate.Data != NULL) { 676 free(kmf_cert->certificate.Data); 677 kmf_cert->certificate.Data = NULL; 678 kmf_cert->certificate.Length = 0; 679 } 680 if (kmf_cert->kmf_private.label != NULL) { 681 free(kmf_cert->kmf_private.label); 682 kmf_cert->kmf_private.label = NULL; 683 } 684 } 685} 686 687 688KMF_RETURN 689NSS_DeleteCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 690{ 691 KMF_RETURN rv = KMF_OK; 692 int nssrv; 693 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 694 CERTCertificate *cert = NULL; 695 PK11SlotInfo *nss_slot = NULL; 696 char *certlabel = NULL; 697 char *issuer = NULL; 698 char *subject = NULL; 699 KMF_BIGINT *serial = NULL; 700 KMF_CERT_VALIDITY validity; 701 702 if (handle == NULL || attrlist == NULL || numattr == 0) { 703 return (KMF_ERR_BAD_PARAMETER); 704 } 705 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 706 if (rv != KMF_OK) 707 return (rv); 708 709 /* Get the search criteria attributes. They are all optional. */ 710 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr); 711 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 712 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 713 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 714 715 rv = kmf_get_attr(KMF_CERT_VALIDITY_ATTR, attrlist, numattr, 716 &validity, NULL); 717 if (rv != KMF_OK) { 718 validity = KMF_ALL_CERTS; 719 rv = KMF_OK; 720 } 721 722 /* Start finding the matched certificates and delete them. */ 723 if (certlabel != NULL) { 724 cert = PK11_FindCertFromNickname(certlabel, NULL); 725 if (cert == NULL) { 726 return (KMF_ERR_CERT_NOT_FOUND); 727 } 728 729 switch (validity) { 730 case KMF_ALL_CERTS: 731 break; 732 case KMF_NONEXPIRED_CERTS: 733 nssrv = CERT_CertTimesValid(cert); 734 if (nssrv == SECFailure) { 735 /* this is an invalid cert - skip it */ 736 goto out; 737 } 738 break; 739 case KMF_EXPIRED_CERTS: 740 nssrv = CERT_CertTimesValid(cert); 741 if (nssrv != SECFailure) { 742 /* this is a valid cert - skip it */ 743 goto out; 744 } 745 break; 746 } 747 /* delete it from database */ 748 nssrv = SEC_DeletePermCertificate(cert); 749 if (nssrv) { 750 SET_ERROR(kmfh, nssrv); 751 rv = KMF_ERR_INTERNAL; 752 } 753 } else { 754 CERTCertListNode *node; 755 CERTCertList *certlist = NULL; 756 757 rv = nss_find_matching_certs(nss_slot, issuer, subject, serial, 758 &certlist, validity); 759 760 for (node = CERT_LIST_HEAD(certlist); 761 !CERT_LIST_END(node, certlist) && rv == KMF_OK; 762 node = CERT_LIST_NEXT(node)) { 763 764 nssrv = SEC_DeletePermCertificate(node->cert); 765 if (nssrv) { 766 SET_ERROR(kmfh, nssrv); 767 rv = KMF_ERR_INTERNAL; 768 } 769 } 770 771 if (rv == KMF_OK && certlist != NULL) { 772 CERT_DestroyCertList(certlist); 773 } else if (rv == KMF_OK && certlist == NULL) { 774 rv = KMF_ERR_CERT_NOT_FOUND; 775 } 776 } 777out: 778 if (nss_slot != NULL) { 779 PK11_FreeSlot(nss_slot); 780 } 781 782 if (cert != NULL) { 783 CERT_DestroyCertificate(cert); 784 } 785 786 return (rv); 787} 788 789static void 790InitRandom(char *filename) 791{ 792 char buf[2048]; 793 int fd; 794 PRInt32 count; 795 796 fd = open(filename, O_RDONLY); 797 if (!fd) 798 return; 799 800 count = read(fd, buf, sizeof (buf)); 801 if (count > 0) { 802 PK11_RandomUpdate(buf, count); 803 } 804 805 (void) close(fd); 806} 807 808KMF_RETURN 809NSS_CreateKeypair(KMF_HANDLE_T handle, 810 int numattr, KMF_ATTRIBUTE *attrlist) 811{ 812 KMF_RETURN rv = KMF_OK; 813 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 814 PK11RSAGenParams rsaparams; 815 void *nssparams; 816 CK_MECHANISM_TYPE mechanism; 817 ulong_t publicExponent = 0x010001; 818 PK11SlotInfo *nss_slot = NULL; 819 SECKEYPrivateKey *NSSprivkey = NULL; 820 SECKEYPublicKey *NSSpubkey = NULL; 821 PQGParams *pqgParams = NULL; 822 KMF_CREDENTIAL cred; 823 boolean_t storekey = TRUE; 824 uint32_t keylen = 1024, len; 825 uint32_t keylen_size = sizeof (uint32_t); 826 KMF_KEY_ALG keytype = KMF_RSA; 827 KMF_KEY_HANDLE *pubkey = NULL; 828 KMF_KEY_HANDLE *privkey = NULL; 829 char *keylabel = NULL; 830 831 if (handle == NULL || attrlist == NULL || numattr == 0) { 832 return (KMF_ERR_BAD_PARAMETER); 833 } 834 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 835 if (rv != KMF_OK) { 836 return (rv); 837 } 838 839 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 840 (void *)&cred, NULL); 841 if (rv != KMF_OK) 842 return (rv); 843 844 rv = nss_authenticate(handle, nss_slot, &cred); 845 if (rv != KMF_OK) { 846 return (rv); 847 } 848 849 /* "storekey" is optional. Default is TRUE */ 850 (void) kmf_get_attr(KMF_STOREKEY_BOOL_ATTR, attrlist, numattr, 851 &storekey, NULL); 852 853 /* keytype is optional. KMF_RSA is default */ 854 (void) kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 855 (void *)&keytype, NULL); 856 857 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, 858 &keylen, &keylen_size); 859 if (rv == KMF_ERR_ATTR_NOT_FOUND) 860 /* Default keylen = 1024 */ 861 rv = KMF_OK; 862 else if (rv != KMF_OK) 863 return (KMF_ERR_BAD_PARAMETER); 864 865 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 866 privkey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, numattr); 867 if (pubkey == NULL || privkey == NULL) 868 return (KMF_ERR_BAD_PARAMETER); 869 870 (void) memset(pubkey, 0, sizeof (KMF_KEY_HANDLE)); 871 (void) memset(privkey, 0, sizeof (KMF_KEY_HANDLE)); 872 873 rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr, NULL, &len); 874 if (rv == KMF_OK && len > 0) { 875 keylabel = malloc(len + 1); 876 if (keylabel == NULL) 877 return (KMF_ERR_MEMORY); 878 /* Now fill in the label value */ 879 (void) memset(keylabel, 0, len + 1); 880 rv = kmf_get_attr(KMF_KEYLABEL_ATTR, attrlist, numattr, 881 keylabel, NULL); 882 if (rv != KMF_OK) { 883 free(keylabel); 884 goto cleanup; 885 } 886 } 887 888 /* Get some random bits */ 889 InitRandom("/dev/urandom"); 890 if (keytype == KMF_RSA) { 891 KMF_BIGINT rsaexp; 892 893 rsaparams.keySizeInBits = keylen; 894 /* 895 * NSS only allows for a 4 byte exponent. 896 * Ignore the exponent parameter if it is too big. 897 */ 898 if ((rv = kmf_get_attr(KMF_RSAEXP_ATTR, attrlist, numattr, 899 &rsaexp, NULL)) == KMF_OK) { 900 if (rsaexp.len > 0 && 901 rsaexp.len <= sizeof (publicExponent) && 902 rsaexp.val != NULL) { 903 (void) memcpy(&publicExponent, rsaexp.val, 904 rsaexp.len); 905 } 906 } 907 rsaparams.pe = publicExponent; 908 mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; 909 nssparams = &rsaparams; 910 } else if (keytype == KMF_DSA) { 911 PQGVerify *pqgVerify = NULL; 912 int ks; 913 SECStatus nssrv, passed; 914 915 mechanism = CKM_DSA_KEY_PAIR_GEN; 916 917 ks = PQG_PBITS_TO_INDEX(keylen); 918 nssrv = PK11_PQG_ParamGen(ks, &pqgParams, &pqgVerify); 919 if (nssrv != SECSuccess) { 920 SET_ERROR(kmfh, rv); 921 PK11_PQG_DestroyVerify(pqgVerify); 922 rv = KMF_ERR_KEYGEN_FAILED; 923 goto cleanup; 924 } 925 926 nssrv = PK11_PQG_VerifyParams(pqgParams, pqgVerify, &passed); 927 if (nssrv != SECSuccess || passed != SECSuccess) { 928 SET_ERROR(kmfh, rv); 929 rv = KMF_ERR_KEYGEN_FAILED; 930 } 931 932 PK11_PQG_DestroyVerify(pqgVerify); 933 934 if (rv != KMF_OK) { 935 SET_ERROR(kmfh, PORT_GetError()); 936 goto cleanup; 937 } 938 939 nssparams = pqgParams; 940 } else { 941 rv = KMF_ERR_BAD_PARAMETER; 942 goto cleanup; 943 } 944 945 NSSprivkey = PK11_GenerateKeyPair(nss_slot, mechanism, nssparams, 946 &NSSpubkey, 947 storekey, /* isPermanent */ 948 PR_TRUE, /* isSensitive */ 949 (void *)cred.cred); 950 951 if (NSSprivkey == NULL || NSSpubkey == NULL) { 952 SET_ERROR(kmfh, PORT_GetError()); 953 rv = KMF_ERR_KEYGEN_FAILED; 954 } else { 955 if (keylabel != NULL && strlen(keylabel)) { 956 (void) PK11_SetPrivateKeyNickname(NSSprivkey, 957 keylabel); 958 (void) PK11_SetPublicKeyNickname(NSSpubkey, keylabel); 959 } 960 /* Now, convert it to a KMF_KEY object for the framework */ 961 privkey->kstype = KMF_KEYSTORE_NSS; 962 privkey->keyalg = keytype; 963 privkey->keyclass = KMF_ASYM_PRI; 964 privkey->keylabel = PK11_GetPrivateKeyNickname(NSSprivkey); 965 privkey->keyp = (void *)NSSprivkey; 966 967 pubkey->kstype = KMF_KEYSTORE_NSS; 968 pubkey->keyalg = keytype; 969 pubkey->keyp = (void *)NSSpubkey; 970 pubkey->keyclass = KMF_ASYM_PUB; 971 pubkey->keylabel = PK11_GetPublicKeyNickname(NSSpubkey); 972 973 rv = KMF_OK; 974 } 975cleanup: 976 if (rv != KMF_OK) { 977 if (NSSpubkey) 978 PK11_DeleteTokenPublicKey(NSSpubkey); 979 if (NSSprivkey) 980 PK11_DeleteTokenPrivateKey(NSSprivkey, PR_TRUE); 981 982 privkey->keyp = NULL; 983 pubkey->keyp = NULL; 984 } 985 986 if (keylabel) 987 free(keylabel); 988 989 if (pqgParams != NULL) 990 PK11_PQG_DestroyParams(pqgParams); 991 992 if (nss_slot != NULL) 993 PK11_FreeSlot(nss_slot); 994 995 return (rv); 996} 997 998KMF_RETURN 999NSS_SignData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 1000 KMF_OID *AlgOID, KMF_DATA *tobesigned, 1001 KMF_DATA *output) 1002{ 1003 KMF_RETURN ret = KMF_OK; 1004 KMF_ALGORITHM_INDEX AlgId; 1005 SECOidTag signAlgTag; 1006 SECKEYPrivateKey *NSSprivkey = NULL; 1007 SECStatus rv; 1008 SECItem signed_data; 1009 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1010 1011 signed_data.data = 0; 1012 if (key == NULL || AlgOID == NULL || 1013 tobesigned == NULL || output == NULL || 1014 tobesigned->Data == NULL || 1015 output->Data == NULL) 1016 return (KMF_ERR_BAD_PARAMETER); 1017 1018 /* Map the OID to a NSS algorithm */ 1019 AlgId = x509_algoid_to_algid(AlgOID); 1020 if (AlgId == KMF_ALGID_NONE) 1021 return (KMF_ERR_BAD_PARAMETER); 1022 1023 NSSprivkey = (SECKEYPrivateKey *)key->keyp; 1024 1025 if (AlgId == KMF_ALGID_MD5WithRSA) 1026 signAlgTag = SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION; 1027 else if (AlgId == KMF_ALGID_MD2WithRSA) 1028 signAlgTag = SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION; 1029 else if (AlgId == KMF_ALGID_SHA1WithRSA) 1030 signAlgTag = SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION; 1031 else if (AlgId == KMF_ALGID_SHA1WithDSA) 1032 signAlgTag = SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST; 1033 else 1034 return (KMF_ERR_BAD_PARAMETER); 1035 1036 rv = SEC_SignData(&signed_data, tobesigned->Data, 1037 tobesigned->Length, NSSprivkey, signAlgTag); 1038 1039 if (rv != 0) { 1040 SET_ERROR(kmfh, rv); 1041 return (KMF_ERR_INTERNAL); 1042 } 1043 1044 if (signed_data.len <= output->Length) { 1045 (void) memcpy(output->Data, signed_data.data, signed_data.len); 1046 output->Length = signed_data.len; 1047 } else { 1048 output->Length = 0; 1049 ret = KMF_ERR_BAD_PARAMETER; 1050 } 1051 free(signed_data.data); 1052 1053 return (ret); 1054} 1055 1056KMF_RETURN 1057NSS_EncodePubKeyData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *keyp, 1058 KMF_DATA *encoded) 1059{ 1060 KMF_RETURN ret = KMF_OK; 1061 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1062 SECItem *rvitem; 1063 CERTSubjectPublicKeyInfo *spki = NULL; 1064 1065 if (keyp == NULL || encoded == NULL || keyp->keyp == NULL) 1066 return (KMF_ERR_BAD_PARAMETER); 1067 1068 spki = SECKEY_CreateSubjectPublicKeyInfo(keyp->keyp); 1069 if (spki == NULL) { 1070 SET_ERROR(kmfh, PORT_GetError()); 1071 return (KMF_ERR_MEMORY); 1072 } 1073 1074 rvitem = SEC_ASN1EncodeItem(NULL, NULL, spki, 1075 CERT_SubjectPublicKeyInfoTemplate); 1076 if (rvitem != NULL) { 1077 encoded->Data = malloc(rvitem->len); 1078 if (encoded->Data == NULL) { 1079 ret = KMF_ERR_MEMORY; 1080 } else { 1081 (void) memcpy(encoded->Data, rvitem->data, rvitem->len); 1082 encoded->Length = rvitem->len; 1083 } 1084 SECITEM_FreeItem(rvitem, TRUE); 1085 } else { 1086 SET_ERROR(kmfh, PORT_GetError()); 1087 encoded->Data = NULL; 1088 encoded->Length = 0; 1089 ret = KMF_ERR_ENCODING; 1090 } 1091 SECKEY_DestroySubjectPublicKeyInfo(spki); 1092 1093 return (ret); 1094} 1095 1096KMF_RETURN 1097NSS_DeleteKey(KMF_HANDLE_T handle, 1098 int numattr, KMF_ATTRIBUTE *attrlist) 1099{ 1100 KMF_RETURN rv = KMF_OK; 1101 PK11SlotInfo *nss_slot = NULL; 1102 KMF_KEY_HANDLE *key; 1103 KMF_CREDENTIAL cred; 1104 boolean_t delete_token = B_TRUE; 1105 1106 if (handle == NULL || attrlist == NULL || numattr == 0) { 1107 return (KMF_ERR_BAD_PARAMETER); 1108 } 1109 /* 1110 * "delete_token" means to clear it from the token storage as well 1111 * as from memory. 1112 */ 1113 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 1114 if (key == NULL || key->keyp == NULL) 1115 return (KMF_ERR_BAD_PARAMETER); 1116 1117 rv = kmf_get_attr(KMF_DESTROY_BOOL_ATTR, attrlist, numattr, 1118 (void *)&delete_token, NULL); 1119 if (rv != KMF_OK) 1120 /* "delete_token" is optional. Default is TRUE */ 1121 rv = KMF_OK; 1122 1123 if (delete_token) { 1124 SECStatus nssrv = SECSuccess; 1125 if (key->keyclass != KMF_ASYM_PUB && 1126 key->keyclass != KMF_ASYM_PRI && 1127 key->keyclass != KMF_SYMMETRIC) 1128 return (KMF_ERR_BAD_KEY_CLASS); 1129 1130 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 1131 if (rv != KMF_OK) { 1132 return (rv); 1133 } 1134 1135 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 1136 (void *)&cred, NULL); 1137 if (rv != KMF_OK) 1138 return (KMF_ERR_BAD_PARAMETER); 1139 1140 rv = nss_authenticate(handle, nss_slot, &cred); 1141 if (rv != KMF_OK) { 1142 return (rv); 1143 } 1144 1145 if (key->keyclass == KMF_ASYM_PUB) { 1146 nssrv = PK11_DeleteTokenPublicKey( 1147 (SECKEYPublicKey *)key->keyp); 1148 } else if (key->keyclass == KMF_ASYM_PRI) { 1149 nssrv = PK11_DeleteTokenPrivateKey( 1150 (SECKEYPrivateKey *)key->keyp, PR_TRUE); 1151 } else if (key->keyclass == KMF_SYMMETRIC) { 1152 nssrv = PK11_DeleteTokenSymKey( 1153 (PK11SymKey *) key->keyp); 1154 if (nssrv == SECSuccess) 1155 PK11_FreeSymKey((PK11SymKey *) key->keyp); 1156 } 1157 if (nssrv != SECSuccess) { 1158 SET_ERROR(handle, PORT_GetError()); 1159 rv = KMF_ERR_INTERNAL; 1160 } 1161 } else { 1162 if (key->keyclass == KMF_ASYM_PUB) { 1163 SECKEY_DestroyPublicKey((SECKEYPublicKey *)key->keyp); 1164 } else if (key->keyclass == KMF_ASYM_PRI) { 1165 SECKEY_DestroyPrivateKey((SECKEYPrivateKey *)key->keyp); 1166 } else if (key->keyclass == KMF_SYMMETRIC) { 1167 PK11_FreeSymKey((PK11SymKey *) key->keyp); 1168 } else { 1169 return (KMF_ERR_BAD_KEY_CLASS); 1170 } 1171 } 1172 key->keyp = NULL; 1173 1174 return (rv); 1175} 1176 1177KMF_RETURN 1178NSS_GetErrorString(KMF_HANDLE_T handle, char **msgstr) 1179{ 1180 KMF_RETURN ret = KMF_OK; 1181 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1182 char *str; 1183 1184 /* Get the error string in the default language */ 1185 str = (char *)PR_ErrorToName((PRErrorCode)kmfh->lasterr.errcode); 1186 1187 if (str != NULL) { 1188 *msgstr = (char *)strdup(str); 1189 if ((*msgstr) == NULL) 1190 ret = KMF_ERR_MEMORY; 1191 } else { 1192 *msgstr = NULL; 1193 } 1194 1195 return (ret); 1196} 1197 1198KMF_RETURN 1199NSS_FindPrikeyByCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 1200{ 1201 KMF_RETURN rv = KMF_OK; 1202 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1203 PK11SlotInfo *nss_slot = NULL; 1204 KMF_CREDENTIAL cred; 1205 KMF_KEY_HANDLE *key = NULL; 1206 KMF_DATA *cert = NULL; 1207 CERTCertificate *nss_cert = NULL; 1208 SECKEYPrivateKey* privkey = NULL; 1209 1210 if (handle == NULL || attrlist == NULL || numattr == 0) { 1211 return (KMF_ERR_BAD_PARAMETER); 1212 } 1213 1214 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 1215 if (rv != KMF_OK) 1216 return (rv); 1217 1218 /* Get the credential */ 1219 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 1220 (void *)&cred, NULL); 1221 if (rv != KMF_OK) 1222 return (KMF_ERR_BAD_PARAMETER); 1223 rv = nss_authenticate(handle, nss_slot, &cred); 1224 if (rv != KMF_OK) 1225 return (rv); 1226 1227 /* Get the key handle */ 1228 key = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 1229 if (key == NULL) 1230 return (KMF_ERR_BAD_PARAMETER); 1231 1232 /* Get the cert data and decode it */ 1233 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 1234 if (cert == NULL || cert->Data == NULL) 1235 return (KMF_ERR_BAD_PARAMETER); 1236 1237 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data, 1238 cert->Length); 1239 if (nss_cert == NULL) { 1240 SET_ERROR(kmfh, PORT_GetError()); 1241 return (KMF_ERR_BAD_CERT_FORMAT); 1242 } 1243 1244 privkey = PK11_FindPrivateKeyFromCert(nss_slot, nss_cert, NULL); 1245 if (privkey == NULL) { 1246 SET_ERROR(kmfh, PORT_GetError()); 1247 return (KMF_ERR_KEY_NOT_FOUND); 1248 } 1249 1250 key->kstype = KMF_KEYSTORE_NSS; 1251 key->keyclass = KMF_ASYM_PRI; 1252 key->keyp = (void *)privkey; 1253 key->keylabel = PK11_GetPrivateKeyNickname(privkey); 1254 1255 CERT_DestroyCertificate(nss_cert); 1256 1257 return (KMF_OK); 1258} 1259 1260 1261KMF_RETURN 1262NSS_DecryptData(KMF_HANDLE_T handle, KMF_KEY_HANDLE *key, 1263 KMF_OID *AlgOID, KMF_DATA *ciphertext, 1264 KMF_DATA *output) 1265{ 1266 KMF_RETURN ret = KMF_OK; 1267 SECKEYPrivateKey *NSSprivkey = NULL; 1268 SECStatus rv; 1269 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1270 unsigned int in_len = 0, out_len = 0; 1271 unsigned int total_decrypted = 0, modulus_len = 0; 1272 uint8_t *in_data, *out_data; 1273 int i, blocks; 1274 1275 if (key == NULL || AlgOID == NULL || 1276 ciphertext == NULL || output == NULL || 1277 ciphertext->Data == NULL || 1278 output->Data == NULL) 1279 return (KMF_ERR_BAD_PARAMETER); 1280 1281 NSSprivkey = (SECKEYPrivateKey *)key->keyp; 1282 modulus_len = PK11_GetPrivateModulusLen(NSSprivkey); 1283 1284 blocks = ciphertext->Length/modulus_len; 1285 out_data = output->Data; 1286 in_data = ciphertext->Data; 1287 out_len = modulus_len - 11; 1288 in_len = modulus_len; 1289 1290 for (i = 0; i < blocks; i++) { 1291 rv = PK11_PrivDecryptPKCS1(NSSprivkey, out_data, 1292 &out_len, ciphertext->Length, in_data, in_len); 1293 1294 if (rv != 0) { 1295 SET_ERROR(kmfh, rv); 1296 return (KMF_ERR_INTERNAL); 1297 } 1298 1299 out_data += out_len; 1300 total_decrypted += out_len; 1301 in_data += in_len; 1302 } 1303 1304 output->Length = total_decrypted; 1305 1306 return (ret); 1307} 1308 1309static KMF_KEY_ALG 1310pk11keytype2kmf(CK_KEY_TYPE type) 1311{ 1312 switch (type) { 1313 case CKK_RSA: 1314 return (KMF_RSA); 1315 case CKK_DSA: 1316 return (KMF_RSA); 1317 case CKK_AES: 1318 return (KMF_AES); 1319 case CKK_RC4: 1320 return (KMF_RC4); 1321 case CKK_DES: 1322 return (KMF_DES); 1323 case CKK_DES3: 1324 return (KMF_DES3); 1325 default: 1326 /* not supported */ 1327 return (KMF_KEYALG_NONE); 1328 } 1329} 1330 1331KMF_RETURN 1332NSS_FindKey(KMF_HANDLE_T handle, 1333 int numattr, KMF_ATTRIBUTE *attrlist) 1334{ 1335 KMF_RETURN rv; 1336 SECKEYPrivateKeyList *prilist; 1337 SECKEYPrivateKeyListNode *prinode; 1338 SECKEYPublicKeyList *publist; 1339 SECKEYPublicKeyListNode *pubnode; 1340 PK11SlotInfo *nss_slot = NULL; 1341 PK11SymKey *symlist = NULL; 1342 int count; 1343 uint32_t maxkeys; 1344 KMF_KEY_HANDLE *keys; 1345 uint32_t *numkeys; 1346 KMF_CREDENTIAL cred; 1347 KMF_KEY_CLASS keyclass; 1348 char *findLabel; 1349 KMF_KEY_ALG keytype = KMF_KEYALG_NONE; 1350 1351 if (handle == NULL || attrlist == NULL || numattr == 0) { 1352 return (KMF_ERR_BAD_PARAMETER); 1353 } 1354 1355 numkeys = kmf_get_attr_ptr(KMF_COUNT_ATTR, attrlist, numattr); 1356 if (numkeys == NULL) 1357 return (KMF_ERR_BAD_PARAMETER); 1358 1359 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 1360 if (rv != KMF_OK) { 1361 return (rv); 1362 } 1363 1364 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 1365 (void *)&cred, NULL); 1366 if (rv != KMF_OK) 1367 return (KMF_ERR_BAD_PARAMETER); 1368 1369 rv = nss_authenticate(handle, nss_slot, &cred); 1370 if (rv != KMF_OK) { 1371 return (rv); 1372 } 1373 1374 maxkeys = *numkeys; 1375 if (maxkeys == 0) 1376 maxkeys = 0xFFFFFFFF; 1377 *numkeys = 0; 1378 1379 rv = kmf_get_attr(KMF_KEYCLASS_ATTR, attrlist, numattr, 1380 (void *)&keyclass, NULL); 1381 if (rv != KMF_OK) 1382 return (KMF_ERR_BAD_PARAMETER); 1383 1384 findLabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr); 1385 1386 if (keyclass == KMF_ASYM_PUB) { 1387 publist = PK11_ListPublicKeysInSlot(nss_slot, findLabel); 1388 if (publist == NULL) { 1389 rv = KMF_ERR_KEY_NOT_FOUND; 1390 goto cleanup; 1391 } 1392 } else if (keyclass == KMF_ASYM_PRI) { 1393 prilist = PK11_ListPrivKeysInSlot(nss_slot, findLabel, NULL); 1394 if (prilist == NULL) { 1395 rv = KMF_ERR_KEY_NOT_FOUND; 1396 goto cleanup; 1397 } 1398 } else if (keyclass == KMF_SYMMETRIC) { 1399 symlist = PK11_ListFixedKeysInSlot(nss_slot, findLabel, NULL); 1400 if (symlist == NULL) { 1401 rv = KMF_ERR_KEY_NOT_FOUND; 1402 goto cleanup; 1403 } 1404 } else { 1405 rv = KMF_ERR_BAD_KEY_CLASS; 1406 goto cleanup; 1407 } 1408 1409 keys = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 1410 /* it is okay to have "keys" contains NULL */ 1411 1412 if (keyclass == KMF_ASYM_PUB) { 1413 for (count = 0, pubnode = PUBKEY_LIST_HEAD(publist); 1414 !PUBKEY_LIST_END(pubnode, publist) && count < maxkeys; 1415 pubnode = PUBKEY_LIST_NEXT(pubnode), count++) { 1416 if (keys != NULL) { 1417 keys[count].kstype = KMF_KEYSTORE_NSS; 1418 keys[count].keyclass = KMF_ASYM_PUB; 1419 keys[count].keyp = (void *)pubnode->key; 1420 keys[count].keylabel = 1421 PK11_GetPublicKeyNickname(pubnode->key); 1422 1423 if (pubnode->key->keyType == rsaKey) 1424 keys[count].keyalg = KMF_RSA; 1425 else if (pubnode->key->keyType == dsaKey) 1426 keys[count].keyalg = KMF_DSA; 1427 } 1428 } 1429 *numkeys = count; 1430 } else if (keyclass == KMF_ASYM_PRI) { 1431 for (count = 0, prinode = PRIVKEY_LIST_HEAD(prilist); 1432 !PRIVKEY_LIST_END(prinode, prilist) && count < maxkeys; 1433 prinode = PRIVKEY_LIST_NEXT(prinode), count++) { 1434 if (keys != NULL) { 1435 keys[count].kstype = KMF_KEYSTORE_NSS; 1436 keys[count].keyclass = KMF_ASYM_PRI; 1437 keys[count].keyp = (void *)prinode->key; 1438 keys[count].keylabel = 1439 PK11_GetPrivateKeyNickname(prinode->key); 1440 1441 if (prinode->key->keyType == rsaKey) 1442 keys[count].keyalg = KMF_RSA; 1443 else if (prinode->key->keyType == dsaKey) 1444 keys[count].keyalg = KMF_DSA; 1445 } 1446 } 1447 *numkeys = count; 1448 } else if (keyclass == KMF_SYMMETRIC) { 1449 count = 0; 1450 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, 1451 (void *)&keytype, NULL); 1452 if (rv != KMF_OK) 1453 rv = KMF_OK; 1454 while (symlist && count < maxkeys) { 1455 PK11SymKey *symkey = symlist; 1456 CK_KEY_TYPE type; 1457 KMF_KEY_ALG keyalg; 1458 1459 type = PK11_GetSymKeyType(symkey); 1460 keyalg = pk11keytype2kmf(type); 1461 1462 symlist = PK11_GetNextSymKey(symkey); 1463 1464 /* 1465 * If keytype is specified in the searching parameter, 1466 * check the keytype and skip the key if its keytype 1467 * doesn't match. 1468 */ 1469 if (keytype != KMF_KEYALG_NONE && keytype != keyalg) { 1470 /* free that key since we arent using it */ 1471 PK11_FreeSymKey(symkey); 1472 continue; 1473 } 1474 1475 if (keys != NULL) { 1476 keys[count].kstype = KMF_KEYSTORE_NSS; 1477 keys[count].keyclass = KMF_SYMMETRIC; 1478 keys[count].keyp = (void *) symkey; 1479 keys[count].keylabel = 1480 PK11_GetSymKeyNickname(symkey); 1481 keys[count].keyalg = keyalg; 1482 } else { 1483 PK11_FreeSymKey(symkey); 1484 } 1485 count++; 1486 } 1487 /* 1488 * Cleanup memory for unused keys. 1489 */ 1490 while (symlist != NULL) { 1491 PK11SymKey *symkey = symlist; 1492 1493 PK11_FreeSymKey(symkey); 1494 symlist = PK11_GetNextSymKey(symkey); 1495 } 1496 *numkeys = count; 1497 } 1498 1499cleanup: 1500 if (nss_slot != NULL) { 1501 PK11_FreeSlot(nss_slot); 1502 } 1503 1504 return (rv); 1505} 1506 1507static SECStatus 1508p12u_SwapUnicodeBytes(SECItem *uniItem) 1509{ 1510 unsigned int i; 1511 unsigned char a; 1512 if ((uniItem == NULL) || (uniItem->len % 2)) { 1513 return (SECFailure); 1514 } 1515 for (i = 0; i < uniItem->len; i += 2) { 1516 a = uniItem->data[i]; 1517 uniItem->data[i] = uniItem->data[i+1]; 1518 uniItem->data[i+1] = a; 1519 } 1520 return (SECSuccess); 1521} 1522 1523static PRBool 1524p12u_ucs2_ascii_conversion_function( 1525 PRBool toUnicode, 1526 unsigned char *inBuf, 1527 unsigned int inBufLen, 1528 unsigned char *outBuf, 1529 unsigned int maxOutBufLen, 1530 unsigned int *outBufLen, 1531 PRBool swapBytes) 1532{ 1533 SECItem it = { 0 }; 1534 SECItem *dup = NULL; 1535 PRBool ret; 1536 1537 it.data = inBuf; 1538 it.len = inBufLen; 1539 dup = SECITEM_DupItem(&it); 1540 /* 1541 * If converting Unicode to ASCII, swap bytes before conversion 1542 * as neccessary. 1543 */ 1544 if (!toUnicode && swapBytes) { 1545 if (p12u_SwapUnicodeBytes(dup) != SECSuccess) { 1546 SECITEM_ZfreeItem(dup, PR_TRUE); 1547 return (PR_FALSE); 1548 } 1549 } 1550 /* Perform the conversion. */ 1551 ret = PORT_UCS2_UTF8Conversion(toUnicode, dup->data, dup->len, 1552 outBuf, maxOutBufLen, outBufLen); 1553 if (dup) 1554 SECITEM_ZfreeItem(dup, PR_TRUE); 1555 1556 return (ret); 1557} 1558 1559static PRBool 1560p12u_OpenFile(p12uContext *p12ctx, PRBool fileRead) 1561{ 1562 if (!p12ctx || !p12ctx->filename) { 1563 return (PR_FALSE); 1564 } 1565 1566 if (fileRead) { 1567 p12ctx->file = PR_Open(p12ctx->filename, PR_RDONLY, 0400); 1568 } else { 1569 p12ctx->file = PR_Open(p12ctx->filename, 1570 PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 0600); 1571 } 1572 1573 if (!p12ctx->file) { 1574 p12ctx->error = PR_TRUE; 1575 return (PR_FALSE); 1576 } 1577 1578 return (PR_TRUE); 1579} 1580 1581static void 1582p12u_DestroyContext(p12uContext **ppCtx, PRBool removeFile) 1583{ 1584 if (!ppCtx || !(*ppCtx)) { 1585 return; 1586 } 1587 1588 if ((*ppCtx)->file != NULL) { 1589 PR_Close((*ppCtx)->file); 1590 } 1591 1592 if ((*ppCtx)->filename != NULL) { 1593 if (removeFile) { 1594 PR_Delete((*ppCtx)->filename); 1595 } 1596 free((*ppCtx)->filename); 1597 } 1598 1599 free(*ppCtx); 1600 *ppCtx = NULL; 1601} 1602 1603static p12uContext * 1604p12u_InitContext(PRBool fileImport, char *filename) 1605{ 1606 p12uContext *p12ctx; 1607 1608 p12ctx = PORT_ZNew(p12uContext); 1609 if (!p12ctx) { 1610 return (NULL); 1611 } 1612 1613 p12ctx->error = PR_FALSE; 1614 p12ctx->errorValue = 0; 1615 p12ctx->filename = strdup(filename); 1616 1617 if (!p12u_OpenFile(p12ctx, fileImport)) { 1618 p12u_DestroyContext(&p12ctx, PR_FALSE); 1619 return (NULL); 1620 } 1621 1622 return (p12ctx); 1623} 1624 1625static void 1626p12u_WriteToExportFile(void *arg, const char *buf, unsigned long len) 1627{ 1628 p12uContext *p12cxt = arg; 1629 int writeLen; 1630 1631 if (!p12cxt || (p12cxt->error == PR_TRUE)) { 1632 return; 1633 } 1634 1635 if (p12cxt->file == NULL) { 1636 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE; 1637 p12cxt->error = PR_TRUE; 1638 return; 1639 } 1640 1641 writeLen = PR_Write(p12cxt->file, (unsigned char *)buf, (int32)len); 1642 1643 if (writeLen != (int)len) { 1644 PR_Close(p12cxt->file); 1645 free(p12cxt->filename); 1646 p12cxt->filename = NULL; 1647 p12cxt->file = NULL; 1648 p12cxt->errorValue = SEC_ERROR_PKCS12_UNABLE_TO_WRITE; 1649 p12cxt->error = PR_TRUE; 1650 } 1651} 1652 1653#define HANDLE_NSS_ERROR(r) {\ 1654 SET_ERROR(kmfh, PORT_GetError()); \ 1655 rv = r; \ 1656 goto out; } 1657 1658static KMF_RETURN 1659add_cert_to_bag(SEC_PKCS12ExportContext *p12ecx, 1660 CERTCertificate *cert, SECItem *pwitem) 1661{ 1662 KMF_RETURN rv = KMF_OK; 1663 SEC_PKCS12SafeInfo *keySafe = NULL, *certSafe = NULL; 1664 1665 keySafe = SEC_PKCS12CreateUnencryptedSafe(p12ecx); 1666 if (PK11_IsFIPS()) { 1667 certSafe = keySafe; 1668 } else { 1669 certSafe = SEC_PKCS12CreatePasswordPrivSafe(p12ecx, pwitem, 1670 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC); 1671 } 1672 1673 if (!certSafe || !keySafe) { 1674 rv = KMF_ERR_INTERNAL; 1675 goto out; 1676 } 1677 1678 if (SEC_PKCS12AddCertAndKey(p12ecx, certSafe, NULL, cert, 1679 CERT_GetDefaultCertDB(), keySafe, NULL, PR_TRUE, pwitem, 1680 SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC) 1681 != SECSuccess) { 1682 rv = KMF_ERR_INTERNAL; 1683 } 1684out: 1685 return (rv); 1686} 1687 1688KMF_RETURN 1689NSS_ExportPK12(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 1690{ 1691 KMF_RETURN rv; 1692 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1693 SEC_PKCS12ExportContext *p12ecx = NULL; 1694 p12uContext *p12ctx = NULL; 1695 CERTCertList *certlist = NULL; 1696 CERTCertificate *nsscert = NULL; 1697 CERTCertListNode* node = NULL; 1698 PK11SlotInfo *slot = NULL; 1699 SECItem pwitem = {NULL, 0}; 1700 KMF_CREDENTIAL *cred = NULL; 1701 KMF_CREDENTIAL *p12cred = NULL; 1702 char *certlabel = NULL; 1703 char *issuer = NULL; 1704 char *subject = NULL; 1705 KMF_BIGINT *serial = NULL; 1706 char *filename = NULL; 1707 1708 if (kmfh == NULL || attrlist == NULL || numattr == 0) { 1709 return (KMF_ERR_BAD_PARAMETER); 1710 } 1711 1712 rv = do_nss_init(handle, numattr, attrlist, FALSE, &slot); 1713 if (rv != KMF_OK) 1714 return (rv); 1715 1716 cred = kmf_get_attr_ptr(KMF_CREDENTIAL_ATTR, attrlist, numattr); 1717 if (cred == NULL) 1718 return (KMF_ERR_BAD_PARAMETER); 1719 1720 rv = nss_authenticate(handle, slot, cred); 1721 if (rv != KMF_OK) 1722 return (rv); 1723 1724 p12cred = kmf_get_attr_ptr(KMF_PK12CRED_ATTR, attrlist, numattr); 1725 if (p12cred == NULL) 1726 return (KMF_ERR_BAD_PARAMETER); 1727 1728 filename = kmf_get_attr_ptr(KMF_OUTPUT_FILENAME_ATTR, attrlist, 1729 numattr); 1730 if (filename == NULL) 1731 return (KMF_ERR_BAD_PARAMETER); 1732 1733 /* Get optional search criteria attributes */ 1734 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr); 1735 issuer = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, numattr); 1736 subject = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, numattr); 1737 serial = kmf_get_attr_ptr(KMF_BIGINT_ATTR, attrlist, numattr); 1738 1739 /* 1740 * Find the certificate(s) first. 1741 */ 1742 if (certlabel != NULL) { 1743 nsscert = PK11_FindCertFromNickname(certlabel, NULL); 1744 if (nsscert == NULL) { 1745 HANDLE_NSS_ERROR(KMF_ERR_CERT_NOT_FOUND) 1746 } 1747 } else { 1748 rv = nss_find_matching_certs(slot, issuer, subject, serial, 1749 &certlist, 0); 1750 1751 if (rv == KMF_OK && certlist == NULL) { 1752 return (KMF_ERR_CERT_NOT_FOUND); 1753 } 1754 if (rv != KMF_OK) 1755 return (rv); 1756 } 1757 1758 /* 1759 * The KMF_CREDENTIAL holds the password to use for 1760 * encrypting the PKCS12 key information. 1761 */ 1762 pwitem.data = (uchar_t *)p12cred->cred; 1763 pwitem.len = p12cred->credlen; 1764 1765 p12ctx = p12u_InitContext(PR_FALSE, filename); 1766 if (!p12ctx) { 1767 HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE) 1768 } 1769 1770 PORT_SetUCS2_ASCIIConversionFunction( 1771 p12u_ucs2_ascii_conversion_function); 1772 1773 p12ecx = SEC_PKCS12CreateExportContext(NULL, NULL, slot, NULL); 1774 if (!p12ecx) { 1775 HANDLE_NSS_ERROR(KMF_ERR_OPEN_FILE) 1776 } 1777 1778 if (SEC_PKCS12AddPasswordIntegrity(p12ecx, &pwitem, SEC_OID_SHA1) 1779 != SECSuccess) { 1780 HANDLE_NSS_ERROR(KMF_ERR_INTERNAL) 1781 } 1782 1783 /* 1784 * NSS actually supports storing a list of keys and certs 1785 * in the PKCS#12 PDU. Nice feature. 1786 */ 1787 if (certlist != NULL) { 1788 for (node = CERT_LIST_HEAD(certlist); 1789 !CERT_LIST_END(node, certlist) && rv == KMF_OK; 1790 node = CERT_LIST_NEXT(node)) { 1791 rv = add_cert_to_bag(p12ecx, node->cert, &pwitem); 1792 } 1793 } else if (nsscert != NULL) { 1794 rv = add_cert_to_bag(p12ecx, nsscert, &pwitem); 1795 } 1796 1797 if (SEC_PKCS12Encode(p12ecx, p12u_WriteToExportFile, p12ctx) 1798 != SECSuccess) { 1799 HANDLE_NSS_ERROR(KMF_ERR_ENCODING) 1800 } 1801out: 1802 if (nsscert) 1803 CERT_DestroyCertificate(nsscert); 1804 1805 if (certlist) 1806 CERT_DestroyCertList(certlist); 1807 1808 if (p12ctx) 1809 p12u_DestroyContext(&p12ctx, PR_FALSE); 1810 1811 if (p12ecx) 1812 SEC_PKCS12DestroyExportContext(p12ecx); 1813 1814 return (rv); 1815} 1816 1817#define SETATTR(t, n, atype, value, size) \ 1818 t[n].type = atype; \ 1819 t[n].pValue = (CK_BYTE *)value; \ 1820 t[n].ulValueLen = (CK_ULONG)size; 1821 1822KMF_RETURN 1823NSS_CreateSymKey(KMF_HANDLE_T handle, 1824 int numattr, KMF_ATTRIBUTE *attrlist) 1825{ 1826 KMF_RETURN rv = KMF_OK; 1827 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1828 PK11SlotInfo *nss_slot = NULL; 1829 PK11SymKey *nsskey = NULL; 1830 CK_MECHANISM_TYPE keyType; 1831 SECStatus nssrv; 1832 int keySize; 1833 KMF_KEY_HANDLE *symkey; 1834 KMF_CREDENTIAL cred; 1835 uint32_t keylen; 1836 uint32_t keylen_size = sizeof (uint32_t); 1837 KMF_KEY_ALG keytype; 1838 char *keylabel = NULL; 1839 1840 if (kmfh == NULL || attrlist == NULL || numattr == 0) { 1841 return (KMF_ERR_BAD_PARAMETER); 1842 } 1843 1844 symkey = kmf_get_attr_ptr(KMF_KEY_HANDLE_ATTR, attrlist, numattr); 1845 if (symkey == NULL) 1846 return (KMF_ERR_BAD_PARAMETER); 1847 1848 rv = kmf_get_attr(KMF_KEYALG_ATTR, attrlist, numattr, (void *)&keytype, 1849 NULL); 1850 if (rv != KMF_OK) 1851 return (KMF_ERR_BAD_PARAMETER); 1852 1853 rv = kmf_get_attr(KMF_KEYLENGTH_ATTR, attrlist, numattr, &keylen, 1854 &keylen_size); 1855 if (rv == KMF_ERR_ATTR_NOT_FOUND && 1856 (keytype == KMF_DES || keytype == KMF_DES3)) 1857 /* keylength is not required for DES and 3DES */ 1858 rv = KMF_OK; 1859 if (rv != KMF_OK) 1860 return (KMF_ERR_BAD_PARAMETER); 1861 1862 keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr); 1863 if (keylabel == NULL) 1864 return (KMF_ERR_BAD_PARAMETER); 1865 1866 switch (keytype) { 1867 case KMF_AES: 1868 keyType = CKM_AES_KEY_GEN; 1869 keySize = keylen; 1870 if (keySize == 0 || (keySize % 8) != 0) 1871 return (KMF_ERR_BAD_KEY_SIZE); 1872 break; 1873 case KMF_RC4: 1874 keyType = CKM_RC4_KEY_GEN; 1875 keySize = keylen; 1876 if (keySize == 0 || (keySize % 8) != 0) 1877 return (KMF_ERR_BAD_KEY_SIZE); 1878 break; 1879 case KMF_DES: 1880 keyType = CKM_DES_KEY_GEN; 1881 keySize = 0; /* required by PK11_TokenKeyGen() */ 1882 break; 1883 case KMF_DES3: 1884 keyType = CKM_DES3_KEY_GEN; 1885 keySize = 0; /* required by PK11_TokenKeyGen() */ 1886 break; 1887 case KMF_GENERIC_SECRET: 1888 keyType = CKM_GENERIC_SECRET_KEY_GEN; 1889 keySize = keylen; 1890 if (keySize == 0 || (keySize % 8) != 0) 1891 return (KMF_ERR_BAD_KEY_SIZE); 1892 break; 1893 default: 1894 rv = KMF_ERR_BAD_KEY_TYPE; 1895 goto out; 1896 } 1897 1898 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 1899 if (rv != KMF_OK) { 1900 return (rv); 1901 } 1902 1903 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 1904 (void *)&cred, NULL); 1905 if (rv != KMF_OK) 1906 return (KMF_ERR_BAD_PARAMETER); 1907 1908 rv = nss_authenticate(handle, nss_slot, &cred); 1909 if (rv != KMF_OK) { 1910 return (rv); 1911 } 1912 1913 nsskey = PK11_TokenKeyGen(nss_slot, keyType, NULL, keySize, NULL, 1914 PR_TRUE, (void *)cred.cred); 1915 if (nsskey == NULL) { 1916 SET_ERROR(kmfh, PORT_GetError()); 1917 rv = KMF_ERR_KEYGEN_FAILED; 1918 goto out; 1919 } 1920 1921 nssrv = PK11_SetSymKeyNickname(nsskey, keylabel); 1922 if (nssrv != SECSuccess) { 1923 SET_ERROR(kmfh, PORT_GetError()); 1924 rv = KMF_ERR_KEYGEN_FAILED; 1925 goto out; 1926 } 1927 1928 symkey->kstype = KMF_KEYSTORE_NSS; 1929 symkey->keyalg = keytype; 1930 symkey->keyclass = KMF_SYMMETRIC; 1931 symkey->israw = FALSE; 1932 symkey->keyp = (void *)nsskey; 1933 1934out: 1935 if (nss_slot != NULL) 1936 PK11_FreeSlot(nss_slot); 1937 1938 if (rv != KMF_OK && nsskey != NULL) { 1939 PK11_DeleteTokenSymKey(nsskey); 1940 PK11_FreeSymKey(nsskey); 1941 } 1942 return (rv); 1943} 1944 1945KMF_RETURN 1946NSS_GetSymKeyValue(KMF_HANDLE_T handle, KMF_KEY_HANDLE *symkey, 1947 KMF_RAW_SYM_KEY *rkey) 1948{ 1949 KMF_RETURN rv = KMF_OK; 1950 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 1951 SECItem *value = NULL; 1952 PK11SymKey *nsskey; 1953 SECStatus nss_rv; 1954 1955 if (kmfh == NULL) 1956 return (KMF_ERR_UNINITIALIZED); 1957 1958 if (symkey == NULL || rkey == NULL) 1959 return (KMF_ERR_BAD_PARAMETER); 1960 else if (symkey->keyclass != KMF_SYMMETRIC) 1961 return (KMF_ERR_BAD_KEY_CLASS); 1962 1963 if (symkey->israw) { 1964 KMF_RAW_KEY_DATA *rawkey = (KMF_RAW_KEY_DATA *)symkey->keyp; 1965 1966 if (rawkey == NULL || 1967 rawkey->rawdata.sym.keydata.val == NULL || 1968 rawkey->rawdata.sym.keydata.len == 0) 1969 return (KMF_ERR_BAD_KEYHANDLE); 1970 1971 rkey->keydata.len = rawkey->rawdata.sym.keydata.len; 1972 if ((rkey->keydata.val = malloc(rkey->keydata.len)) == NULL) 1973 return (KMF_ERR_MEMORY); 1974 (void) memcpy(rkey->keydata.val, 1975 rawkey->rawdata.sym.keydata.val, rkey->keydata.len); 1976 } else { 1977 nsskey = (PK11SymKey *)(symkey->keyp); 1978 if (nsskey == NULL) 1979 return (KMF_ERR_BAD_KEYHANDLE); 1980 1981 nss_rv = PK11_ExtractKeyValue(nsskey); 1982 if (nss_rv != SECSuccess) { 1983 SET_ERROR(kmfh, PORT_GetError()); 1984 rv = KMF_ERR_GETKEYVALUE_FAILED; 1985 goto out; 1986 } 1987 1988 value = PK11_GetKeyData(nsskey); 1989 if (value == NULL) { 1990 SET_ERROR(kmfh, PORT_GetError()); 1991 rv = KMF_ERR_GETKEYVALUE_FAILED; 1992 goto out; 1993 } 1994 1995 if (value->len == 0 || value->data == NULL) { 1996 rv = KMF_ERR_GETKEYVALUE_FAILED; 1997 goto out; 1998 } 1999 2000 rkey->keydata.val = malloc(value->len); 2001 if (rkey->keydata.val == NULL) { 2002 rv = KMF_ERR_MEMORY; 2003 goto out; 2004 } 2005 (void) memcpy(rkey->keydata.val, value->data, value->len); 2006 rkey->keydata.len = value->len; 2007 (void) memset(value->data, 0, value->len); 2008 } 2009out: 2010 if (value != NULL) 2011 SECITEM_FreeItem(value, PR_TRUE); 2012 return (rv); 2013} 2014 2015KMF_RETURN 2016NSS_SetTokenPin(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2017{ 2018 KMF_RETURN ret = KMF_OK; 2019 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2020 int rv; 2021 PK11SlotInfo *nss_slot = NULL; 2022 KMF_CREDENTIAL oldcred, newcred; 2023 2024 if (handle == NULL || attrlist == NULL || numattr == 0) 2025 return (KMF_ERR_BAD_PARAMETER); 2026 2027 ret = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 2028 (void *)&oldcred, NULL); 2029 if (ret != KMF_OK) 2030 return (KMF_ERR_BAD_PARAMETER); 2031 ret = kmf_get_attr(KMF_NEWPIN_ATTR, attrlist, numattr, 2032 (void *)&newcred, NULL); 2033 if (ret != KMF_OK) 2034 return (KMF_ERR_BAD_PARAMETER); 2035 2036 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2037 /* If it was uninitialized, set it */ 2038 if (ret == KMF_ERR_UNINITIALIZED_TOKEN) { 2039 rv = PK11_InitPin(nss_slot, NULL, newcred.cred); 2040 if (rv != SECSuccess) { 2041 SET_ERROR(kmfh, PORT_GetError()); 2042 ret = KMF_ERR_AUTH_FAILED; 2043 } else { 2044 ret = KMF_OK; 2045 } 2046 } else if (ret == KMF_OK) { 2047 ret = nss_authenticate(handle, nss_slot, &oldcred); 2048 if (ret != KMF_OK) { 2049 return (ret); 2050 } 2051 rv = PK11_ChangePW(nss_slot, oldcred.cred, newcred.cred); 2052 if (rv != SECSuccess) { 2053 SET_ERROR(kmfh, PORT_GetError()); 2054 ret = KMF_ERR_AUTH_FAILED; 2055 } 2056 } 2057 2058 return (ret); 2059} 2060 2061KMF_RETURN 2062NSS_StoreKey(KMF_HANDLE_T handle, 2063 int numattr, KMF_ATTRIBUTE *attrlist) 2064{ 2065 KMF_RETURN rv = KMF_OK; 2066 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2067 PK11SlotInfo *nss_slot = NULL; 2068 KMF_CREDENTIAL cred = {NULL, 0}; 2069 KMF_KEY_HANDLE *pubkey = NULL, *prikey = NULL; 2070 KMF_RAW_KEY_DATA *rawkey = NULL; 2071 char *keylabel = NULL; 2072 SECStatus ckrv = SECSuccess; 2073 SECItem nickname = {NULL, 0}; 2074 CERTCertificate *nss_cert = NULL; 2075 2076 if (kmfh == NULL || attrlist == NULL || numattr == 0) { 2077 return (KMF_ERR_BAD_PARAMETER); 2078 } 2079 2080 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2081 if (rv != KMF_OK) { 2082 return (rv); 2083 } 2084 2085 rv = kmf_get_attr(KMF_CREDENTIAL_ATTR, attrlist, numattr, 2086 (void *)&cred, NULL); 2087 if (rv != KMF_OK) 2088 return (KMF_ERR_BAD_PARAMETER); 2089 2090 rv = nss_authenticate(handle, nss_slot, &cred); 2091 if (rv != KMF_OK) { 2092 return (rv); 2093 } 2094 2095 pubkey = kmf_get_attr_ptr(KMF_PUBKEY_HANDLE_ATTR, attrlist, numattr); 2096 if (pubkey == NULL) { 2097 /* look for private key */ 2098 prikey = kmf_get_attr_ptr(KMF_PRIVKEY_HANDLE_ATTR, attrlist, 2099 numattr); 2100 if (prikey == NULL) 2101 /* look for raw key */ 2102 rawkey = kmf_get_attr_ptr(KMF_RAW_KEY_ATTR, 2103 attrlist, numattr); 2104 } 2105 2106 /* If no keys were found, return error */ 2107 if (pubkey == NULL && prikey == NULL && rawkey == NULL) 2108 return (KMF_ERR_ATTR_NOT_FOUND); 2109 2110 keylabel = kmf_get_attr_ptr(KMF_KEYLABEL_ATTR, attrlist, numattr); 2111 if (keylabel != NULL) { 2112 nickname.data = (uchar_t *)keylabel; 2113 nickname.len = strlen(keylabel); 2114 } 2115 2116 if (rawkey != NULL) { 2117 uchar_t ver = 0; 2118 SECKEYPrivateKeyInfo rpk; 2119 KMF_DATA derkey = {NULL, 0}; 2120 KMF_DATA *cert; 2121 2122 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 2123 if (cert == NULL) 2124 return (rv); 2125 /* 2126 * Decode the cert into an NSS CERT object so we can access the 2127 * SPKI and KeyUsage data later. 2128 */ 2129 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data, 2130 cert->Length); 2131 2132 if (nss_cert == NULL) { 2133 SET_ERROR(kmfh, PORT_GetError()); 2134 rv = KMF_ERR_BAD_CERT_FORMAT; 2135 goto cleanup; 2136 } 2137 2138 (void) memset(&rpk, 0, sizeof (rpk)); 2139 rpk.arena = NULL; 2140 rpk.version.type = siUnsignedInteger; 2141 rpk.version.data = &ver; 2142 rpk.version.len = 1; 2143 if (rawkey->keytype == KMF_RSA) { 2144 rv = DerEncodeRSAPrivateKey(&derkey, 2145 &rawkey->rawdata.rsa); 2146 if (rv != KMF_OK) 2147 goto cleanup; 2148 2149 } else if (rawkey->keytype == KMF_DSA) { 2150 rv = DerEncodeDSAPrivateKey(&derkey, 2151 &rawkey->rawdata.dsa); 2152 if (rv != KMF_OK) 2153 goto cleanup; 2154 } 2155 rpk.algorithm = nss_cert->subjectPublicKeyInfo.algorithm; 2156 rpk.privateKey.data = derkey.Data; 2157 rpk.privateKey.len = derkey.Length; 2158 rpk.attributes = NULL; 2159 2160 ckrv = PK11_ImportPrivateKeyInfo(nss_slot, &rpk, &nickname, 2161 &nss_cert->subjectPublicKeyInfo.subjectPublicKey, TRUE, 2162 TRUE, nss_cert->keyUsage, NULL); 2163 if (ckrv != CKR_OK) { 2164 SET_ERROR(kmfh, PORT_GetError()); 2165 rv = KMF_ERR_INTERNAL; 2166 } 2167 kmf_free_data(&derkey); 2168 } else if (pubkey != NULL && pubkey->kstype == KMF_KEYSTORE_NSS) { 2169 CK_OBJECT_HANDLE pk; 2170 SECKEYPublicKey *publicKey = (SECKEYPublicKey *) pubkey->keyp; 2171 2172 pk = PK11_ImportPublicKey(nss_slot, publicKey, PR_TRUE); 2173 if (pk == CK_INVALID_HANDLE) { 2174 SET_ERROR(kmfh, PORT_GetError()); 2175 rv = KMF_ERR_INTERNAL; 2176 } 2177 } else if (prikey != NULL && prikey->kstype == KMF_KEYSTORE_NSS) { 2178 SECKEYPrivateKey *pk; 2179 SECKEYPrivateKey *privKey = (SECKEYPrivateKey *) prikey->keyp; 2180 2181 pk = PK11_LoadPrivKey(nss_slot, privKey, NULL, PR_TRUE, 2182 PR_TRUE); 2183 if (pk == CK_INVALID_HANDLE) { 2184 SET_ERROR(kmfh, PORT_GetError()); 2185 rv = KMF_ERR_INTERNAL; 2186 } 2187 /* We stored it, but don't need the handle anymore */ 2188 SECKEY_DestroyPrivateKey(pk); 2189 } 2190 2191cleanup: 2192 if (nss_cert != NULL) 2193 CERT_DestroyCertificate(nss_cert); 2194 PK11_FreeSlot(nss_slot); 2195 return (rv); 2196} 2197 2198/* 2199 * This function is called by NSS_StoreCert() and NSS_ImportCert(). 2200 * The "label" and "trust_flag" arguments can be NULL. 2201 */ 2202static KMF_RETURN 2203store_cert(KMF_HANDLE_T handle, PK11SlotInfo *nss_slot, KMF_DATA *cert, 2204 char *label, char *trust_flag) 2205{ 2206 KMF_RETURN ret = KMF_OK; 2207 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2208 SECStatus nss_rv; 2209 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); 2210 CERTCertificate *nss_cert = NULL; 2211 CERTCertTrust *nss_trust = NULL; 2212 2213 if (nss_slot == NULL || cert == NULL) 2214 return (KMF_ERR_BAD_PARAMETER); 2215 2216 nss_cert = CERT_DecodeCertFromPackage((char *)cert->Data, 2217 cert->Length); 2218 if (nss_cert == NULL) { 2219 SET_ERROR(kmfh, PORT_GetError()); 2220 ret = KMF_ERR_BAD_CERT_FORMAT; 2221 goto out; 2222 } 2223 2224 /* Store the cert into the NSS database */ 2225 nss_rv = PK11_ImportCert(nss_slot, nss_cert, CK_INVALID_HANDLE, 2226 label, 0); 2227 if (nss_rv) { 2228 SET_ERROR(kmfh, nss_rv); 2229 ret = KMF_ERR_BAD_CERT_FORMAT; 2230 goto out; 2231 } 2232 2233 /* If trust_flag is NULL, then we are done */ 2234 if (trust_flag == NULL) 2235 goto out; 2236 2237 nss_trust = (CERTCertTrust *) malloc(sizeof (CERTCertTrust)); 2238 if (nss_trust == NULL) { 2239 ret = KMF_ERR_MEMORY; 2240 goto out; 2241 } 2242 2243 nss_rv = CERT_DecodeTrustString(nss_trust, trust_flag); 2244 if (nss_rv) { 2245 SET_ERROR(kmfh, nss_rv); 2246 ret = KMF_ERR_BAD_PARAMETER; 2247 goto out; 2248 } 2249 2250 nss_rv = CERT_ChangeCertTrust(certHandle, nss_cert, nss_trust); 2251 if (nss_rv) { 2252 SET_ERROR(kmfh, nss_rv); 2253 ret = KMF_ERR_BAD_PARAMETER; 2254 } 2255 2256out: 2257 if (nss_cert != NULL) { 2258 CERT_DestroyCertificate(nss_cert); 2259 } 2260 2261 if (nss_trust != NULL) { 2262 free(nss_trust); 2263 } 2264 2265 return (ret); 2266} 2267 2268 2269KMF_RETURN 2270NSS_StoreCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2271{ 2272 KMF_RETURN ret = KMF_OK; 2273 PK11SlotInfo *nss_slot = NULL; 2274 KMF_DATA *cert = NULL; 2275 char *label = NULL; 2276 char *trust_flag = NULL; 2277 2278 if (handle == NULL || attrlist == NULL || numattr == 0) { 2279 return (KMF_ERR_BAD_PARAMETER); 2280 } 2281 2282 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2283 if (ret != KMF_OK) 2284 return (ret); 2285 2286 /* Get the cert data */ 2287 cert = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, attrlist, numattr); 2288 if (cert == NULL || cert->Data == NULL) 2289 return (KMF_ERR_BAD_PARAMETER); 2290 2291 /* The label attribute is optional */ 2292 label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr); 2293 2294 /* The trustflag attriburte is optional */ 2295 trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr); 2296 2297 ret = store_cert(handle, nss_slot, cert, label, trust_flag); 2298 2299out: 2300 if (nss_slot != NULL) { 2301 PK11_FreeSlot(nss_slot); 2302 } 2303 2304 return (ret); 2305} 2306 2307 2308KMF_RETURN 2309NSS_ImportCert(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2310{ 2311 KMF_RETURN ret = KMF_OK; 2312 PK11SlotInfo *nss_slot = NULL; 2313 KMF_DATA cert = {NULL, 0}; 2314 KMF_DATA cert_der = {NULL, 0}; 2315 KMF_DATA *cptr = NULL; 2316 KMF_ENCODE_FORMAT format; 2317 char *label = NULL; 2318 char *trust_flag = NULL; 2319 char *certfile = NULL; 2320 2321 if (handle == NULL || attrlist == NULL || numattr == 0) { 2322 return (KMF_ERR_BAD_PARAMETER); 2323 } 2324 2325 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2326 if (ret != KMF_OK) 2327 return (ret); 2328 2329 /* Get the input cert filename attribute */ 2330 certfile = kmf_get_attr_ptr(KMF_CERT_FILENAME_ATTR, attrlist, numattr); 2331 if (certfile == NULL) 2332 return (KMF_ERR_BAD_PARAMETER); 2333 2334 /* Check the cert file and auto-detect the file format of it. */ 2335 ret = kmf_is_cert_file(handle, certfile, &format); 2336 if (ret != KMF_OK) 2337 return (ret); 2338 2339 ret = kmf_read_input_file(handle, certfile, &cert); 2340 if (ret != KMF_OK) { 2341 return (ret); 2342 } 2343 2344 /* 2345 * If the imported cert is in PEM format, convert it to 2346 * DER format in order to store it in NSS token. 2347 */ 2348 if (format == KMF_FORMAT_PEM) { 2349 int derlen; 2350 ret = kmf_pem_to_der(cert.Data, cert.Length, 2351 &cert_der.Data, &derlen); 2352 if (ret != KMF_OK) { 2353 goto cleanup; 2354 } 2355 cert_der.Length = (size_t)derlen; 2356 cptr = &cert_der; 2357 } else { 2358 cptr = &cert; 2359 } 2360 2361 label = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr); 2362 trust_flag = kmf_get_attr_ptr(KMF_TRUSTFLAG_ATTR, attrlist, numattr); 2363 ret = store_cert(handle, nss_slot, cptr, label, trust_flag); 2364 2365cleanup: 2366 if (format == KMF_FORMAT_PEM) { 2367 kmf_free_data(&cert_der); 2368 } 2369 2370 kmf_free_data(&cert); 2371 2372 return (ret); 2373} 2374 2375 2376KMF_RETURN 2377NSS_ImportCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2378{ 2379 KMF_RETURN ret = KMF_OK; 2380 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2381 PK11SlotInfo *nss_slot = NULL; 2382 CERTSignedCrl *nss_crl = NULL; 2383 KMF_ENCODE_FORMAT format; 2384 int importOptions; 2385 SECItem crlDER; 2386 KMF_DATA crl1; 2387 KMF_DATA crl2; 2388 char *crlfilename; 2389 boolean_t crlcheck = FALSE; 2390 2391 if (attrlist == NULL || numattr == 0) { 2392 return (KMF_ERR_BAD_PARAMETER); 2393 } 2394 2395 ret = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2396 if (ret != KMF_OK) { 2397 return (ret); 2398 } 2399 2400 crlfilename = kmf_get_attr_ptr(KMF_CRL_FILENAME_ATTR, attrlist, 2401 numattr); 2402 if (crlfilename == NULL) 2403 return (KMF_ERR_BAD_CRLFILE); 2404 2405 /* 2406 * Check if the input CRL file is a valid CRL file and auto-detect 2407 * the encoded format of the file. 2408 */ 2409 ret = kmf_is_crl_file(handle, crlfilename, &format); 2410 if (ret != KMF_OK) 2411 return (ret); 2412 2413 ret = kmf_get_attr(KMF_CRL_CHECK_ATTR, attrlist, numattr, 2414 &crlcheck, NULL); 2415 if (ret != KMF_OK) 2416 ret = KMF_OK; /* CRL_CHECK is optional */ 2417 2418 /* set importOptions */ 2419 if (crlcheck == B_FALSE) { 2420 importOptions = CRL_IMPORT_DEFAULT_OPTIONS | 2421 CRL_IMPORT_BYPASS_CHECKS; 2422 } else { 2423 importOptions = CRL_IMPORT_DEFAULT_OPTIONS; 2424 } 2425 2426 2427 /* Read in the CRL file */ 2428 crl1.Data = NULL; 2429 crl2.Data = NULL; 2430 ret = kmf_read_input_file(handle, crlfilename, &crl1); 2431 if (ret != KMF_OK) { 2432 return (ret); 2433 } 2434 2435 /* If the input CRL is in PEM format, convert it to DER first. */ 2436 if (format == KMF_FORMAT_PEM) { 2437 int len; 2438 ret = kmf_pem_to_der(crl1.Data, crl1.Length, 2439 &crl2.Data, &len); 2440 if (ret != KMF_OK) { 2441 goto out; 2442 } 2443 crl2.Length = (size_t)len; 2444 } 2445 2446 crlDER.data = format == KMF_FORMAT_ASN1 ? crl1.Data : crl2.Data; 2447 crlDER.len = format == KMF_FORMAT_ASN1 ? crl1.Length : crl2.Length; 2448 2449 nss_crl = PK11_ImportCRL(nss_slot, &crlDER, NULL, SEC_CRL_TYPE, 2450 NULL, importOptions, NULL, CRL_DECODE_DEFAULT_OPTIONS); 2451 2452 if (nss_crl == NULL) { 2453 SET_ERROR(kmfh, PORT_GetError()); 2454 ret = KMF_ERR_BAD_CRLFILE; 2455 goto out; 2456 } 2457 2458out: 2459 if (nss_slot != NULL) { 2460 PK11_FreeSlot(nss_slot); 2461 } 2462 2463 if (crl1.Data != NULL) { 2464 free(crl1.Data); 2465 } 2466 2467 if (crl2.Data != NULL) { 2468 free(crl2.Data); 2469 } 2470 2471 if (nss_crl != NULL) { 2472 SEC_DestroyCrl(nss_crl); 2473 } 2474 2475 return (ret); 2476} 2477 2478KMF_RETURN 2479NSS_DeleteCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2480{ 2481 KMF_RETURN rv = KMF_OK; 2482 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2483 CERTSignedCrl *crl = NULL; 2484 CERTCertificate *cert = NULL; 2485 PK11SlotInfo *nss_slot = NULL; 2486 CERTCrlHeadNode *crlList = NULL; 2487 CERTCrlNode *crlNode = NULL; 2488 PRArenaPool *arena = NULL; 2489 CERTName *name = NULL; 2490 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); 2491 char *issuername, *subjectname; 2492 2493 /* check params */ 2494 if (numattr == 0 || attrlist == NULL) { 2495 return (KMF_ERR_BAD_PARAMETER); 2496 } 2497 2498 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2499 if (rv != KMF_OK) { 2500 return (rv); 2501 } 2502 2503 issuername = kmf_get_attr_ptr(KMF_ISSUER_NAME_ATTR, attrlist, 2504 numattr); 2505 subjectname = kmf_get_attr_ptr(KMF_SUBJECT_NAME_ATTR, attrlist, 2506 numattr); 2507 2508 /* Caller must specify issuer or subject but not both */ 2509 if ((issuername == NULL && subjectname == NULL) || 2510 (issuername != NULL && subjectname != NULL)) 2511 return (KMF_ERR_BAD_PARAMETER); 2512 2513 /* Find the CRL based on the deletion criteria. */ 2514 if (issuername != NULL) { 2515 /* 2516 * If the deletion is based on the issuer's certificate 2517 * nickname, we will get the issuer's cert first, then 2518 * get the CRL from the cert. 2519 */ 2520 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, 2521 issuername); 2522 if (!cert) { 2523 SET_ERROR(kmfh, PORT_GetError()); 2524 rv = KMF_ERR_CERT_NOT_FOUND; 2525 goto out; 2526 } 2527 2528 crl = SEC_FindCrlByName(certHandle, &cert->derSubject, 2529 SEC_CRL_TYPE); 2530 if (crl == NULL) { 2531 SET_ERROR(kmfh, PORT_GetError()); 2532 rv = KMF_ERR_CRL_NOT_FOUND; 2533 goto out; 2534 } 2535 } else { 2536 /* 2537 * If the deletion is based on the CRL's subject name, we will 2538 * get all the CRLs from the internal database and search 2539 * for the CRL with the same subject name. 2540 */ 2541 boolean_t found = B_FALSE; 2542 int nssrv; 2543 2544 nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE); 2545 if (nssrv) { 2546 SET_ERROR(kmfh, nssrv); 2547 rv = KMF_ERR_CRL_NOT_FOUND; 2548 goto out; 2549 } 2550 2551 if (crlList == NULL) { 2552 SET_ERROR(kmfh, PORT_GetError()); 2553 rv = KMF_ERR_CRL_NOT_FOUND; 2554 goto out; 2555 } 2556 2557 /* Allocate space for name */ 2558 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 2559 if (arena == NULL) { 2560 rv = KMF_ERR_MEMORY; 2561 goto out; 2562 } 2563 2564 name = PORT_ArenaZAlloc(arena, sizeof (*name)); 2565 if (name == NULL) { 2566 rv = KMF_ERR_MEMORY; 2567 goto out; 2568 } 2569 name->arena = arena; 2570 2571 crlNode = crlList->first; 2572 while (crlNode && !found) { 2573 char *asciiname = NULL; 2574 SECItem* issuer; 2575 2576 name = &crlNode->crl->crl.name; 2577 if (!name) { 2578 SET_ERROR(kmfh, PORT_GetError()); 2579 rv = KMF_ERR_CRL_NOT_FOUND; 2580 break; 2581 } 2582 2583 asciiname = CERT_NameToAscii(name); 2584 if (asciiname == NULL) { 2585 SET_ERROR(kmfh, PORT_GetError()); 2586 rv = KMF_ERR_CRL_NOT_FOUND; 2587 break; 2588 } 2589 2590 if (strcmp(subjectname, asciiname) == 0) { 2591 found = B_TRUE; 2592 issuer = &crlNode->crl->crl.derName; 2593 crl = SEC_FindCrlByName(certHandle, issuer, 2594 SEC_CRL_TYPE); 2595 if (crl == NULL) { 2596 /* We found a cert but no CRL */ 2597 SET_ERROR(kmfh, PORT_GetError()); 2598 rv = KMF_ERR_CRL_NOT_FOUND; 2599 } 2600 } 2601 PORT_Free(asciiname); 2602 crlNode = crlNode->next; 2603 } 2604 2605 if (rv) { 2606 goto out; 2607 } 2608 } 2609 2610 if (crl) { 2611 (void) SEC_DeletePermCRL(crl); 2612 } 2613 2614out: 2615 if (nss_slot != NULL) { 2616 PK11_FreeSlot(nss_slot); 2617 } 2618 2619 if (crlList != NULL) { 2620 PORT_FreeArena(crlList->arena, PR_FALSE); 2621 } 2622 2623 if (arena != NULL) { 2624 PORT_FreeArena(arena, PR_FALSE); 2625 } 2626 2627 if (cert != NULL) { 2628 CERT_DestroyCertificate(cert); 2629 } 2630 2631 if (crl != NULL) { 2632 SEC_DestroyCrl(crl); 2633 } 2634 2635 return (rv); 2636} 2637 2638KMF_RETURN 2639NSS_FindCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2640{ 2641 KMF_RETURN rv = KMF_OK; 2642 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2643 PK11SlotInfo *nss_slot = NULL; 2644 CERTCrlHeadNode *crlList = NULL; 2645 CERTCrlNode *crlNode = NULL; 2646 PRArenaPool *arena = NULL; 2647 CERTName *name = NULL; 2648 SECStatus nssrv; 2649 char *asciiname = NULL; 2650 int crl_num; 2651 int i, *CRLCount; 2652 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); 2653 char **CRLNameList; 2654 2655 if (numattr == 0 || attrlist == NULL) { 2656 return (KMF_ERR_BAD_PARAMETER); 2657 } 2658 2659 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2660 if (rv != KMF_OK) { 2661 return (rv); 2662 } 2663 2664 CRLCount = kmf_get_attr_ptr(KMF_CRL_COUNT_ATTR, attrlist, numattr); 2665 if (CRLCount == NULL) 2666 return (KMF_ERR_BAD_PARAMETER); 2667 2668 CRLNameList = (char **)kmf_get_attr_ptr(KMF_CRL_NAMELIST_ATTR, 2669 attrlist, numattr); 2670 2671 /* Look up Crls */ 2672 nssrv = SEC_LookupCrls(certHandle, &crlList, SEC_CRL_TYPE); 2673 if (nssrv) { 2674 SET_ERROR(kmfh, rv); 2675 rv = KMF_ERR_CRL_NOT_FOUND; 2676 goto out; 2677 } 2678 2679 /* Allocate space for name first */ 2680 arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 2681 if (arena == NULL) { 2682 rv = KMF_ERR_MEMORY; 2683 goto out; 2684 } 2685 2686 name = PORT_ArenaZAlloc(arena, sizeof (*name)); 2687 if (name == NULL) { 2688 rv = KMF_ERR_MEMORY; 2689 goto out; 2690 } 2691 name->arena = arena; 2692 2693 /* 2694 * Loop thru the crlList and create a crl list with CRL's subject name. 2695 */ 2696 crlNode = crlList->first; 2697 crl_num = 0; 2698 while (crlNode) { 2699 char *subj_name; 2700 2701 /* Get the CRL subject name */ 2702 name = &crlNode->crl->crl.name; 2703 if (!name) { 2704 SET_ERROR(kmfh, PORT_GetError()); 2705 rv = KMF_ERR_CRL_NOT_FOUND; 2706 break; 2707 } 2708 2709 2710 if (CRLNameList != NULL) { 2711 asciiname = CERT_NameToAscii(name); 2712 if (asciiname == NULL) { 2713 SET_ERROR(kmfh, PORT_GetError()); 2714 rv = KMF_ERR_CRL_NOT_FOUND; 2715 break; 2716 } 2717 subj_name = strdup(asciiname); 2718 PORT_Free(asciiname); 2719 if (subj_name == NULL) { 2720 rv = KMF_ERR_MEMORY; 2721 break; 2722 } 2723 CRLNameList[crl_num] = subj_name; 2724 } 2725 2726 crl_num++; 2727 crlNode = crlNode->next; 2728 } 2729 2730 if (rv == KMF_OK) { 2731 /* success */ 2732 *CRLCount = crl_num; 2733 } 2734 2735out: 2736 if (nss_slot != NULL) { 2737 PK11_FreeSlot(nss_slot); 2738 } 2739 2740 if (crlList != NULL) { 2741 PORT_FreeArena(crlList->arena, PR_FALSE); 2742 } 2743 2744 if (arena != NULL) { 2745 PORT_FreeArena(arena, PR_FALSE); 2746 } 2747 2748 /* If failed, free memory allocated for the returning rlist */ 2749 if (rv && (CRLNameList != NULL)) { 2750 for (i = 0; i < crl_num; i++) { 2751 free(CRLNameList[i]); 2752 } 2753 } 2754 2755 return (rv); 2756} 2757 2758KMF_RETURN 2759NSS_FindCertInCRL(KMF_HANDLE_T handle, int numattr, KMF_ATTRIBUTE *attrlist) 2760{ 2761 KMF_RETURN rv = KMF_OK; 2762 KMF_HANDLE *kmfh = (KMF_HANDLE *)handle; 2763 PK11SlotInfo *nss_slot = NULL; 2764 CERTCertificate *cert = NULL; 2765 CERTSignedCrl *crl = NULL; 2766 CERTCrlEntry *entry; 2767 boolean_t match = B_FALSE; 2768 int i; 2769 CERTCertDBHandle *certHandle = CERT_GetDefaultCertDB(); 2770 char *certlabel; 2771 KMF_DATA *certdata; 2772 2773 /* check params */ 2774 if (numattr == 0 || attrlist == NULL) { 2775 return (KMF_ERR_BAD_PARAMETER); 2776 } 2777 2778 rv = do_nss_init(handle, numattr, attrlist, FALSE, &nss_slot); 2779 if (rv != KMF_OK) { 2780 return (rv); 2781 } 2782 2783 certlabel = kmf_get_attr_ptr(KMF_CERT_LABEL_ATTR, attrlist, numattr); 2784 2785 /* Find the certificate first */ 2786 if (certlabel != NULL) { 2787 cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, 2788 certlabel); 2789 } else { 2790 SECItem derCert = { NULL, 0}; 2791 2792 certdata = kmf_get_attr_ptr(KMF_CERT_DATA_ATTR, 2793 attrlist, numattr); 2794 2795 if (certdata == NULL) 2796 return (KMF_ERR_BAD_PARAMETER); 2797 2798 derCert.data = certdata->Data; 2799 derCert.len = certdata->Length; 2800 2801 cert = CERT_FindCertByDERCert(certHandle, &derCert); 2802 } 2803 2804 if (cert == NULL) { 2805 SET_ERROR(kmfh, PORT_GetError()); 2806 rv = KMF_ERR_CERT_NOT_FOUND; 2807 goto out; 2808 } 2809 2810 /* Find the CRL with the same issuer as the given certificate. */ 2811 crl = SEC_FindCrlByName(certHandle, &cert->derIssuer, SEC_CRL_TYPE); 2812 if (crl == NULL) { 2813 /* 2814 * Could not find the CRL issued by the same issuer. This 2815 * usually means that the CRL is not installed in the DB. 2816 */ 2817 SET_ERROR(kmfh, PORT_GetError()); 2818 rv = KMF_ERR_CRL_NOT_FOUND; 2819 goto out; 2820 2821 } 2822 2823 /* Check if the certificate's serialNumber is revoked in the CRL */ 2824 i = 0; 2825 while ((entry = (crl->crl).entries[i++]) != NULL) { 2826 if (SECITEM_CompareItem(&(cert->serialNumber), 2827 &(entry->serialNumber)) == SECEqual) { 2828 match = B_TRUE; 2829 break; 2830 } 2831 } 2832 2833 if (!match) { 2834 rv = KMF_ERR_NOT_REVOKED; 2835 } 2836 2837out: 2838 if (nss_slot != NULL) { 2839 PK11_FreeSlot(nss_slot); 2840 } 2841 2842 if (cert != NULL) { 2843 CERT_DestroyCertificate(cert); 2844 } 2845 2846 if (crl != NULL) { 2847 SEC_DestroyCrl(crl); 2848 } 2849 2850 return (rv); 2851} 2852