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