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 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * This file implements the token object delete operation for this tool. 30 * It loads the PKCS#11 modules, finds the object to delete, deletes it, 31 * and cleans up. User must be R/W logged into the token. 32 */ 33 34 #include <stdio.h> 35 #include <string.h> 36 #include <cryptoutil.h> 37 #include <security/cryptoki.h> 38 #include "common.h" 39 #include <kmfapi.h> 40 41 static KMF_RETURN 42 pk_destroy_keys(void *handle, KMF_KEY_HANDLE *keys, 43 KMF_FINDKEY_PARAMS *fkparams, uint32_t numkeys) 44 { 45 int i; 46 KMF_RETURN rv = KMF_OK; 47 KMF_DELETEKEY_PARAMS dkparams; 48 49 (void) memset(&dkparams, 0, sizeof (dkparams)); 50 dkparams.kstype = fkparams->kstype; 51 52 switch (fkparams->kstype) { 53 case KMF_KEYSTORE_NSS: 54 dkparams.nssparms = fkparams->nssparms; 55 dkparams.cred = fkparams->cred; 56 break; 57 case KMF_KEYSTORE_OPENSSL: 58 break; 59 case KMF_KEYSTORE_PK11TOKEN: 60 dkparams.cred = fkparams->cred; 61 break; 62 default: 63 return (PK_ERR_USAGE); 64 } 65 66 for (i = 0; rv == KMF_OK && i < numkeys; i++) { 67 rv = KMF_DeleteKeyFromKeystore(handle, &dkparams, &keys[i]); 68 } 69 return (rv); 70 } 71 72 static KMF_RETURN 73 pk_delete_keys(KMF_HANDLE_T kmfhandle, KMF_FINDKEY_PARAMS *parms, char *desc, 74 int *keysdeleted) 75 { 76 KMF_RETURN rv = KMF_OK; 77 uint32_t numkeys = 0; 78 79 *keysdeleted = 0; 80 numkeys = 0; 81 rv = KMF_FindKey(kmfhandle, parms, NULL, &numkeys); 82 if (rv == KMF_OK && numkeys > 0) { 83 KMF_KEY_HANDLE *keys = NULL; 84 char prompt[1024]; 85 86 (void) snprintf(prompt, sizeof (prompt), 87 gettext("%d %s key(s) found, do you want " 88 "to delete them (y/N) ?"), numkeys, 89 (desc != NULL ? desc : "")); 90 91 if (!yesno(prompt, 92 gettext("Respond with yes or no.\n"), 93 B_FALSE)) { 94 return (KMF_OK); 95 } 96 keys = (KMF_KEY_HANDLE *)malloc(numkeys * 97 sizeof (KMF_KEY_HANDLE)); 98 if (keys == NULL) 99 return (KMF_ERR_MEMORY); 100 (void) memset(keys, 0, numkeys * 101 sizeof (KMF_KEY_HANDLE)); 102 103 rv = KMF_FindKey(kmfhandle, parms, keys, &numkeys); 104 if (rv == KMF_OK) { 105 rv = pk_destroy_keys(kmfhandle, keys, 106 parms, numkeys); 107 } 108 109 free(keys); 110 } 111 112 if (rv == KMF_ERR_KEY_NOT_FOUND) { 113 rv = KMF_OK; 114 } 115 116 *keysdeleted = numkeys; 117 return (rv); 118 } 119 120 static KMF_RETURN 121 pk_delete_certs(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *fcparms, 122 KMF_DELETECERT_PARAMS *dcparms) 123 { 124 KMF_RETURN rv = KMF_OK; 125 uint32_t numcerts = 0; 126 127 rv = KMF_FindCert(kmfhandle, fcparms, NULL, &numcerts); 128 if (rv == KMF_OK && numcerts > 0) { 129 char prompt[1024]; 130 (void) snprintf(prompt, sizeof (prompt), 131 gettext("%d certificate(s) found, do you want " 132 "to delete them (y/N) ?"), numcerts); 133 134 if (!yesno(prompt, 135 gettext("Respond with yes or no.\n"), 136 B_FALSE)) { 137 return (KMF_OK); 138 } 139 140 rv = KMF_DeleteCertFromKeystore(kmfhandle, dcparms); 141 142 } else if (rv == KMF_ERR_CERT_NOT_FOUND) { 143 rv = KMF_OK; 144 } 145 146 return (rv); 147 } 148 149 static KMF_RETURN 150 delete_nss_keys(KMF_HANDLE_T kmfhandle, char *dir, char *prefix, 151 char *token, int oclass, char *objlabel, 152 KMF_CREDENTIAL *tokencred) 153 { 154 KMF_RETURN rv = KMF_OK; 155 KMF_FINDKEY_PARAMS parms; 156 char *keytype = NULL; 157 int nk, numkeys = 0; 158 159 rv = configure_nss(kmfhandle, dir, prefix); 160 if (rv != KMF_OK) 161 return (rv); 162 163 (void) memset(&parms, 0, sizeof (parms)); 164 parms.kstype = KMF_KEYSTORE_NSS; 165 parms.findLabel = objlabel; 166 parms.cred = *tokencred; 167 parms.nssparms.slotlabel = token; 168 169 if (oclass & PK_PRIKEY_OBJ) { 170 parms.keyclass = KMF_ASYM_PRI; 171 keytype = "private"; 172 rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk); 173 numkeys += nk; 174 } 175 if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) { 176 parms.keyclass = KMF_SYMMETRIC; 177 keytype = "symmetric"; 178 rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk); 179 numkeys += nk; 180 } 181 if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) { 182 parms.keyclass = KMF_ASYM_PUB; 183 keytype = "public"; 184 rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk); 185 numkeys += nk; 186 } 187 if (rv == KMF_OK && numkeys == 0) 188 rv = KMF_ERR_KEY_NOT_FOUND; 189 190 return (rv); 191 } 192 193 194 static KMF_RETURN 195 delete_nss_certs(KMF_HANDLE_T kmfhandle, 196 char *dir, char *prefix, 197 char *token, char *objlabel, 198 KMF_BIGINT *serno, char *issuer, char *subject, 199 KMF_CERT_VALIDITY find_criteria_flag) 200 { 201 KMF_RETURN rv = KMF_OK; 202 KMF_DELETECERT_PARAMS dcparms; 203 KMF_FINDCERT_PARAMS fcargs; 204 205 rv = configure_nss(kmfhandle, dir, prefix); 206 if (rv != KMF_OK) 207 return (rv); 208 209 (void) memset(&dcparms, 0, sizeof (dcparms)); 210 dcparms.kstype = KMF_KEYSTORE_NSS; 211 dcparms.certLabel = objlabel; 212 dcparms.issuer = issuer; 213 dcparms.subject = subject; 214 dcparms.serial = serno; 215 dcparms.find_cert_validity = find_criteria_flag; 216 dcparms.nssparms.slotlabel = token; 217 218 (void) memset(&fcargs, 0, sizeof (fcargs)); 219 fcargs.kstype = KMF_KEYSTORE_NSS; 220 fcargs.certLabel = objlabel; 221 fcargs.issuer = issuer; 222 fcargs.subject = subject; 223 fcargs.serial = serno; 224 fcargs.find_cert_validity = find_criteria_flag; 225 fcargs.nssparms.slotlabel = token; 226 227 rv = pk_delete_certs(kmfhandle, &fcargs, &dcparms); 228 229 return (rv); 230 } 231 232 static KMF_RETURN 233 delete_nss_crl(void *kmfhandle, 234 char *dir, char *prefix, char *token, 235 char *issuernickname, char *subject) 236 { 237 KMF_RETURN rv = KMF_OK; 238 KMF_DELETECRL_PARAMS dcrlparms; 239 240 rv = configure_nss(kmfhandle, dir, prefix); 241 if (rv != KMF_OK) 242 return (rv); 243 244 (void) memset(&dcrlparms, 0, sizeof (dcrlparms)); 245 246 dcrlparms.kstype = KMF_KEYSTORE_NSS; 247 dcrlparms.nssparms.slotlabel = token; 248 dcrlparms.nssparms.crl_issuerName = issuernickname; 249 dcrlparms.nssparms.crl_subjName = subject; 250 251 rv = KMF_DeleteCRL(kmfhandle, &dcrlparms); 252 253 return (rv); 254 } 255 256 static KMF_RETURN 257 delete_pk11_keys(KMF_HANDLE_T kmfhandle, 258 char *token, int oclass, char *objlabel, 259 KMF_CREDENTIAL *tokencred) 260 { 261 KMF_RETURN rv = KMF_OK; 262 KMF_FINDKEY_PARAMS parms; 263 int nk, numkeys = 0; 264 265 /* 266 * Symmetric keys and RSA/DSA private keys are always 267 * created with the "CKA_PRIVATE" field == TRUE, so 268 * make sure we search for them with it also set. 269 */ 270 if (oclass & (PK_SYMKEY_OBJ | PK_PRIKEY_OBJ)) 271 oclass |= PK_PRIVATE_OBJ; 272 273 rv = select_token(kmfhandle, token, FALSE); 274 if (rv != KMF_OK) { 275 return (rv); 276 } 277 278 (void) memset(&parms, 0, sizeof (parms)); 279 parms.kstype = KMF_KEYSTORE_PK11TOKEN; 280 parms.findLabel = (char *)objlabel; 281 parms.keytype = 0; 282 parms.pkcs11parms.private = ((oclass & PK_PRIVATE_OBJ) > 0); 283 parms.pkcs11parms.token = 1; 284 parms.cred.cred = tokencred->cred; 285 parms.cred.credlen = tokencred->credlen; 286 287 if (oclass & PK_PRIKEY_OBJ) { 288 parms.keyclass = KMF_ASYM_PRI; 289 rv = pk_delete_keys(kmfhandle, &parms, "private", &nk); 290 numkeys += nk; 291 } 292 293 if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) { 294 parms.keyclass = KMF_SYMMETRIC; 295 rv = pk_delete_keys(kmfhandle, &parms, "symmetric", &nk); 296 numkeys += nk; 297 } 298 299 if (rv == KMF_OK && (oclass & PK_PUBKEY_OBJ)) { 300 parms.keyclass = KMF_ASYM_PUB; 301 rv = pk_delete_keys(kmfhandle, &parms, "public", &nk); 302 numkeys += nk; 303 } 304 if (rv == KMF_OK && numkeys == 0) 305 rv = KMF_ERR_KEY_NOT_FOUND; 306 307 return (rv); 308 } 309 310 static KMF_RETURN 311 delete_pk11_certs(KMF_HANDLE_T kmfhandle, 312 char *token, char *objlabel, 313 KMF_BIGINT *serno, char *issuer, char *subject, 314 KMF_CERT_VALIDITY find_criteria_flag) 315 { 316 KMF_RETURN kmfrv; 317 KMF_DELETECERT_PARAMS dparms; 318 KMF_FINDCERT_PARAMS fcargs; 319 320 kmfrv = select_token(kmfhandle, token, FALSE); 321 322 if (kmfrv != KMF_OK) { 323 return (kmfrv); 324 } 325 326 (void) memset(&dparms, 0, sizeof (dparms)); 327 dparms.kstype = KMF_KEYSTORE_PK11TOKEN; 328 dparms.certLabel = objlabel; 329 dparms.issuer = issuer; 330 dparms.subject = subject; 331 dparms.serial = serno; 332 dparms.find_cert_validity = find_criteria_flag; 333 334 fcargs = dparms; 335 kmfrv = pk_delete_certs(kmfhandle, &fcargs, &dparms); 336 337 return (kmfrv); 338 } 339 340 static KMF_RETURN 341 delete_file_certs(KMF_HANDLE_T kmfhandle, 342 char *dir, char *filename, KMF_BIGINT *serial, char *issuer, 343 char *subject, KMF_CERT_VALIDITY find_criteria_flag) 344 { 345 KMF_RETURN rv; 346 KMF_DELETECERT_PARAMS dparms; 347 KMF_FINDCERT_PARAMS fcargs; 348 349 (void *)memset(&dparms, 0, sizeof (dparms)); 350 (void *)memset(&fcargs, 0, sizeof (fcargs)); 351 fcargs.kstype = KMF_KEYSTORE_OPENSSL; 352 fcargs.certLabel = NULL; 353 fcargs.issuer = issuer; 354 fcargs.subject = subject; 355 fcargs.serial = serial; 356 fcargs.sslparms.dirpath = dir; 357 fcargs.sslparms.certfile = filename; 358 fcargs.find_cert_validity = find_criteria_flag; 359 360 /* For now, delete parameters and find parameters are the same */ 361 dparms = fcargs; 362 363 rv = pk_delete_certs(kmfhandle, &fcargs, &dparms); 364 365 return (rv); 366 } 367 368 static KMF_RETURN 369 delete_file_keys(KMF_HANDLE_T kmfhandle, int oclass, 370 char *dir, char *infile) 371 { 372 KMF_RETURN rv = KMF_OK; 373 KMF_FINDKEY_PARAMS parms; 374 char *keytype = ""; 375 int nk, numkeys = 0; 376 377 (void) memset(&parms, 0, sizeof (parms)); 378 parms.kstype = KMF_KEYSTORE_OPENSSL; 379 parms.sslparms.dirpath = dir; 380 parms.sslparms.keyfile = infile; 381 382 if (oclass & (PK_PUBKEY_OBJ | PK_PRIKEY_OBJ)) { 383 parms.keyclass = KMF_ASYM_PRI; 384 keytype = "Asymmetric"; 385 rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk); 386 numkeys += nk; 387 } 388 if (rv == KMF_OK && (oclass & PK_SYMKEY_OBJ)) { 389 parms.keyclass = KMF_SYMMETRIC; 390 keytype = "symmetric"; 391 rv = pk_delete_keys(kmfhandle, &parms, keytype, &nk); 392 numkeys += nk; 393 } 394 if (rv == KMF_OK && numkeys == 0) 395 rv = KMF_ERR_KEY_NOT_FOUND; 396 397 return (rv); 398 } 399 400 static KMF_RETURN 401 delete_file_crl(void *kmfhandle, char *dir, char *filename) 402 { 403 KMF_RETURN rv; 404 KMF_DELETECRL_PARAMS dcrlparms; 405 406 (void) memset(&dcrlparms, 0, sizeof (dcrlparms)); 407 408 dcrlparms.kstype = KMF_KEYSTORE_OPENSSL; 409 dcrlparms.sslparms.dirpath = dir; 410 dcrlparms.sslparms.crlfile = filename; 411 412 rv = KMF_DeleteCRL(kmfhandle, &dcrlparms); 413 414 return (rv); 415 } 416 417 /* 418 * Delete token objects. 419 */ 420 int 421 pk_delete(int argc, char *argv[]) 422 { 423 int opt; 424 extern int optind_av; 425 extern char *optarg_av; 426 char *token_spec = NULL; 427 char *subject = NULL; 428 char *issuer = NULL; 429 char *dir = NULL; 430 char *prefix = NULL; 431 char *infile = NULL; 432 char *object_label = NULL; 433 char *serstr = NULL; 434 435 int oclass = 0; 436 KMF_BIGINT serial = { NULL, 0 }; 437 KMF_HANDLE_T kmfhandle = NULL; 438 KMF_KEYSTORE_TYPE kstype = 0; 439 KMF_RETURN kmfrv; 440 int rv = 0; 441 char *find_criteria = NULL; 442 KMF_CERT_VALIDITY find_criteria_flag = KMF_ALL_CERTS; 443 KMF_CREDENTIAL tokencred = {NULL, 0}; 444 445 /* Parse command line options. Do NOT i18n/l10n. */ 446 while ((opt = getopt_av(argc, argv, 447 "T:(token)y:(objtype)l:(label)" 448 "k:(keystore)s:(subject)n:(nickname)" 449 "d:(dir)p:(prefix)S:(serial)i:(issuer)" 450 "c:(criteria)" 451 "f:(infile)")) != EOF) { 452 453 if (EMPTYSTRING(optarg_av)) 454 return (PK_ERR_USAGE); 455 switch (opt) { 456 case 'T': /* token specifier */ 457 if (token_spec) 458 return (PK_ERR_USAGE); 459 token_spec = optarg_av; 460 break; 461 case 'y': /* object type: public, private, both */ 462 if (oclass) 463 return (PK_ERR_USAGE); 464 oclass = OT2Int(optarg_av); 465 if (oclass == -1) 466 return (PK_ERR_USAGE); 467 break; 468 case 'l': /* objects with specific label */ 469 case 'n': 470 if (object_label) 471 return (PK_ERR_USAGE); 472 object_label = (char *)optarg_av; 473 break; 474 case 'k': 475 kstype = KS2Int(optarg_av); 476 if (kstype == 0) 477 return (PK_ERR_USAGE); 478 break; 479 case 's': 480 subject = optarg_av; 481 break; 482 case 'i': 483 issuer = optarg_av; 484 break; 485 case 'd': 486 dir = optarg_av; 487 break; 488 case 'p': 489 prefix = optarg_av; 490 break; 491 case 'S': 492 serstr = optarg_av; 493 break; 494 case 'f': 495 infile = optarg_av; 496 break; 497 case 'c': 498 find_criteria = optarg_av; 499 if (!strcasecmp(find_criteria, "valid")) 500 find_criteria_flag = 501 KMF_NONEXPIRED_CERTS; 502 else if (!strcasecmp(find_criteria, "expired")) 503 find_criteria_flag = KMF_EXPIRED_CERTS; 504 else if (!strcasecmp(find_criteria, "both")) 505 find_criteria_flag = KMF_ALL_CERTS; 506 else 507 return (PK_ERR_USAGE); 508 break; 509 default: 510 return (PK_ERR_USAGE); 511 break; 512 } 513 } 514 515 /* Assume keystore = PKCS#11 if not specified */ 516 if (kstype == 0) 517 kstype = KMF_KEYSTORE_PK11TOKEN; 518 519 /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 520 if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 521 kstype != KMF_KEYSTORE_PK11TOKEN) { 522 523 (void) fprintf(stderr, gettext("The objtype parameter " 524 "is only relevant if keystore=pkcs11\n")); 525 return (PK_ERR_USAGE); 526 } 527 528 /* If no object class specified, delete everything but CRLs */ 529 if (oclass == 0) 530 oclass = PK_CERT_OBJ | PK_PUBKEY_OBJ | PK_PRIKEY_OBJ | 531 PK_SYMKEY_OBJ; 532 533 /* No additional args allowed. */ 534 argc -= optind_av; 535 argv += optind_av; 536 if (argc) 537 return (PK_ERR_USAGE); 538 /* Done parsing command line options. */ 539 540 if (kstype == KMF_KEYSTORE_PK11TOKEN && token_spec == NULL) { 541 token_spec = PK_DEFAULT_PK11TOKEN; 542 } else if (kstype == KMF_KEYSTORE_NSS && token_spec == NULL) { 543 token_spec = DEFAULT_NSS_TOKEN; 544 } 545 546 if (serstr != NULL) { 547 uchar_t *bytes = NULL; 548 size_t bytelen; 549 550 rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen); 551 if (rv != KMF_OK || bytes == NULL) { 552 (void) fprintf(stderr, gettext("serial number " 553 "must be specified as a hex number " 554 "(ex: 0x0102030405ffeeddee)\n")); 555 return (PK_ERR_USAGE); 556 } 557 serial.val = bytes; 558 serial.len = bytelen; 559 } 560 561 if ((kstype == KMF_KEYSTORE_PK11TOKEN || 562 kstype == KMF_KEYSTORE_NSS) && 563 (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) { 564 565 (void) get_token_password(kstype, token_spec, 566 &tokencred); 567 } 568 569 if ((kmfrv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) 570 return (kmfrv); 571 572 switch (kstype) { 573 case KMF_KEYSTORE_PK11TOKEN: 574 if (oclass & PK_KEY_OBJ) { 575 kmfrv = delete_pk11_keys(kmfhandle, 576 token_spec, oclass, 577 object_label, 578 &tokencred); 579 /* 580 * If deleting groups of objects, it is OK 581 * to ignore the "key not found" case so that 582 * we can continue to find other objects. 583 */ 584 if (kmfrv == KMF_ERR_KEY_NOT_FOUND && 585 (oclass != PK_KEY_OBJ)) 586 kmfrv = KMF_OK; 587 if (kmfrv != KMF_OK) 588 break; 589 } 590 if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 591 kmfrv = delete_pk11_certs(kmfhandle, 592 token_spec, 593 object_label, 594 &serial, issuer, 595 subject, find_criteria_flag); 596 /* 597 * If cert delete failed, but we are looking at 598 * other objects, then it is OK. 599 */ 600 if (kmfrv == KMF_ERR_CERT_NOT_FOUND && 601 (oclass & (PK_CRL_OBJ | PK_KEY_OBJ))) 602 kmfrv = KMF_OK; 603 if (kmfrv != KMF_OK) 604 break; 605 } 606 if (oclass & PK_CRL_OBJ) 607 kmfrv = delete_file_crl(kmfhandle, 608 dir, infile); 609 break; 610 case KMF_KEYSTORE_NSS: 611 if (oclass & PK_KEY_OBJ) { 612 kmfrv = delete_nss_keys(kmfhandle, 613 dir, prefix, token_spec, 614 oclass, (char *)object_label, 615 &tokencred); 616 if (kmfrv != KMF_OK) 617 break; 618 } 619 if (oclass & PK_CERT_OBJ) { 620 kmfrv = delete_nss_certs(kmfhandle, 621 dir, prefix, token_spec, 622 (char *)object_label, 623 &serial, issuer, subject, 624 find_criteria_flag); 625 if (kmfrv != KMF_OK) 626 break; 627 } 628 if (oclass & PK_CRL_OBJ) 629 kmfrv = delete_nss_crl(kmfhandle, 630 dir, prefix, token_spec, 631 (char *)object_label, subject); 632 break; 633 case KMF_KEYSTORE_OPENSSL: 634 if (oclass & PK_KEY_OBJ) { 635 kmfrv = delete_file_keys(kmfhandle, oclass, 636 dir, infile); 637 if (kmfrv != KMF_OK) 638 break; 639 } 640 if (oclass & (PK_CERT_OBJ)) { 641 kmfrv = delete_file_certs(kmfhandle, 642 dir, infile, &serial, issuer, 643 subject, find_criteria_flag); 644 if (kmfrv != KMF_OK) 645 break; 646 } 647 if (oclass & PK_CRL_OBJ) 648 kmfrv = delete_file_crl(kmfhandle, 649 dir, infile); 650 break; 651 default: 652 rv = PK_ERR_USAGE; 653 break; 654 } 655 656 if (kmfrv != KMF_OK) { 657 display_error(kmfhandle, kmfrv, 658 gettext("Error deleting objects")); 659 } 660 661 if (serial.val != NULL) 662 free(serial.val); 663 (void) KMF_Finalize(kmfhandle); 664 return (kmfrv); 665 } 666