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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Developer command for adding the signature section to an ELF object 29 * PSARC 2001/488 30 * 31 * DEBUG Information: 32 * This command uses the cryptodebug() function from libcryptoutil. 33 * Set SUNW_CRYPTO_DEBUG to stderr or syslog for all debug to go to auth.debug 34 */ 35 36 #include <stdio.h> 37 #include <stdlib.h> 38 #include <stdarg.h> 39 #include <limits.h> 40 #include <time.h> 41 #include <unistd.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <fcntl.h> 45 #include <libintl.h> 46 #include <locale.h> 47 #include <errno.h> 48 #include <strings.h> 49 #include <langinfo.h> 50 51 #include <cryptoutil.h> 52 #include <sys/crypto/elfsign.h> 53 #include <libelfsign.h> 54 55 #include <kmfapi.h> 56 57 #define SIGN "sign" 58 #define SIGN_OPTS "ac:e:F:k:P:T:v" 59 #define VERIFY "verify" 60 #define VERIFY_OPTS "c:e:v" 61 #define REQUEST "request" 62 #define REQUEST_OPTS "i:k:r:T:" 63 #define LIST "list" 64 #define LIST_OPTS "c:e:f:" 65 66 enum cmd_e { 67 ES_SIGN, 68 ES_VERIFY, 69 ES_REQUEST, 70 ES_LIST 71 }; 72 73 enum field_e { 74 FLD_UNKNOWN, 75 FLD_SUBJECT, 76 FLD_ISSUER, 77 FLD_FORMAT, 78 FLD_SIGNER, 79 FLD_TIME 80 }; 81 82 #define MIN_ARGS 3 /* The minimum # args to do anything */ 83 #define ES_DEFAULT_KEYSIZE 1024 84 85 static struct { 86 enum cmd_e cmd; /* sub command: sign | verify | request */ 87 char *cert; /* -c <certificate_file> | */ 88 /* -r <certificate_request_file> */ 89 char **elfobj; /* -e <elf_object> */ 90 int elfcnt; 91 enum ES_ACTION es_action; 92 ELFsign_t ess; /* libelfsign opaque "state" */ 93 int extracnt; 94 enum field_e field; /* -f <field> */ 95 char internal_req; /* Sun internal certificate request */ 96 char *pinpath; /* -P <pin> */ 97 char *privpath; /* -k <private_key> */ 98 char *token_label; /* -T <token_label> */ 99 boolean_t verbose; /* chatty output */ 100 } cmd_info; 101 102 enum ret_e { 103 EXIT_OKAY, 104 EXIT_INVALID_ARG, 105 EXIT_VERIFY_FAILED, 106 EXIT_CANT_OPEN_ELF_OBJECT, 107 EXIT_BAD_CERT, 108 EXIT_BAD_PRIVATEKEY, 109 EXIT_SIGN_FAILED, 110 EXIT_VERIFY_FAILED_UNSIGNED, 111 EXIT_CSR_FAILED, 112 EXIT_MEMORY_ERROR 113 }; 114 115 struct field_s { 116 char *name; 117 enum field_e field; 118 } fields[] = { 119 { "subject", FLD_SUBJECT }, 120 { "issuer", FLD_ISSUER }, 121 { "format", FLD_FORMAT }, 122 { "signer", FLD_SIGNER }, 123 { "time", FLD_TIME }, 124 NULL, 0 125 }; 126 127 typedef enum ret_e ret_t; 128 129 static void usage(void); 130 static ret_t getelfobj(char *); 131 static char *getpin(void); 132 static ret_t do_sign(char *); 133 static ret_t do_verify(char *); 134 static ret_t do_cert_request(char *); 135 static ret_t do_gen_esa(char *); 136 static ret_t do_list(char *); 137 static void es_error(const char *fmt, ...); 138 static char *time_str(time_t t); 139 static void sig_info_print(struct ELFsign_sig_info *esip); 140 141 int 142 main(int argc, char **argv) 143 { 144 extern char *optarg; 145 char *scmd = NULL; 146 char *opts; /* The set of flags for cmd */ 147 int errflag = 0; /* We had an options parse error */ 148 char c; /* current getopts flag */ 149 ret_t (*action)(char *); /* Function pointer for the action */ 150 ret_t ret; 151 152 (void) setlocale(LC_ALL, ""); 153 #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */ 154 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 155 #endif 156 (void) textdomain(TEXT_DOMAIN); 157 158 cryptodebug_init("elfsign"); 159 160 if (argc < MIN_ARGS) { 161 es_error(gettext("invalid number of arguments")); 162 usage(); 163 return (EXIT_INVALID_ARG); 164 } 165 166 scmd = argv[1]; 167 cmd_info.cert = NULL; 168 cmd_info.elfobj = NULL; 169 cmd_info.elfcnt = 0; 170 cmd_info.es_action = ES_GET; 171 cmd_info.ess = NULL; 172 cmd_info.extracnt = 0; 173 cmd_info.field = FLD_UNKNOWN; 174 cmd_info.internal_req = '\0'; 175 cmd_info.pinpath = NULL; 176 cmd_info.privpath = NULL; 177 cmd_info.token_label = NULL; 178 cmd_info.verbose = B_FALSE; 179 180 if (strcmp(scmd, SIGN) == 0) { 181 cmd_info.cmd = ES_SIGN; 182 opts = SIGN_OPTS; 183 cryptodebug("cmd=sign opts=%s", opts); 184 action = do_sign; 185 cmd_info.es_action = ES_UPDATE_RSA_SHA1; 186 } else if (strcmp(scmd, VERIFY) == 0) { 187 cmd_info.cmd = ES_VERIFY; 188 opts = VERIFY_OPTS; 189 cryptodebug("cmd=verify opts=%s", opts); 190 action = do_verify; 191 } else if (strcmp(scmd, REQUEST) == 0) { 192 cmd_info.cmd = ES_REQUEST; 193 opts = REQUEST_OPTS; 194 cryptodebug("cmd=request opts=%s", opts); 195 action = do_cert_request; 196 } else if (strcmp(scmd, LIST) == 0) { 197 cmd_info.cmd = ES_LIST; 198 opts = LIST_OPTS; 199 cryptodebug("cmd=list opts=%s", opts); 200 action = do_list; 201 } else { 202 es_error(gettext("Unknown sub-command: %s"), 203 scmd); 204 usage(); 205 return (EXIT_INVALID_ARG); 206 } 207 208 /* 209 * Note: There is no need to check that optarg isn't NULL 210 * because getopt does that for us. 211 */ 212 while (!errflag && (c = getopt(argc - 1, argv + 1, opts)) != EOF) { 213 if (strchr("ceFihkPTr", c) != NULL) 214 cryptodebug("c=%c, '%s'", c, optarg); 215 else 216 cryptodebug("c=%c", c); 217 218 switch (c) { 219 case 'a': 220 /* not a normal sign operation, change the action */ 221 cmd_info.es_action = ES_GET; 222 action = do_gen_esa; 223 break; 224 case 'c': 225 cmd_info.cert = optarg; 226 break; 227 case 'e': 228 cmd_info.elfcnt++; 229 cmd_info.elfobj = (char **)realloc(cmd_info.elfobj, 230 sizeof (char *) * cmd_info.elfcnt); 231 if (cmd_info.elfobj == NULL) { 232 es_error(gettext( 233 "Too many elf objects specified.")); 234 return (EXIT_INVALID_ARG); 235 } 236 cmd_info.elfobj[cmd_info.elfcnt - 1] = optarg; 237 break; 238 case 'f': 239 { 240 struct field_s *fp; 241 cmd_info.field = FLD_UNKNOWN; 242 for (fp = fields; fp->name != NULL; fp++) { 243 if (strcasecmp(optarg, fp->name) == 0) { 244 cmd_info.field = fp->field; 245 break; 246 } 247 } 248 if (cmd_info.field == FLD_UNKNOWN) { 249 cryptodebug("Invalid field option"); 250 errflag++; 251 } 252 } 253 break; 254 case 'F': 255 if (strcasecmp(optarg, ES_FMT_RSA_MD5_SHA1) == 0) 256 cmd_info.es_action = ES_UPDATE_RSA_MD5_SHA1; 257 else if (strcasecmp(optarg, ES_FMT_RSA_SHA1) == 0) 258 cmd_info.es_action = ES_UPDATE_RSA_SHA1; 259 else { 260 cryptodebug("Invalid format option"); 261 errflag++; 262 } 263 break; 264 case 'i': /* Undocumented internal Sun use only */ 265 cmd_info.internal_req = *optarg; 266 break; 267 case 'k': 268 cmd_info.privpath = optarg; 269 if (cmd_info.token_label != NULL || 270 cmd_info.pinpath != NULL) 271 errflag++; 272 break; 273 case 'P': 274 cmd_info.pinpath = optarg; 275 if (cmd_info.privpath != NULL) 276 errflag++; 277 break; 278 case 'r': 279 cmd_info.cert = optarg; 280 break; 281 case 'T': 282 cmd_info.token_label = optarg; 283 if (cmd_info.privpath != NULL) 284 errflag++; 285 break; 286 case 'v': 287 cmd_info.verbose = B_TRUE; 288 break; 289 default: 290 errflag++; 291 } 292 } 293 294 optind++; /* we skipped over subcommand */ 295 cmd_info.extracnt = argc - optind; 296 297 if (cmd_info.extracnt != 0 && 298 cmd_info.cmd != ES_SIGN && cmd_info.cmd != ES_VERIFY) { 299 cryptodebug("Extra arguments, optind=%d, argc=%d", 300 optind, argc); 301 errflag++; 302 } 303 304 switch (cmd_info.cmd) { 305 case ES_VERIFY: 306 if (cmd_info.elfcnt + argc - optind == 0) { 307 cryptodebug("Missing elfobj"); 308 errflag++; 309 } 310 break; 311 312 case ES_SIGN: 313 if (((cmd_info.privpath == NULL) && 314 (cmd_info.token_label == NULL)) || 315 (cmd_info.cert == NULL) || 316 (cmd_info.elfcnt + argc - optind == 0)) { 317 cryptodebug("Missing privpath|token_label/cert/elfobj"); 318 errflag++; 319 } 320 break; 321 322 case ES_REQUEST: 323 if (((cmd_info.privpath == NULL) && 324 (cmd_info.token_label == NULL)) || 325 (cmd_info.cert == NULL)) { 326 cryptodebug("Missing privpath|token_label/certreq"); 327 errflag++; 328 } 329 break; 330 case ES_LIST: 331 if ((cmd_info.cert != NULL) == (cmd_info.elfcnt > 0)) { 332 cryptodebug("Neither or both of cert/elfobj"); 333 errflag++; 334 } 335 break; 336 } 337 338 if (errflag) { 339 usage(); 340 return (EXIT_INVALID_ARG); 341 } 342 343 switch (cmd_info.cmd) { 344 case ES_REQUEST: 345 case ES_LIST: 346 ret = action(NULL); 347 break; 348 default: 349 { 350 int i; 351 ret_t iret; 352 353 ret = EXIT_OKAY; 354 iret = EXIT_OKAY; 355 for (i = 0; i < cmd_info.elfcnt && 356 (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) { 357 iret = action(cmd_info.elfobj[i]); 358 if (iret > ret) 359 ret = iret; 360 } 361 for (i = optind; i < argc && 362 (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) { 363 iret = action(argv[i]); 364 if (iret > ret) 365 ret = iret; 366 } 367 break; 368 } 369 } 370 371 if (cmd_info.elfobj != NULL) 372 free(cmd_info.elfobj); 373 374 return (ret); 375 } 376 377 378 static void 379 usage(void) 380 { 381 /* BEGIN CSTYLED */ 382 (void) fprintf(stderr, gettext( 383 "usage:\n" 384 "\telfsign sign [-a] [-v] [-e <elf_object>] -c <certificate_file>\n" 385 "\t\t[-F <format>] -k <private_key_file> [elf_object]..." 386 "\n" 387 "\telfsign sign [-a] [-v] [-e <elf_object>] -c <certificate_file>\n" 388 "\t\t[-F <format>] -T <token_label> [-P <pin_file>] [elf_object]..." 389 "\n\n" 390 "\telfsign verify [-v] [-c <certificate_file>] [-e <elf_object>]\n" 391 "\t\t[elf_object]..." 392 "\n\n" 393 "\telfsign request -r <certificate_request_file> -k <private_key_file>" 394 "\n" 395 "\telfsign request -r <certificate_request_file> -T <token_label>" 396 "\n\n" 397 "\telfsign list -f field -c <certificate_file>" 398 "\n" 399 "\telfsign list -f field -e <elf_object>" 400 "\n")); 401 /* END CSTYLED */ 402 } 403 404 static ret_t 405 getelfobj(char *elfpath) 406 { 407 ELFsign_status_t estatus; 408 ret_t ret = EXIT_SIGN_FAILED; 409 410 estatus = elfsign_begin(elfpath, cmd_info.es_action, &(cmd_info.ess)); 411 switch (estatus) { 412 case ELFSIGN_SUCCESS: 413 case ELFSIGN_RESTRICTED: 414 ret = EXIT_OKAY; 415 break; 416 case ELFSIGN_INVALID_ELFOBJ: 417 es_error(gettext( 418 "Unable to open %s as an ELF object."), 419 elfpath); 420 ret = EXIT_CANT_OPEN_ELF_OBJECT; 421 break; 422 default: 423 es_error(gettext("unexpected failure: %d"), estatus); 424 if (cmd_info.cmd == ES_SIGN) { 425 ret = EXIT_SIGN_FAILED; 426 } else if (cmd_info.cmd == ES_VERIFY) { 427 ret = EXIT_VERIFY_FAILED; 428 } 429 } 430 431 return (ret); 432 } 433 434 static ret_t 435 setcertpath(void) 436 { 437 ELFsign_status_t estatus; 438 ret_t ret = EXIT_SIGN_FAILED; 439 440 if (cmd_info.cert == NULL) 441 return (EXIT_OKAY); 442 estatus = elfsign_setcertpath(cmd_info.ess, cmd_info.cert); 443 switch (estatus) { 444 case ELFSIGN_SUCCESS: 445 ret = EXIT_OKAY; 446 break; 447 case ELFSIGN_INVALID_CERTPATH: 448 if (cmd_info.cert != NULL) { 449 es_error(gettext("Unable to open %s as a certificate."), 450 cmd_info.cert); 451 } 452 ret = EXIT_BAD_CERT; 453 break; 454 default: 455 es_error(gettext("unusable certificate: %s"), cmd_info.cert); 456 if (cmd_info.cmd == ES_SIGN) { 457 ret = EXIT_SIGN_FAILED; 458 } else if (cmd_info.cmd == ES_VERIFY) { 459 ret = EXIT_VERIFY_FAILED; 460 } 461 } 462 463 return (ret); 464 } 465 466 /* 467 * getpin - return pointer to token PIN in static storage 468 */ 469 static char * 470 getpin(void) 471 { 472 static char pinbuf[PASS_MAX + 1]; 473 char *pp; 474 FILE *pinfile; 475 476 if (cmd_info.pinpath == NULL) 477 return (getpassphrase( 478 gettext("Enter PIN for PKCS#11 token: "))); 479 if ((pinfile = fopen(cmd_info.pinpath, "r")) == NULL) { 480 es_error(gettext("failed to open %s."), 481 cmd_info.pinpath); 482 return (NULL); 483 } 484 485 pp = fgets(pinbuf, sizeof (pinbuf), pinfile); 486 (void) fclose(pinfile); 487 if (pp == NULL) { 488 es_error(gettext("failed to read PIN from %s."), 489 cmd_info.pinpath); 490 return (NULL); 491 } 492 pp = &pinbuf[strlen(pinbuf) - 1]; 493 if (*pp == '\n') 494 *pp = '\0'; 495 return (pinbuf); 496 } 497 498 /* 499 * Add the .SUNW_signature sections for the ELF signature 500 */ 501 static ret_t 502 do_sign(char *object) 503 { 504 ret_t ret; 505 ELFsign_status_t elfstat; 506 struct filesignatures *fssp = NULL; 507 size_t fs_len; 508 uchar_t sig[SIG_MAX_LENGTH]; 509 size_t sig_len = SIG_MAX_LENGTH; 510 uchar_t hash[SIG_MAX_LENGTH]; 511 size_t hash_len = SIG_MAX_LENGTH; 512 ELFCert_t cert = NULL; 513 char *dn; 514 size_t dn_len; 515 516 cryptodebug("do_sign"); 517 if ((ret = getelfobj(object)) != EXIT_OKAY) 518 return (ret); 519 520 if (cmd_info.token_label && 521 !elfcertlib_settoken(cmd_info.ess, cmd_info.token_label)) { 522 es_error(gettext("Unable to access token: %s"), 523 cmd_info.token_label); 524 ret = EXIT_SIGN_FAILED; 525 goto cleanup; 526 } 527 528 if ((ret = setcertpath()) != EXIT_OKAY) 529 goto cleanup; 530 531 if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert, 532 cmd_info.es_action)) { 533 es_error(gettext("Unable to load certificate: %s"), 534 cmd_info.cert); 535 ret = EXIT_BAD_CERT; 536 goto cleanup; 537 } 538 539 if (cmd_info.privpath != NULL) { 540 if (!elfcertlib_loadprivatekey(cmd_info.ess, cert, 541 cmd_info.privpath)) { 542 es_error(gettext("Unable to load private key: %s"), 543 cmd_info.privpath); 544 ret = EXIT_BAD_PRIVATEKEY; 545 goto cleanup; 546 } 547 } else { 548 char *pin = getpin(); 549 if (pin == NULL) { 550 es_error(gettext("Unable to get PIN")); 551 ret = EXIT_BAD_PRIVATEKEY; 552 goto cleanup; 553 } 554 if (!elfcertlib_loadtokenkey(cmd_info.ess, cert, 555 cmd_info.token_label, pin)) { 556 es_error(gettext("Unable to access private key " 557 "in token %s"), cmd_info.token_label); 558 ret = EXIT_BAD_PRIVATEKEY; 559 goto cleanup; 560 } 561 } 562 563 /* 564 * Get the DN from the certificate. 565 */ 566 if ((dn = elfcertlib_getdn(cert)) == NULL) { 567 es_error(gettext("Unable to find DN in certificate %s"), 568 cmd_info.cert); 569 ret = EXIT_SIGN_FAILED; 570 goto cleanup; 571 } 572 dn_len = strlen(dn); 573 cryptodebug("DN = %s", dn); 574 575 elfstat = elfsign_signatures(cmd_info.ess, &fssp, &fs_len, ES_GET); 576 if (elfstat != ELFSIGN_SUCCESS) { 577 if (elfstat != ELFSIGN_NOTSIGNED) { 578 es_error(gettext("Unable to retrieve existing " 579 "signature block in %s"), object); 580 ret = EXIT_SIGN_FAILED; 581 goto cleanup; 582 } 583 fssp = NULL; 584 /* 585 * force creation and naming of signature section 586 * so the hash doesn't change 587 */ 588 if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len, 589 cmd_info.es_action) != ELFSIGN_SUCCESS) { 590 es_error(gettext("Unable to insert " 591 "signature block into %s"), object); 592 ret = EXIT_SIGN_FAILED; 593 goto cleanup; 594 } 595 } 596 597 bzero(hash, sizeof (hash)); 598 if (elfsign_hash(cmd_info.ess, hash, &hash_len) != ELFSIGN_SUCCESS) { 599 es_error(gettext("Unable to calculate hash of ELF object %s"), 600 object); 601 ret = EXIT_SIGN_FAILED; 602 goto cleanup; 603 } 604 605 bzero(sig, sizeof (sig)); 606 if (!elfcertlib_sign(cmd_info.ess, cert, 607 hash, hash_len, sig, &sig_len)) { 608 es_error(gettext("Unable to sign %s using key from %s"), 609 object, cmd_info.privpath ? 610 cmd_info.privpath : cmd_info.token_label); 611 ret = EXIT_SIGN_FAILED; 612 goto cleanup; 613 } 614 615 { /* DEBUG START */ 616 const int sigstr_len = sizeof (char) * sig_len * 2 + 1; 617 char *sigstr = malloc(sigstr_len); 618 619 tohexstr(sig, sig_len, sigstr, sigstr_len); 620 cryptodebug("sig value is: %s", sigstr); 621 free(sigstr); 622 } /* DEBUG END */ 623 624 fssp = elfsign_insert_dso(cmd_info.ess, fssp, 625 dn, dn_len, sig, sig_len, NULL, 0); 626 if (fssp == NULL) { 627 es_error(gettext("Unable to prepare signature for %s"), 628 object); 629 ret = EXIT_SIGN_FAILED; 630 goto cleanup; 631 } 632 if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len, 633 cmd_info.es_action) != ELFSIGN_SUCCESS) { 634 es_error(gettext("Unable to update %s: with signature"), 635 object); 636 ret = EXIT_SIGN_FAILED; 637 goto cleanup; 638 } 639 if (cmd_info.verbose || (cmd_info.elfcnt + cmd_info.extracnt) > 1) { 640 (void) fprintf(stdout, 641 gettext("elfsign: %s signed successfully.\n"), 642 object); 643 } 644 if (cmd_info.verbose) { 645 struct ELFsign_sig_info *esip; 646 647 if (elfsign_sig_info(fssp, &esip)) { 648 sig_info_print(esip); 649 elfsign_sig_info_free(esip); 650 } 651 } 652 653 ret = EXIT_OKAY; 654 655 cleanup: 656 free(fssp); 657 bzero(sig, sig_len); 658 bzero(hash, hash_len); 659 660 if (cert != NULL) 661 elfcertlib_releasecert(cmd_info.ess, cert); 662 if (cmd_info.ess != NULL) 663 elfsign_end(cmd_info.ess); 664 665 return (ret); 666 } 667 668 #define ESA_ERROR(str, esa_file) { \ 669 int realerrno = errno; \ 670 es_error(gettext(str), esa_file, strerror(realerrno)); \ 671 goto clean_esa; \ 672 } 673 674 /* 675 * Generate the elfsign activation file (.esa) for this request. 676 * The .esa file should contain the signature of main binary 677 * signed with an unlimited certificate, the DN and its own signature. 678 * 679 * The format is as follows: 680 * ----------------------------- 681 * A | main signature length | 682 * ----------------------------- 683 * B | main signature (copy of | 684 * | signature from original | 685 * | limited-use binary | 686 * ----------------------------- 687 * C | signing DN length | 688 * ----------------------------- 689 * D | signing DN | 690 * ----------------------------- 691 * E | esa signature length | 692 * ----------------------------- 693 * F | esa signature = | 694 * | RSA(HASH(A||B) | 695 * ----------------------------- 696 * (lengths are in the same endianness as the original object) 697 * 698 * cmd_info.ess set for the main binary is correct here, since this 699 * is the only elf object we are actually dealing with during the .esa 700 * generation. 701 */ 702 static ret_t 703 do_gen_esa(char *object) 704 { 705 ret_t ret; 706 707 /* variables used for signing and writing to .esa file */ 708 char *elfobj_esa; 709 size_t elfobj_esa_len; 710 int esa_fd; 711 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; 712 uchar_t *esa_buf = NULL; 713 size_t esa_buf_len = 0; 714 uchar_t hash[SIG_MAX_LENGTH], *hash_ptr = hash; 715 size_t hash_len = SIG_MAX_LENGTH; 716 uchar_t esa_sig[SIG_MAX_LENGTH]; 717 size_t esa_sig_len = SIG_MAX_LENGTH; 718 struct filesignatures *fssp = NULL; 719 size_t fslen; 720 ELFCert_t cert = NULL; 721 char *dn; 722 size_t dn_len; 723 uchar_t tmp_buf[sizeof (uint32_t)]; 724 int realerrno = 0; 725 726 /* 727 * variables used for finding information on signer of main 728 * elfobject. 729 */ 730 uchar_t orig_signature[SIG_MAX_LENGTH]; 731 size_t orig_sig_len = sizeof (orig_signature); 732 733 cryptodebug("do_gen_esa"); 734 if ((ret = getelfobj(object)) != EXIT_OKAY) 735 return (ret); 736 ret = EXIT_SIGN_FAILED; 737 738 if (cmd_info.token_label && 739 !elfcertlib_settoken(cmd_info.ess, cmd_info.token_label)) { 740 es_error(gettext("Unable to access token: %s"), 741 cmd_info.token_label); 742 ret = EXIT_SIGN_FAILED; 743 goto clean_esa; 744 } 745 746 if ((ret = setcertpath()) != EXIT_OKAY) 747 goto clean_esa; 748 749 /* 750 * Find the certificate we need to sign the activation file with. 751 */ 752 if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert, 753 cmd_info.es_action)) { 754 es_error(gettext("Unable to load certificate: %s"), 755 cmd_info.cert); 756 ret = EXIT_BAD_CERT; 757 goto clean_esa; 758 } 759 760 if (cmd_info.privpath != NULL) { 761 if (!elfcertlib_loadprivatekey(cmd_info.ess, cert, 762 cmd_info.privpath)) { 763 es_error(gettext("Unable to load private key: %s"), 764 cmd_info.privpath); 765 ret = EXIT_BAD_PRIVATEKEY; 766 goto clean_esa; 767 } 768 } else { 769 char *pin = getpin(); 770 771 if (pin == NULL) { 772 cryptoerror(LOG_STDERR, gettext("Unable to get PIN")); 773 ret = EXIT_BAD_PRIVATEKEY; 774 goto clean_esa; 775 } 776 if (!elfcertlib_loadtokenkey(cmd_info.ess, cert, 777 cmd_info.token_label, pin)) { 778 es_error(gettext("Unable to access private key " 779 "in token %s"), cmd_info.token_label); 780 ret = EXIT_BAD_PRIVATEKEY; 781 goto clean_esa; 782 } 783 } 784 785 /* 786 * Get the DN from the certificate. 787 */ 788 if ((dn = elfcertlib_getdn(cert)) == NULL) { 789 es_error(gettext("Unable to find DN in certifiate %s"), 790 cmd_info.cert); 791 goto clean_esa; 792 } 793 dn_len = strlen(dn); 794 cryptodebug("DN = %s", dn); 795 796 /* 797 * Make sure they are not trying to sign .esa file with a 798 * limited certificate. 799 */ 800 if (strstr(dn, USAGELIMITED) != NULL) { 801 es_error(gettext("Activation file must be signed with a " 802 "certficate without %s."), USAGELIMITED); 803 goto clean_esa; 804 } 805 806 /* 807 * Find information in the associated elfobject that will 808 * be needed to generate the activation file. 809 */ 810 if (elfsign_signatures(cmd_info.ess, &fssp, &fslen, ES_GET) != 811 ELFSIGN_SUCCESS) { 812 es_error(gettext("%s must be signed first, before an " 813 "associated activation file can be created."), 814 object); 815 goto clean_esa; 816 } 817 if (elfsign_extract_sig(cmd_info.ess, fssp, 818 orig_signature, &orig_sig_len) == FILESIG_UNKNOWN) { 819 es_error(gettext("elfsign can not create " 820 "an associated activation file for the " 821 "signature format of %s."), 822 object); 823 goto clean_esa; 824 } 825 { /* DEBUG START */ 826 const int sigstr_len = orig_sig_len * 2 + 1; 827 char *sigstr = malloc(sigstr_len); 828 829 tohexstr(orig_signature, orig_sig_len, sigstr, sigstr_len); 830 cryptodebug("signature value is: %s", sigstr); 831 cryptodebug("sig size value is: %d", orig_sig_len); 832 free(sigstr); 833 } /* DEBUG END */ 834 835 esa_buf_len = sizeof (uint32_t) + orig_sig_len; 836 esa_buf = malloc(esa_buf_len); 837 if (esa_buf == NULL) { 838 es_error(gettext("Unable to allocate memory for .esa buffer")); 839 goto clean_esa; 840 } 841 842 /* 843 * Write eventual contents of .esa file to a temporary 844 * buffer, so we can sign it before writing out to 845 * the file. 846 */ 847 elfsign_buffer_len(cmd_info.ess, &orig_sig_len, esa_buf, ES_UPDATE); 848 (void) memcpy(esa_buf + sizeof (uint32_t), orig_signature, 849 orig_sig_len); 850 851 if (elfsign_hash_esa(cmd_info.ess, esa_buf, esa_buf_len, 852 &hash_ptr, &hash_len) != ELFSIGN_SUCCESS) { 853 es_error(gettext("Unable to calculate activation hash")); 854 goto clean_esa; 855 } 856 857 /* 858 * sign the buffer for the .esa file 859 */ 860 if (!elfcertlib_sign(cmd_info.ess, cert, 861 hash_ptr, hash_len, esa_sig, &esa_sig_len)) { 862 es_error(gettext("Unable to sign .esa data using key from %s"), 863 cmd_info.privpath ? 864 cmd_info.privpath : cmd_info.token_label); 865 goto clean_esa; 866 } 867 868 { /* DEBUG START */ 869 const int sigstr_len = esa_sig_len * 2 + 1; 870 char *sigstr = malloc(sigstr_len); 871 872 tohexstr(esa_sig, esa_sig_len, sigstr, sigstr_len); 873 cryptodebug("esa signature value is: %s", sigstr); 874 cryptodebug("esa size value is: %d", esa_sig_len); 875 free(sigstr); 876 } /* DEBUG END */ 877 878 /* 879 * Create the empty activation file once we know 880 * we are working with the good data. 881 */ 882 elfobj_esa_len = strlen(object) + ESA_LEN + 1; 883 elfobj_esa = malloc(elfobj_esa_len); 884 885 if (elfobj_esa == NULL) { 886 es_error(gettext("Unable to allocate buffer for esa filename")); 887 goto clean_esa; 888 } 889 890 (void) strlcpy(elfobj_esa, object, elfobj_esa_len); 891 (void) strlcat(elfobj_esa, ESA, elfobj_esa_len); 892 893 cryptodebug("Creating .esa file: %s", elfobj_esa); 894 895 if ((esa_fd = open(elfobj_esa, O_WRONLY|O_CREAT|O_EXCL, mode)) == -1) { 896 ESA_ERROR("Unable to create activation file: %s. %s.", 897 elfobj_esa); 898 } 899 900 if (write(esa_fd, esa_buf, esa_buf_len) != esa_buf_len) { 901 ESA_ERROR("Unable to write contents to %s. %s.", 902 elfobj_esa); 903 } 904 905 { /* DEBUG START */ 906 const int sigstr_len = dn_len * 2 + 1; 907 char *sigstr = malloc(sigstr_len); 908 909 tohexstr((uchar_t *)dn, dn_len, sigstr, sigstr_len); 910 cryptodebug("dn value is: %s", sigstr); 911 cryptodebug("dn size value is: %d", dn_len); 912 free(sigstr); 913 } /* DEBUG END */ 914 915 elfsign_buffer_len(cmd_info.ess, &dn_len, tmp_buf, ES_UPDATE); 916 if (write(esa_fd, tmp_buf, sizeof (tmp_buf)) != sizeof (tmp_buf)) { 917 ESA_ERROR("Unable to write dn_len to %s. %s.", elfobj_esa); 918 } 919 920 if (write(esa_fd, dn, dn_len) != dn_len) { 921 ESA_ERROR("Unable to write dn to %s. %s.", elfobj_esa); 922 } 923 924 elfsign_buffer_len(cmd_info.ess, &esa_sig_len, tmp_buf, ES_UPDATE); 925 if (write(esa_fd, tmp_buf, sizeof (tmp_buf)) != sizeof (tmp_buf)) { 926 ESA_ERROR("Unable to write .esa signature len to %s. %s.", 927 elfobj_esa); 928 } 929 930 if (write(esa_fd, esa_sig, esa_sig_len) != esa_sig_len) { 931 realerrno = errno; 932 es_error(gettext("Unable to write .esa signature. %s."), 933 strerror(realerrno)); 934 goto clean_esa; 935 } 936 937 ret = EXIT_OKAY; 938 939 clean_esa: 940 free(fssp); 941 if (esa_fd != -1) 942 (void) close(esa_fd); 943 944 if (esa_buf != NULL) 945 free(esa_buf); 946 947 bzero(esa_sig, esa_sig_len); 948 949 if (cert != NULL) 950 elfcertlib_releasecert(cmd_info.ess, cert); 951 if (cmd_info.ess != NULL) 952 elfsign_end(cmd_info.ess); 953 954 return (ret); 955 } 956 957 /* 958 * Verify the signature of the object 959 * This subcommand is intended to be used by developers during their build 960 * processes. Therefore we can not assume that the certificate is in 961 * /etc/crypto/certs so we must use the path we got from the commandline. 962 */ 963 static ret_t 964 do_verify(char *object) 965 { 966 ELFsign_status_t res; 967 struct ELFsign_sig_info *esip; 968 ret_t retval; 969 970 cryptodebug("do_verify"); 971 if ((retval = getelfobj(object)) != EXIT_OKAY) 972 return (retval); 973 974 if ((retval = setcertpath()) != EXIT_OKAY) { 975 elfsign_end(cmd_info.ess); 976 return (retval); 977 } 978 979 res = elfsign_verify_signature(cmd_info.ess, &esip); 980 switch (res) { 981 case ELFSIGN_SUCCESS: 982 (void) fprintf(stdout, 983 gettext("elfsign: verification of %s passed.\n"), 984 object); 985 if (cmd_info.verbose) 986 sig_info_print(esip); 987 retval = EXIT_OKAY; 988 break; 989 case ELFSIGN_RESTRICTED: 990 (void) fprintf(stdout, 991 gettext("elfsign: verification of %s passed, " 992 "but restricted.\n"), object); 993 if (cmd_info.verbose) 994 sig_info_print(esip); 995 retval = EXIT_OKAY; 996 break; 997 case ELFSIGN_FAILED: 998 case ELFSIGN_INVALID_CERTPATH: 999 es_error(gettext("verification of %s failed."), 1000 object); 1001 if (cmd_info.verbose) 1002 sig_info_print(esip); 1003 retval = EXIT_VERIFY_FAILED; 1004 break; 1005 case ELFSIGN_NOTSIGNED: 1006 es_error(gettext("no signature found in %s."), 1007 object); 1008 retval = EXIT_VERIFY_FAILED_UNSIGNED; 1009 break; 1010 default: 1011 es_error(gettext("unexpected failure attempting verification " 1012 "of %s."), object); 1013 retval = EXIT_VERIFY_FAILED_UNSIGNED; 1014 break; 1015 } 1016 1017 if (esip != NULL) 1018 elfsign_sig_info_free(esip); 1019 if (cmd_info.ess != NULL) 1020 elfsign_end(cmd_info.ess); 1021 return (retval); 1022 } 1023 1024 #define SET_VALUE(f, s) \ 1025 kmfrv = f; \ 1026 if (kmfrv != KMF_OK) { \ 1027 char *e = NULL; \ 1028 (void) kmf_get_kmf_error_str(kmfrv, &e); \ 1029 cryptoerror(LOG_STDERR, \ 1030 gettext("Failed to %s: %s\n"), \ 1031 s, (e ? e : "unknown error")); \ 1032 if (e) free(e); \ 1033 goto cleanup; \ 1034 } 1035 1036 static KMF_RETURN 1037 create_csr(char *dn) 1038 { 1039 KMF_RETURN kmfrv = KMF_OK; 1040 KMF_HANDLE_T kmfhandle = NULL; 1041 KMF_KEY_HANDLE pubk, prik; 1042 KMF_X509_NAME csrSubject; 1043 KMF_CSR_DATA csr; 1044 KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA; 1045 KMF_DATA signedCsr = { NULL, 0 }; 1046 char *err; 1047 KMF_ATTRIBUTE attrlist[16]; 1048 KMF_ENCODE_FORMAT format; 1049 KMF_KEYSTORE_TYPE kstype; 1050 KMF_KEY_ALG keytype; 1051 uint32_t keylength; 1052 KMF_CREDENTIAL cred; 1053 char *pin = NULL; 1054 int numattr; 1055 1056 if ((kmfrv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 1057 (void) kmf_get_kmf_error_str(kmfrv, &err); 1058 cryptoerror(LOG_STDERR, 1059 gettext("Error initializing KMF: %s\n"), 1060 (err ? err : "unknown error")); 1061 if (err) 1062 free(err); 1063 return (kmfrv); 1064 } 1065 (void) memset(&csr, 0, sizeof (csr)); 1066 (void) memset(&csrSubject, 0, sizeof (csrSubject)); 1067 1068 if (cmd_info.privpath != NULL) { 1069 kstype = KMF_KEYSTORE_OPENSSL; 1070 format = KMF_FORMAT_ASN1; 1071 } else { 1072 boolean_t readonly; 1073 /* args checking verified (cmd_info.token_label != NULL) */ 1074 1075 /* Get a PIN to store the private key in the token */ 1076 pin = getpin(); 1077 1078 if (pin == NULL) { 1079 (void) kmf_finalize(kmfhandle); 1080 return (KMF_ERR_AUTH_FAILED); 1081 } 1082 1083 kstype = KMF_KEYSTORE_PK11TOKEN; 1084 readonly = B_FALSE; 1085 1086 numattr = 0; 1087 kmf_set_attr_at_index(attrlist, numattr++, 1088 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1089 kmf_set_attr_at_index(attrlist, numattr++, 1090 KMF_TOKEN_LABEL_ATTR, cmd_info.token_label, 1091 strlen(cmd_info.token_label)); 1092 kmf_set_attr_at_index(attrlist, numattr++, 1093 KMF_READONLY_ATTR, &readonly, sizeof (readonly)); 1094 kmfrv = kmf_configure_keystore(kmfhandle, numattr, attrlist); 1095 if (kmfrv != KMF_OK) { 1096 goto cleanup; 1097 } 1098 } 1099 1100 /* Create the RSA keypair */ 1101 keytype = KMF_RSA; 1102 keylength = ES_DEFAULT_KEYSIZE; 1103 (void) memset(&prik, 0, sizeof (prik)); 1104 (void) memset(&pubk, 0, sizeof (pubk)); 1105 1106 numattr = 0; 1107 kmf_set_attr_at_index(attrlist, numattr++, 1108 KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1109 kmf_set_attr_at_index(attrlist, numattr++, 1110 KMF_KEYALG_ATTR, &keytype, sizeof (keytype)); 1111 kmf_set_attr_at_index(attrlist, numattr++, 1112 KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength)); 1113 if (pin != NULL) { 1114 cred.cred = pin; 1115 cred.credlen = strlen(pin); 1116 kmf_set_attr_at_index(attrlist, numattr++, 1117 KMF_CREDENTIAL_ATTR, &cred, sizeof (KMF_CREDENTIAL)); 1118 } 1119 kmf_set_attr_at_index(attrlist, numattr++, 1120 KMF_PRIVKEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE)); 1121 kmf_set_attr_at_index(attrlist, numattr++, 1122 KMF_PUBKEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE)); 1123 if (kstype == KMF_KEYSTORE_OPENSSL) { 1124 kmf_set_attr_at_index(attrlist, numattr++, 1125 KMF_KEY_FILENAME_ATTR, cmd_info.privpath, 1126 strlen(cmd_info.privpath)); 1127 kmf_set_attr_at_index(attrlist, numattr++, 1128 KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format)); 1129 } 1130 1131 kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist); 1132 if (kmfrv != KMF_OK) { 1133 (void) kmf_get_kmf_error_str(kmfrv, &err); 1134 cryptoerror(LOG_STDERR, 1135 gettext("Create RSA keypair failed: %s"), 1136 (err ? err : "unknown error")); 1137 free(err); 1138 goto cleanup; 1139 } 1140 1141 kmfrv = kmf_dn_parser(dn, &csrSubject); 1142 if (kmfrv != KMF_OK) { 1143 (void) kmf_get_kmf_error_str(kmfrv, &err); 1144 cryptoerror(LOG_STDERR, 1145 gettext("Error parsing subject name: %s\n"), 1146 (err ? err : "unknown error")); 1147 free(err); 1148 goto cleanup; 1149 } 1150 1151 SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair"); 1152 1153 SET_VALUE(kmf_set_csr_version(&csr, 2), "version number"); 1154 1155 SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name"); 1156 1157 SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "SignatureAlgorithm"); 1158 1159 if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) == 1160 KMF_OK) { 1161 kmfrv = kmf_create_csr_file(&signedCsr, KMF_FORMAT_PEM, 1162 cmd_info.cert); 1163 } 1164 1165 cleanup: 1166 (void) kmf_free_kmf_key(kmfhandle, &prik); 1167 (void) kmf_free_data(&signedCsr); 1168 (void) kmf_free_signed_csr(&csr); 1169 (void) kmf_finalize(kmfhandle); 1170 1171 return (kmfrv); 1172 } 1173 1174 static boolean_t 1175 is_restricted(void) 1176 { 1177 char nr[80]; /* Non-retail provider? big buffer for l10n */ 1178 char *yeschar = nl_langinfo(YESSTR); 1179 char *nochar = nl_langinfo(NOSTR); 1180 1181 /* 1182 * Find out if user will need an activation file. 1183 * These questions cover cases #1 and #2 from the Jumbo Export 1184 * Control case. The logic of these questions should not be modified 1185 * without consulting the jumbo case, unless there is a new 1186 * export case or a change in export/import regulations for Sun 1187 * and Sun customers. 1188 * Case #3 should be covered in the developer documentation. 1189 */ 1190 /* BEGIN CSTYLED */ 1191 (void) fprintf(stdout, gettext("\n" 1192 "The government of the United States of America restricts the export of \n" 1193 "\"open cryptographic interfaces\", also known as \"crypto-with-a-hole\".\n" 1194 "Due to this restriction, all providers for the Solaris cryptographic\n" 1195 "framework must be signed, regardless of the country of origin.\n\n")); 1196 1197 (void) fprintf(stdout, gettext( 1198 "The terms \"retail\" and \"non-retail\" refer to export classifications \n" 1199 "for products manufactured in the USA. These terms define the portion of the\n" 1200 "world where the product may be shipped. Roughly speaking, \"retail\" is \n" 1201 "worldwide (minus certain excluded nations) and \"non-retail\" is domestic \n" 1202 "only (plus some highly favored nations). If your provider is subject to\n" 1203 "USA export control, then you must obtain an export approval (classification)\n" 1204 "from the government of the USA before exporting your provider. It is\n" 1205 "critical that you specify the obtained (or expected, when used during \n" 1206 "development) classification to the following questions so that your provider\n" 1207 "will be appropriately signed.\n\n")); 1208 1209 for (;;) { 1210 (void) fprintf(stdout, gettext( 1211 "Do you have retail export approval for use without restrictions based \n" 1212 "on the caller (for example, IPsec)? [Yes/No] ")); 1213 /* END CSTYLED */ 1214 1215 (void) fflush(stdout); 1216 1217 (void) fgets(nr, sizeof (nr), stdin); 1218 if (nr == NULL) 1219 goto demand_answer; 1220 1221 nr[strlen(nr) - 1] = '\0'; 1222 1223 if (strncasecmp(nochar, nr, 1) == 0) { 1224 /* BEGIN CSTYLED */ 1225 (void) fprintf(stdout, gettext("\n" 1226 "If you have non-retail export approval for unrestricted use of your provider\n" 1227 "by callers, are you also planning to receive retail approval by restricting \n" 1228 "which export sensitive callers (for example, IPsec) may use your \n" 1229 "provider? [Yes/No] ")); 1230 /* END CSTYLED */ 1231 1232 (void) fflush(stdout); 1233 1234 (void) fgets(nr, sizeof (nr), stdin); 1235 1236 /* 1237 * flush standard input so any remaining text 1238 * does not affect next read. 1239 */ 1240 (void) fflush(stdin); 1241 1242 if (nr == NULL) 1243 goto demand_answer; 1244 1245 nr[strlen(nr) - 1] = '\0'; 1246 1247 if (strncasecmp(nochar, nr, 1) == 0) { 1248 return (B_FALSE); 1249 } else if (strncasecmp(yeschar, nr, 1) == 0) { 1250 return (B_TRUE); 1251 } else 1252 goto demand_answer; 1253 1254 } else if (strncasecmp(yeschar, nr, 1) == 0) { 1255 return (B_FALSE); 1256 } 1257 1258 demand_answer: 1259 (void) fprintf(stdout, 1260 gettext("You must specify an answer.\n\n")); 1261 } 1262 } 1263 1264 #define CN_MAX_LENGTH 64 /* Verisign implementation limit */ 1265 /* 1266 * Generate a certificate request into the file named cmd_info.cert 1267 */ 1268 /*ARGSUSED*/ 1269 static ret_t 1270 do_cert_request(char *object) 1271 { 1272 const char PartnerDNFMT[] = 1273 "CN=%s, " 1274 "OU=Class B, " 1275 "%sOU=Solaris Cryptographic Framework, " 1276 "OU=Partner Object Signing, " 1277 "O=Sun Microsystems Inc"; 1278 const char SunCDNFMT[] = 1279 "CN=%s, " 1280 "OU=Class B, " 1281 "%sOU=Solaris Cryptographic Framework, " 1282 "OU=Corporate Object Signing, " 1283 "O=Sun Microsystems Inc"; 1284 const char SunSDNFMT[] = 1285 "CN=%s, " 1286 "OU=Class B, " 1287 "%sOU=Solaris Signed Execution, " 1288 "OU=Corporate Object Signing, " 1289 "O=Sun Microsystems Inc"; 1290 const char *dnfmt = NULL; 1291 char cn[CN_MAX_LENGTH + 1]; 1292 char *dn = NULL; 1293 size_t dn_len; 1294 char *restriction = ""; 1295 KMF_RETURN kmfret; 1296 cryptodebug("do_cert_request"); 1297 1298 /* 1299 * Get the DN prefix from the user 1300 */ 1301 switch (cmd_info.internal_req) { 1302 case 'c': 1303 dnfmt = SunCDNFMT; 1304 (void) fprintf(stdout, gettext( 1305 "Enter Sun Microsystems, Inc. Release name.\n" 1306 "This will be the prefix of the Certificate DN: ")); 1307 break; 1308 case 's': 1309 dnfmt = SunSDNFMT; 1310 (void) fprintf(stdout, gettext( 1311 "Enter Sun Microsystems, Inc. Release name.\n" 1312 "This will be the prefix of the Certificate DN: ")); 1313 break; 1314 default: 1315 dnfmt = PartnerDNFMT; 1316 (void) fprintf(stdout, gettext( 1317 "Enter Company Name / Stock Symbol" 1318 " or some other globally unique identifier.\n" 1319 "This will be the prefix of the Certificate DN: ")); 1320 break; 1321 } 1322 1323 (void) fgets(cn, sizeof (cn), stdin); 1324 if ((cn == NULL) || (cn[0] == '\n')) { 1325 es_error(gettext("you must specify a Certificate DN prefix")); 1326 return (EXIT_INVALID_ARG); 1327 } 1328 1329 if (cn[strlen(cn) - 1] == '\n') { 1330 cn[strlen(cn) - 1] = '\0'; /* chop trailing \n */ 1331 } else { 1332 es_error(gettext("You must specify a Certificate DN prefix " 1333 "of no more than %d characters"), CN_MAX_LENGTH); 1334 return (EXIT_INVALID_ARG); 1335 } 1336 1337 /* 1338 * determine if there is an export restriction 1339 */ 1340 switch (cmd_info.internal_req) { 1341 case 's': 1342 restriction = ""; 1343 break; 1344 default: 1345 restriction = is_restricted() ? USAGELIMITED ", " : ""; 1346 break; 1347 } 1348 1349 /* Update DN string */ 1350 dn_len = strlen(cn) + strlen(dnfmt) + strlen(restriction); 1351 dn = malloc(dn_len + 1); 1352 (void) snprintf(dn, dn_len, dnfmt, cn, restriction); 1353 1354 cryptodebug("Generating Certificate request for DN: %s", dn); 1355 kmfret = create_csr(dn); 1356 free(dn); 1357 if (kmfret == KMF_OK) 1358 return (EXIT_OKAY); 1359 else 1360 return (EXIT_CSR_FAILED); 1361 } 1362 1363 static void 1364 str_print(char *s) 1365 { 1366 if (s == NULL) 1367 return; 1368 (void) fprintf(stdout, "%s\n", s); 1369 } 1370 1371 /*ARGSUSED*/ 1372 static ret_t 1373 do_list(char *object) 1374 { 1375 ret_t retval; 1376 1377 if (cmd_info.elfcnt > 0) { 1378 ELFsign_status_t elfstat; 1379 struct filesignatures *fssp = NULL; 1380 size_t fs_len; 1381 struct ELFsign_sig_info *esip; 1382 1383 if ((retval = getelfobj(cmd_info.elfobj[0])) != EXIT_OKAY) 1384 return (retval); 1385 elfstat = elfsign_signatures(cmd_info.ess, 1386 &fssp, &fs_len, ES_GET); 1387 if (elfstat == ELFSIGN_SUCCESS) { 1388 retval = EXIT_OKAY; 1389 if (elfsign_sig_info(fssp, &esip)) { 1390 switch (cmd_info.field) { 1391 case FLD_FORMAT: 1392 str_print(esip->esi_format); 1393 break; 1394 case FLD_SIGNER: 1395 str_print(esip->esi_signer); 1396 break; 1397 case FLD_TIME: 1398 if (esip->esi_time == 0) 1399 retval = EXIT_INVALID_ARG; 1400 else 1401 str_print(time_str( 1402 esip->esi_time)); 1403 break; 1404 default: 1405 retval = EXIT_INVALID_ARG; 1406 } 1407 elfsign_sig_info_free(esip); 1408 } 1409 free(fssp); 1410 } else 1411 retval = EXIT_VERIFY_FAILED_UNSIGNED; 1412 elfsign_end(cmd_info.ess); 1413 } else { 1414 ELFCert_t cert; 1415 /* 1416 * Initialize the ESS record here even though we are not 1417 * actually opening any ELF files. 1418 */ 1419 if (elfsign_begin(NULL, ES_GET, &(cmd_info.ess)) != 1420 ELFSIGN_SUCCESS) 1421 return (EXIT_MEMORY_ERROR); 1422 1423 if (elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, 1424 &cert, cmd_info.es_action)) { 1425 retval = EXIT_OKAY; 1426 switch (cmd_info.field) { 1427 case FLD_SUBJECT: 1428 str_print(elfcertlib_getdn(cert)); 1429 break; 1430 case FLD_ISSUER: 1431 str_print(elfcertlib_getissuer(cert)); 1432 break; 1433 default: 1434 retval = EXIT_INVALID_ARG; 1435 } 1436 elfcertlib_releasecert(cmd_info.ess, cert); 1437 } else 1438 retval = EXIT_BAD_CERT; 1439 elfsign_end(cmd_info.ess); 1440 } 1441 1442 return (retval); 1443 } 1444 1445 static void 1446 es_error(const char *fmt, ...) 1447 { 1448 char msgbuf[BUFSIZ]; 1449 va_list args; 1450 1451 va_start(args, fmt); 1452 (void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args); 1453 va_end(args); 1454 (void) fflush(stdout); 1455 cryptoerror(LOG_STDERR, "%s", msgbuf); 1456 (void) fflush(stderr); 1457 } 1458 1459 static char * 1460 time_str(time_t t) 1461 { 1462 static char buf[80]; 1463 char *bufp; 1464 1465 bufp = buf; 1466 if (strftime(buf, sizeof (buf), NULL, localtime(&t)) == 0) 1467 bufp = ctime(&t); 1468 return (bufp); 1469 } 1470 1471 static void 1472 sig_info_print(struct ELFsign_sig_info *esip) 1473 { 1474 if (esip == NULL) 1475 return; 1476 (void) fprintf(stdout, gettext("format: %s.\n"), esip->esi_format); 1477 (void) fprintf(stdout, gettext("signer: %s.\n"), esip->esi_signer); 1478 if (esip->esi_time == 0) 1479 return; 1480 (void) fprintf(stdout, gettext("signed on: %s.\n"), 1481 time_str(esip->esi_time)); 1482 } 1483