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