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