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 2007 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; 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; 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: %d"), 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 elfsign_end(cmd_info.ess); 525 es_error(gettext("Unable to access token: %s"), 526 cmd_info.token_label); 527 ret = EXIT_SIGN_FAILED; 528 goto cleanup; 529 } 530 531 if ((ret = setcertpath()) != EXIT_OKAY) 532 goto cleanup; 533 534 if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert, 535 cmd_info.es_action)) { 536 es_error(gettext("Unable to load certificate: %s"), 537 cmd_info.cert); 538 ret = EXIT_BAD_CERT; 539 goto cleanup; 540 } 541 542 if (cmd_info.privpath != NULL) { 543 if (!elfcertlib_loadprivatekey(cmd_info.ess, cert, 544 cmd_info.privpath)) { 545 es_error(gettext("Unable to load private key: %s"), 546 cmd_info.privpath); 547 ret = EXIT_BAD_PRIVATEKEY; 548 goto cleanup; 549 } 550 } else { 551 char *pin = getpin(); 552 if (pin == NULL) { 553 es_error(gettext("Unable to get PIN")); 554 ret = EXIT_BAD_PRIVATEKEY; 555 goto cleanup; 556 } 557 if (!elfcertlib_loadtokenkey(cmd_info.ess, cert, 558 cmd_info.token_label, pin)) { 559 es_error(gettext("Unable to access private key " 560 "in token %s"), cmd_info.token_label); 561 ret = EXIT_BAD_PRIVATEKEY; 562 goto cleanup; 563 } 564 } 565 566 /* 567 * Get the DN from the certificate. 568 */ 569 if ((dn = elfcertlib_getdn(cert)) == NULL) { 570 es_error(gettext("Unable to find DN in certificate %s"), 571 cmd_info.cert); 572 ret = EXIT_SIGN_FAILED; 573 goto cleanup; 574 } 575 dn_len = strlen(dn); 576 cryptodebug("DN = %s", dn); 577 578 elfstat = elfsign_signatures(cmd_info.ess, &fssp, &fs_len, ES_GET); 579 if (elfstat != ELFSIGN_SUCCESS) { 580 if (elfstat != ELFSIGN_NOTSIGNED) { 581 es_error(gettext("Unable to retrieve existing " 582 "signature block in %s"), object); 583 ret = EXIT_SIGN_FAILED; 584 goto cleanup; 585 } 586 fssp = NULL; 587 /* 588 * force creation and naming of signature section 589 * so the hash doesn't change 590 */ 591 if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len, 592 cmd_info.es_action) != ELFSIGN_SUCCESS) { 593 es_error(gettext("Unable to insert " 594 "signature block into %s"), object); 595 ret = EXIT_SIGN_FAILED; 596 goto cleanup; 597 } 598 } 599 600 bzero(hash, sizeof (hash)); 601 if (elfsign_hash(cmd_info.ess, hash, &hash_len) != ELFSIGN_SUCCESS) { 602 es_error(gettext("Unable to calculate hash of ELF object %s"), 603 object); 604 ret = EXIT_SIGN_FAILED; 605 goto cleanup; 606 } 607 608 bzero(sig, sizeof (sig)); 609 if (!elfcertlib_sign(cmd_info.ess, cert, 610 hash, hash_len, sig, &sig_len)) { 611 es_error(gettext("Unable to sign %s using key from %s"), 612 object, cmd_info.privpath ? 613 cmd_info.privpath : cmd_info.token_label); 614 ret = EXIT_SIGN_FAILED; 615 goto cleanup; 616 } 617 618 { /* DEBUG START */ 619 const int sigstr_len = sizeof (char) * sig_len * 2 + 1; 620 char *sigstr = malloc(sigstr_len); 621 622 tohexstr(sig, sig_len, sigstr, sigstr_len); 623 cryptodebug("sig value is: %s", sigstr); 624 free(sigstr); 625 } /* DEBUG END */ 626 627 fssp = elfsign_insert_dso(cmd_info.ess, fssp, 628 dn, dn_len, sig, sig_len, NULL, 0); 629 if (fssp == NULL) { 630 es_error(gettext("Unable to prepare signature for %s"), 631 object); 632 ret = EXIT_SIGN_FAILED; 633 goto cleanup; 634 } 635 if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len, 636 cmd_info.es_action) != ELFSIGN_SUCCESS) { 637 es_error(gettext("Unable to update %s: with signature"), 638 object); 639 ret = EXIT_SIGN_FAILED; 640 goto cleanup; 641 } 642 if (cmd_info.verbose || (cmd_info.elfcnt + cmd_info.extracnt) > 1) { 643 (void) fprintf(stdout, 644 gettext("elfsign: %s signed successfully.\n"), 645 object); 646 } 647 if (cmd_info.verbose) { 648 struct ELFsign_sig_info *esip; 649 650 if (elfsign_sig_info(fssp, &esip)) { 651 sig_info_print(esip); 652 elfsign_sig_info_free(esip); 653 } 654 } 655 656 ret = EXIT_OKAY; 657 658 cleanup: 659 free(fssp); 660 bzero(sig, sig_len); 661 bzero(hash, hash_len); 662 663 if (cert != NULL) 664 elfcertlib_releasecert(cmd_info.ess, cert); 665 if (cmd_info.ess != NULL) 666 elfsign_end(cmd_info.ess); 667 668 return (ret); 669 } 670 671 #define ESA_ERROR(str, esa_file) { \ 672 int realerrno = errno; \ 673 es_error(gettext(str), esa_file, strerror(realerrno)); \ 674 goto clean_esa; \ 675 } 676 677 /* 678 * Generate the elfsign activation file (.esa) for this request. 679 * The .esa file should contain the signature of main binary 680 * signed with an unlimited certificate, the DN and its own signature. 681 * 682 * The format is as follows: 683 * ----------------------------- 684 * A | main signature length | 685 * ----------------------------- 686 * B | main signature (copy of | 687 * | signature from original | 688 * | limited-use binary | 689 * ----------------------------- 690 * C | signing DN length | 691 * ----------------------------- 692 * D | signing DN | 693 * ----------------------------- 694 * E | esa signature length | 695 * ----------------------------- 696 * F | esa signature = | 697 * | RSA(HASH(A||B) | 698 * ----------------------------- 699 * (lengths are in the same endianness as the original object) 700 * 701 * cmd_info.ess set for the main binary is correct here, since this 702 * is the only elf object we are actually dealing with during the .esa 703 * generation. 704 */ 705 static ret_t 706 do_gen_esa(char *object) 707 { 708 ret_t ret; 709 710 /* variables used for signing and writing to .esa file */ 711 char *elfobj_esa; 712 size_t elfobj_esa_len; 713 int esa_fd; 714 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH; 715 uchar_t *esa_buf = NULL; 716 size_t esa_buf_len = 0; 717 uchar_t hash[SIG_MAX_LENGTH], *hash_ptr = hash; 718 size_t hash_len = SIG_MAX_LENGTH; 719 uchar_t esa_sig[SIG_MAX_LENGTH]; 720 size_t esa_sig_len = SIG_MAX_LENGTH; 721 struct filesignatures *fssp = NULL; 722 size_t fslen; 723 ELFCert_t cert = NULL; 724 char *dn; 725 size_t dn_len; 726 uchar_t tmp_buf[sizeof (uint32_t)]; 727 int realerrno = 0; 728 729 /* 730 * variables used for finding information on signer of main 731 * elfobject. 732 */ 733 uchar_t orig_signature[SIG_MAX_LENGTH]; 734 size_t orig_sig_len = sizeof (orig_signature); 735 736 cryptodebug("do_gen_esa"); 737 if ((ret = getelfobj(object)) != EXIT_OKAY) 738 return (ret); 739 ret = EXIT_SIGN_FAILED; 740 741 /* 742 * Find the certificate we need to sign the activation file with. 743 */ 744 if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert, 745 cmd_info.es_action)) { 746 es_error(gettext("Unable to load certificate: %s"), 747 cmd_info.cert); 748 ret = EXIT_BAD_CERT; 749 goto clean_esa; 750 } 751 752 if (cmd_info.privpath != NULL) { 753 if (!elfcertlib_loadprivatekey(cmd_info.ess, cert, 754 cmd_info.privpath)) { 755 es_error(gettext("Unable to load private key: %s"), 756 cmd_info.privpath); 757 ret = EXIT_BAD_PRIVATEKEY; 758 goto clean_esa; 759 } 760 } else { 761 char *pin = getpin(); 762 763 if (pin == NULL) { 764 cryptoerror(LOG_STDERR, gettext("Unable to get PIN")); 765 ret = EXIT_BAD_PRIVATEKEY; 766 goto clean_esa; 767 } 768 if (!elfcertlib_loadtokenkey(cmd_info.ess, cert, 769 cmd_info.token_label, pin)) { 770 es_error(gettext("Unable to access private key " 771 "in token %s"), cmd_info.token_label); 772 ret = EXIT_BAD_PRIVATEKEY; 773 goto clean_esa; 774 } 775 } 776 777 /* 778 * Get the DN from the certificate. 779 */ 780 if ((dn = elfcertlib_getdn(cert)) == NULL) { 781 es_error(gettext("Unable to find DN in certifiate %s"), 782 cmd_info.cert); 783 goto clean_esa; 784 } 785 dn_len = strlen(dn); 786 cryptodebug("DN = %s", dn); 787 788 /* 789 * Make sure they are not trying to sign .esa file with a 790 * limited certificate. 791 */ 792 if (strstr(dn, USAGELIMITED) != NULL) { 793 es_error(gettext("Activation file must be signed with a " 794 "certficate without %s."), USAGELIMITED); 795 goto clean_esa; 796 } 797 798 /* 799 * Find information in the associated elfobject that will 800 * be needed to generate the activation file. 801 */ 802 if (elfsign_signatures(cmd_info.ess, &fssp, &fslen, ES_GET) != 803 ELFSIGN_SUCCESS) { 804 es_error(gettext("%s must be signed first, before an " 805 "associated activation file can be created."), 806 object); 807 goto clean_esa; 808 } 809 if (elfsign_extract_sig(cmd_info.ess, fssp, 810 orig_signature, &orig_sig_len) == FILESIG_UNKNOWN) { 811 es_error(gettext("elfsign can not create " 812 "an associated activation file for the " 813 "signature format of %s."), 814 object); 815 goto clean_esa; 816 } 817 { /* DEBUG START */ 818 const int sigstr_len = orig_sig_len * 2 + 1; 819 char *sigstr = malloc(sigstr_len); 820 821 tohexstr(orig_signature, orig_sig_len, sigstr, sigstr_len); 822 cryptodebug("signature value is: %s", sigstr); 823 cryptodebug("sig size value is: %d", orig_sig_len); 824 free(sigstr); 825 } /* DEBUG END */ 826 827 esa_buf_len = sizeof (uint32_t) + orig_sig_len; 828 esa_buf = malloc(esa_buf_len); 829 if (esa_buf == NULL) { 830 es_error(gettext("Unable to allocate memory for .esa buffer")); 831 goto clean_esa; 832 } 833 834 /* 835 * Write eventual contents of .esa file to a temporary 836 * buffer, so we can sign it before writing out to 837 * the file. 838 */ 839 elfsign_buffer_len(cmd_info.ess, &orig_sig_len, esa_buf, ES_UPDATE); 840 (void) memcpy(esa_buf + sizeof (uint32_t), orig_signature, 841 orig_sig_len); 842 843 if (elfsign_hash_esa(cmd_info.ess, esa_buf, esa_buf_len, 844 &hash_ptr, &hash_len) != ELFSIGN_SUCCESS) { 845 es_error(gettext("Unable to calculate activation hash")); 846 goto clean_esa; 847 } 848 849 /* 850 * sign the buffer for the .esa file 851 */ 852 if (!elfcertlib_sign(cmd_info.ess, cert, 853 hash_ptr, hash_len, esa_sig, &esa_sig_len)) { 854 es_error(gettext("Unable to sign .esa data using key from %s"), 855 cmd_info.privpath ? 856 cmd_info.privpath : cmd_info.token_label); 857 goto clean_esa; 858 } 859 860 { /* DEBUG START */ 861 const int sigstr_len = esa_sig_len * 2 + 1; 862 char *sigstr = malloc(sigstr_len); 863 864 tohexstr(esa_sig, esa_sig_len, sigstr, sigstr_len); 865 cryptodebug("esa signature value is: %s", sigstr); 866 cryptodebug("esa size value is: %d", esa_sig_len); 867 free(sigstr); 868 } /* DEBUG END */ 869 870 /* 871 * Create the empty activation file once we know 872 * we are working with the good data. 873 */ 874 elfobj_esa_len = strlen(object) + ESA_LEN + 1; 875 elfobj_esa = malloc(elfobj_esa_len); 876 877 if (elfobj_esa == NULL) { 878 es_error(gettext("Unable to allocate buffer for esa filename")); 879 goto clean_esa; 880 } 881 882 (void) strlcpy(elfobj_esa, object, elfobj_esa_len); 883 (void) strlcat(elfobj_esa, ESA, elfobj_esa_len); 884 885 cryptodebug("Creating .esa file: %s", elfobj_esa); 886 887 if ((esa_fd = open(elfobj_esa, O_WRONLY|O_CREAT|O_EXCL, mode)) == -1) { 888 ESA_ERROR("Unable to create activation file: %s. %s.", 889 elfobj_esa); 890 } 891 892 if (write(esa_fd, esa_buf, esa_buf_len) != esa_buf_len) { 893 ESA_ERROR("Unable to write contents to %s. %s.", 894 elfobj_esa); 895 } 896 897 { /* DEBUG START */ 898 const int sigstr_len = dn_len * 2 + 1; 899 char *sigstr = malloc(sigstr_len); 900 901 tohexstr((uchar_t *)dn, dn_len, sigstr, sigstr_len); 902 cryptodebug("dn value is: %s", sigstr); 903 cryptodebug("dn size value is: %d", dn_len); 904 free(sigstr); 905 } /* DEBUG END */ 906 907 elfsign_buffer_len(cmd_info.ess, &dn_len, tmp_buf, ES_UPDATE); 908 if (write(esa_fd, tmp_buf, sizeof (tmp_buf)) != sizeof (tmp_buf)) { 909 ESA_ERROR("Unable to write dn_len to %s. %s.", elfobj_esa); 910 } 911 912 if (write(esa_fd, dn, dn_len) != dn_len) { 913 ESA_ERROR("Unable to write dn to %s. %s.", elfobj_esa); 914 } 915 916 elfsign_buffer_len(cmd_info.ess, &esa_sig_len, tmp_buf, ES_UPDATE); 917 if (write(esa_fd, tmp_buf, sizeof (tmp_buf)) != sizeof (tmp_buf)) { 918 ESA_ERROR("Unable to write .esa signature len to %s. %s.", 919 elfobj_esa); 920 } 921 922 if (write(esa_fd, esa_sig, esa_sig_len) != esa_sig_len) { 923 realerrno = errno; 924 es_error(gettext("Unable to write .esa signature. %s."), 925 strerror(realerrno)); 926 goto clean_esa; 927 } 928 929 ret = EXIT_OKAY; 930 931 clean_esa: 932 free(fssp); 933 if (esa_fd != -1) 934 (void) close(esa_fd); 935 936 if (esa_buf != NULL) 937 free(esa_buf); 938 939 bzero(esa_sig, esa_sig_len); 940 941 if (cert != NULL) 942 elfcertlib_releasecert(cmd_info.ess, cert); 943 if (cmd_info.ess != NULL) 944 elfsign_end(cmd_info.ess); 945 946 return (ret); 947 } 948 949 /* 950 * Verify the signature of the object 951 * This subcommand is intended to be used by developers during their build 952 * processes. Therefore we can not assume that the certificate is in 953 * /etc/crypto/certs so we must use the path we got from the commandline. 954 */ 955 static ret_t 956 do_verify(char *object) 957 { 958 ELFsign_status_t res; 959 struct ELFsign_sig_info *esip; 960 ret_t retval; 961 962 cryptodebug("do_verify"); 963 if ((retval = getelfobj(object)) != EXIT_OKAY) 964 return (retval); 965 966 if ((retval = setcertpath()) != EXIT_OKAY) { 967 elfsign_end(cmd_info.ess); 968 return (retval); 969 } 970 971 res = elfsign_verify_signature(cmd_info.ess, &esip); 972 switch (res) { 973 case ELFSIGN_SUCCESS: 974 (void) fprintf(stdout, 975 gettext("elfsign: verification of %s passed.\n"), 976 object); 977 if (cmd_info.verbose) 978 sig_info_print(esip); 979 retval = EXIT_OKAY; 980 break; 981 case ELFSIGN_RESTRICTED: 982 (void) fprintf(stdout, 983 gettext("elfsign: verification of %s passed, " 984 "but restricted.\n"), object); 985 if (cmd_info.verbose) 986 sig_info_print(esip); 987 retval = EXIT_OKAY; 988 break; 989 case ELFSIGN_FAILED: 990 case ELFSIGN_INVALID_CERTPATH: 991 es_error(gettext("verification of %s failed."), 992 object); 993 if (cmd_info.verbose) 994 sig_info_print(esip); 995 retval = EXIT_VERIFY_FAILED; 996 break; 997 case ELFSIGN_NOTSIGNED: 998 es_error(gettext("no signature found in %s."), 999 object); 1000 retval = EXIT_VERIFY_FAILED_UNSIGNED; 1001 break; 1002 default: 1003 es_error(gettext("unexpected failure attempting verification " 1004 "of %s."), object); 1005 retval = EXIT_VERIFY_FAILED_UNSIGNED; 1006 break; 1007 } 1008 1009 if (esip != NULL) 1010 elfsign_sig_info_free(esip); 1011 if (cmd_info.ess != NULL) 1012 elfsign_end(cmd_info.ess); 1013 return (retval); 1014 } 1015 1016 #define SET_VALUE(f, s) \ 1017 kmfrv = f; \ 1018 if (kmfrv != KMF_OK) { \ 1019 char *e = NULL; \ 1020 (void) KMF_GetKMFErrorString(kmfrv, &e); \ 1021 cryptoerror(LOG_STDERR, \ 1022 gettext("Failed to %s: %s\n"), \ 1023 s, (e ? e : "unknown error")); \ 1024 if (e) free(e); \ 1025 goto cleanup; \ 1026 } 1027 1028 static KMF_RETURN 1029 create_csr(char *dn) 1030 { 1031 KMF_RETURN kmfrv = KMF_OK; 1032 KMF_HANDLE_T kmfhandle = NULL; 1033 KMF_CREATEKEYPAIR_PARAMS kp_params; 1034 KMF_KEY_HANDLE pubk, prik; 1035 KMF_X509_NAME csrSubject; 1036 KMF_CSR_DATA csr; 1037 KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA; 1038 KMF_DATA signedCsr = { NULL, 0 }; 1039 KMF_CONFIG_PARAMS config; 1040 char *err; 1041 1042 if ((kmfrv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 1043 (void) KMF_GetKMFErrorString(kmfrv, &err); 1044 cryptoerror(LOG_STDERR, 1045 gettext("Error initializing KMF: %s\n"), 1046 (err ? err : "unknown error")); 1047 if (err) 1048 free(err); 1049 return (kmfrv); 1050 } 1051 (void) memset(&csr, 0, sizeof (csr)); 1052 (void) memset(&csrSubject, 0, sizeof (csrSubject)); 1053 (void) memset(&kp_params, 0, sizeof (kp_params)); 1054 1055 if (cmd_info.privpath != NULL) { 1056 kp_params.kstype = KMF_KEYSTORE_OPENSSL; 1057 kp_params.sslparms.keyfile = cmd_info.privpath; 1058 kp_params.sslparms.format = KMF_FORMAT_ASN1; 1059 } else if (cmd_info.token_label != NULL) { 1060 1061 /* Get a PIN to store the private key in the token */ 1062 char *pin = getpin(); 1063 1064 if (pin == NULL) { 1065 (void) KMF_Finalize(kmfhandle); 1066 return (KMF_ERR_AUTH_FAILED); 1067 } 1068 1069 kp_params.kstype = KMF_KEYSTORE_PK11TOKEN; 1070 kp_params.cred.cred = pin; 1071 kp_params.cred.credlen = strlen(pin); 1072 1073 (void) memset(&config, 0, sizeof (config)); 1074 config.kstype = KMF_KEYSTORE_PK11TOKEN; 1075 config.pkcs11config.label = cmd_info.token_label; 1076 config.pkcs11config.readonly = FALSE; 1077 kmfrv = KMF_ConfigureKeystore(kmfhandle, &config); 1078 if (kmfrv != KMF_OK) { 1079 goto cleanup; 1080 } 1081 } 1082 1083 /* Create the RSA keypair */ 1084 kp_params.keytype = KMF_RSA; 1085 kp_params.keylength = ES_DEFAULT_KEYSIZE; 1086 1087 kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk); 1088 if (kmfrv != KMF_OK) { 1089 (void) KMF_GetKMFErrorString(kmfrv, &err); 1090 if (err != NULL) { 1091 cryptoerror(LOG_STDERR, 1092 gettext("Create RSA keypair failed: %s"), err); 1093 free(err); 1094 } 1095 goto cleanup; 1096 } 1097 1098 kmfrv = KMF_DNParser(dn, &csrSubject); 1099 if (kmfrv != KMF_OK) { 1100 (void) KMF_GetKMFErrorString(kmfrv, &err); 1101 if (err != NULL) { 1102 cryptoerror(LOG_STDERR, 1103 gettext("Error parsing subject name: %s\n"), err); 1104 free(err); 1105 } 1106 goto cleanup; 1107 } 1108 1109 SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "keypair"); 1110 1111 SET_VALUE(KMF_SetCSRVersion(&csr, 2), "version number"); 1112 1113 SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), "subject name"); 1114 1115 SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg), 1116 "SignatureAlgorithm"); 1117 1118 if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) == 1119 KMF_OK) { 1120 kmfrv = KMF_CreateCSRFile(&signedCsr, KMF_FORMAT_PEM, 1121 cmd_info.cert); 1122 } 1123 1124 cleanup: 1125 (void) KMF_FreeKMFKey(kmfhandle, &prik); 1126 (void) KMF_FreeData(&signedCsr); 1127 (void) KMF_FreeSignedCSR(&csr); 1128 (void) KMF_Finalize(kmfhandle); 1129 1130 return (kmfrv); 1131 } 1132 1133 static boolean_t 1134 is_restricted(void) 1135 { 1136 char nr[80]; /* Non-retail provider? big buffer for l10n */ 1137 char *yeschar = nl_langinfo(YESSTR); 1138 char *nochar = nl_langinfo(NOSTR); 1139 1140 /* 1141 * Find out if user will need an activation file. 1142 * These questions cover cases #1 and #2 from the Jumbo Export 1143 * Control case. The logic of these questions should not be modified 1144 * without consulting the jumbo case, unless there is a new 1145 * export case or a change in export/import regulations for Sun 1146 * and Sun customers. 1147 * Case #3 should be covered in the developer documentation. 1148 */ 1149 /* BEGIN CSTYLED */ 1150 (void) fprintf(stdout, gettext("\n" 1151 "The government of the United States of America restricts the export of \n" 1152 "\"open cryptographic interfaces\", also known as \"crypto-with-a-hole\".\n" 1153 "Due to this restriction, all providers for the Solaris cryptographic\n" 1154 "framework must be signed, regardless of the country of origin.\n\n")); 1155 1156 (void) fprintf(stdout, gettext( 1157 "The terms \"retail\" and \"non-retail\" refer to export classifications \n" 1158 "for products manufactured in the USA. These terms define the portion of the\n" 1159 "world where the product may be shipped. Roughly speaking, \"retail\" is \n" 1160 "worldwide (minus certain excluded nations) and \"non-retail\" is domestic \n" 1161 "only (plus some highly favored nations). If your provider is subject to\n" 1162 "USA export control, then you must obtain an export approval (classification)\n" 1163 "from the government of the USA before exporting your provider. It is\n" 1164 "critical that you specify the obtained (or expected, when used during \n" 1165 "development) classification to the following questions so that your provider\n" 1166 "will be appropriately signed.\n\n")); 1167 1168 for (;;) { 1169 (void) fprintf(stdout, gettext( 1170 "Do you have retail export approval for use without restrictions based \n" 1171 "on the caller (for example, IPsec)? [Yes/No] ")); 1172 /* END CSTYLED */ 1173 1174 (void) fflush(stdout); 1175 1176 (void) fgets(nr, sizeof (nr), stdin); 1177 if (nr == NULL) 1178 goto demand_answer; 1179 1180 nr[strlen(nr) - 1] = '\0'; 1181 1182 if (strncasecmp(nochar, nr, 1) == 0) { 1183 /* BEGIN CSTYLED */ 1184 (void) fprintf(stdout, gettext("\n" 1185 "If you have non-retail export approval for unrestricted use of your provider\n" 1186 "by callers, are you also planning to receive retail approval by restricting \n" 1187 "which export sensitive callers (for example, IPsec) may use your \n" 1188 "provider? [Yes/No] ")); 1189 /* END CSTYLED */ 1190 1191 (void) fflush(stdout); 1192 1193 (void) fgets(nr, sizeof (nr), stdin); 1194 1195 /* 1196 * flush standard input so any remaining text 1197 * does not affect next read. 1198 */ 1199 (void) fflush(stdin); 1200 1201 if (nr == NULL) 1202 goto demand_answer; 1203 1204 nr[strlen(nr) - 1] = '\0'; 1205 1206 if (strncasecmp(nochar, nr, 1) == 0) { 1207 return (B_FALSE); 1208 } else if (strncasecmp(yeschar, nr, 1) == 0) { 1209 return (B_TRUE); 1210 } else 1211 goto demand_answer; 1212 1213 } else if (strncasecmp(yeschar, nr, 1) == 0) { 1214 return (B_FALSE); 1215 } 1216 1217 demand_answer: 1218 (void) fprintf(stdout, 1219 gettext("You must specify an answer.\n\n")); 1220 } 1221 } 1222 1223 #define CN_MAX_LENGTH 64 /* Verisign implementation limit */ 1224 /* 1225 * Generate a certificate request into the file named cmd_info.cert 1226 */ 1227 /*ARGSUSED*/ 1228 static ret_t 1229 do_cert_request(char *object) 1230 { 1231 const char PartnerDNFMT[] = 1232 "CN=%s, " 1233 "OU=Class B, " 1234 "%sOU=Solaris Cryptographic Framework, " 1235 "OU=Partner Object Signing, " 1236 "O=Sun Microsystems Inc"; 1237 const char SunCDNFMT[] = 1238 "CN=%s, " 1239 "OU=Class B, " 1240 "%sOU=Solaris Cryptographic Framework, " 1241 "OU=Corporate Object Signing, " 1242 "O=Sun Microsystems Inc"; 1243 const char SunSDNFMT[] = 1244 "CN=%s, " 1245 "OU=Class B, " 1246 "%sOU=Solaris Signed Execution, " 1247 "OU=Corporate Object Signing, " 1248 "O=Sun Microsystems Inc"; 1249 const char *dnfmt = NULL; 1250 char cn[CN_MAX_LENGTH + 1]; 1251 char *dn = NULL; 1252 size_t dn_len; 1253 char *restriction = ""; 1254 KMF_RETURN kmfret; 1255 cryptodebug("do_cert_request"); 1256 1257 /* 1258 * Get the DN prefix from the user 1259 */ 1260 switch (cmd_info.internal_req) { 1261 case 'c': 1262 dnfmt = SunCDNFMT; 1263 (void) fprintf(stdout, gettext( 1264 "Enter Sun Microsystems, Inc. Release name.\n" 1265 "This will be the prefix of the Certificate DN: ")); 1266 break; 1267 case 's': 1268 dnfmt = SunSDNFMT; 1269 (void) fprintf(stdout, gettext( 1270 "Enter Sun Microsystems, Inc. Release name.\n" 1271 "This will be the prefix of the Certificate DN: ")); 1272 break; 1273 default: 1274 dnfmt = PartnerDNFMT; 1275 (void) fprintf(stdout, gettext( 1276 "Enter Company Name / Stock Symbol" 1277 " or some other globally unique identifier.\n" 1278 "This will be the prefix of the Certificate DN: ")); 1279 break; 1280 } 1281 1282 (void) fgets(cn, sizeof (cn), stdin); 1283 if ((cn == NULL) || (cn[0] == '\n')) { 1284 es_error(gettext("you must specify a Certificate DN prefix")); 1285 return (EXIT_INVALID_ARG); 1286 } 1287 1288 if (cn[strlen(cn) - 1] == '\n') { 1289 cn[strlen(cn) - 1] = '\0'; /* chop trailing \n */ 1290 } else { 1291 es_error(gettext("You must specify a Certificate DN prefix " 1292 "of no more than %d characters"), CN_MAX_LENGTH); 1293 return (EXIT_INVALID_ARG); 1294 } 1295 1296 /* 1297 * determine if there is an export restriction 1298 */ 1299 switch (cmd_info.internal_req) { 1300 case 's': 1301 restriction = ""; 1302 break; 1303 default: 1304 restriction = is_restricted() ? USAGELIMITED ", " : ""; 1305 break; 1306 } 1307 1308 /* Update DN string */ 1309 dn_len = strlen(cn) + strlen(dnfmt) + strlen(restriction); 1310 dn = malloc(dn_len + 1); 1311 (void) snprintf(dn, dn_len, dnfmt, cn, restriction); 1312 1313 cryptodebug("Generating Certificate request for DN: %s", dn); 1314 kmfret = create_csr(dn); 1315 free(dn); 1316 if (kmfret == KMF_OK) 1317 return (EXIT_OKAY); 1318 else 1319 return (EXIT_CSR_FAILED); 1320 } 1321 1322 static void 1323 str_print(char *s) 1324 { 1325 if (s == NULL) 1326 return; 1327 (void) fprintf(stdout, "%s\n", s); 1328 } 1329 1330 /*ARGSUSED*/ 1331 static ret_t 1332 do_list(char *object) 1333 { 1334 ret_t retval; 1335 1336 if (cmd_info.elfcnt > 0) { 1337 ELFsign_status_t elfstat; 1338 struct filesignatures *fssp = NULL; 1339 size_t fs_len; 1340 struct ELFsign_sig_info *esip; 1341 1342 if ((retval = getelfobj(cmd_info.elfobj[0])) != EXIT_OKAY) 1343 return (retval); 1344 elfstat = elfsign_signatures(cmd_info.ess, 1345 &fssp, &fs_len, ES_GET); 1346 if (elfstat == ELFSIGN_SUCCESS) { 1347 retval = EXIT_OKAY; 1348 if (elfsign_sig_info(fssp, &esip)) { 1349 switch (cmd_info.field) { 1350 case FLD_FORMAT: 1351 str_print(esip->esi_format); 1352 break; 1353 case FLD_SIGNER: 1354 str_print(esip->esi_signer); 1355 break; 1356 case FLD_TIME: 1357 if (esip->esi_time == 0) 1358 retval = EXIT_INVALID_ARG; 1359 else 1360 str_print(time_str( 1361 esip->esi_time)); 1362 break; 1363 default: 1364 retval = EXIT_INVALID_ARG; 1365 } 1366 elfsign_sig_info_free(esip); 1367 } 1368 free(fssp); 1369 } else 1370 retval = EXIT_VERIFY_FAILED_UNSIGNED; 1371 elfsign_end(cmd_info.ess); 1372 } else { 1373 ELFCert_t cert; 1374 /* 1375 * Initialize the ESS record here even though we are not 1376 * actually opening any ELF files. 1377 */ 1378 if (elfsign_begin(NULL, ES_GET, &(cmd_info.ess)) != 1379 ELFSIGN_SUCCESS) 1380 return (EXIT_MEMORY_ERROR); 1381 1382 if (elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, 1383 &cert, cmd_info.es_action)) { 1384 retval = EXIT_OKAY; 1385 switch (cmd_info.field) { 1386 case FLD_SUBJECT: 1387 str_print(elfcertlib_getdn(cert)); 1388 break; 1389 case FLD_ISSUER: 1390 str_print(elfcertlib_getissuer(cert)); 1391 break; 1392 default: 1393 retval = EXIT_INVALID_ARG; 1394 } 1395 elfcertlib_releasecert(cmd_info.ess, cert); 1396 } else 1397 retval = EXIT_BAD_CERT; 1398 elfsign_end(cmd_info.ess); 1399 } 1400 1401 return (retval); 1402 } 1403 1404 static void 1405 es_error(const char *fmt, ...) 1406 { 1407 char msgbuf[BUFSIZ]; 1408 va_list args; 1409 1410 va_start(args, fmt); 1411 (void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args); 1412 va_end(args); 1413 (void) fflush(stdout); 1414 cryptoerror(LOG_STDERR, "%s", msgbuf); 1415 (void) fflush(stderr); 1416 } 1417 1418 static char * 1419 time_str(time_t t) 1420 { 1421 static char buf[80]; 1422 char *bufp; 1423 1424 bufp = buf; 1425 if (strftime(buf, sizeof (buf), NULL, localtime(&t)) == 0) 1426 bufp = ctime(&t); 1427 return (bufp); 1428 } 1429 1430 static void 1431 sig_info_print(struct ELFsign_sig_info *esip) 1432 { 1433 if (esip == NULL) 1434 return; 1435 (void) fprintf(stdout, gettext("format: %s.\n"), esip->esi_format); 1436 (void) fprintf(stdout, gettext("signer: %s.\n"), esip->esi_signer); 1437 if (esip->esi_time == 0) 1438 return; 1439 (void) fprintf(stdout, gettext("signed on: %s.\n"), 1440 time_str(esip->esi_time)); 1441 } 1442