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