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