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