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