15194Sjohnz /*
25194Sjohnz * CDDL HEADER START
35194Sjohnz *
45194Sjohnz * The contents of this file are subject to the terms of the
55194Sjohnz * Common Development and Distribution License (the "License").
65194Sjohnz * You may not use this file except in compliance with the License.
75194Sjohnz *
85194Sjohnz * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95194Sjohnz * or http://www.opensolaris.org/os/licensing.
105194Sjohnz * See the License for the specific language governing permissions
115194Sjohnz * and limitations under the License.
125194Sjohnz *
135194Sjohnz * When distributing Covered Code, include this CDDL HEADER in each
145194Sjohnz * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155194Sjohnz * If applicable, add the following below this CDDL HEADER, with the
165194Sjohnz * fields enclosed by brackets "[]" replaced with your own identifying
175194Sjohnz * information: Portions Copyright [yyyy] [name of copyright owner]
185194Sjohnz *
195194Sjohnz * CDDL HEADER END
205194Sjohnz */
215194Sjohnz
225194Sjohnz /*
23*12304SValerie.Fenwick@Oracle.COM * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
245194Sjohnz */
255194Sjohnz
265194Sjohnz /*
275194Sjohnz * Developer command for adding the signature section to an ELF object
285194Sjohnz * PSARC 2001/488
295194Sjohnz *
305194Sjohnz * DEBUG Information:
315194Sjohnz * This command uses the cryptodebug() function from libcryptoutil.
325194Sjohnz * Set SUNW_CRYPTO_DEBUG to stderr or syslog for all debug to go to auth.debug
335194Sjohnz */
345194Sjohnz
355194Sjohnz #include <stdio.h>
365194Sjohnz #include <stdlib.h>
375194Sjohnz #include <stdarg.h>
385194Sjohnz #include <limits.h>
395194Sjohnz #include <time.h>
405194Sjohnz #include <unistd.h>
415194Sjohnz #include <sys/types.h>
425194Sjohnz #include <sys/stat.h>
435194Sjohnz #include <fcntl.h>
445194Sjohnz #include <libintl.h>
455194Sjohnz #include <locale.h>
465194Sjohnz #include <errno.h>
475194Sjohnz #include <strings.h>
485194Sjohnz
495194Sjohnz #include <cryptoutil.h>
505194Sjohnz #include <sys/crypto/elfsign.h>
515194Sjohnz #include <libelfsign.h>
525194Sjohnz
535194Sjohnz #include <kmfapi.h>
545194Sjohnz
555194Sjohnz #define SIGN "sign"
56*12304SValerie.Fenwick@Oracle.COM #define SIGN_OPTS "c:e:F:k:P:T:v"
575194Sjohnz #define VERIFY "verify"
585194Sjohnz #define VERIFY_OPTS "c:e:v"
595194Sjohnz #define REQUEST "request"
605194Sjohnz #define REQUEST_OPTS "i:k:r:T:"
615194Sjohnz #define LIST "list"
625194Sjohnz #define LIST_OPTS "c:e:f:"
635194Sjohnz
645194Sjohnz enum cmd_e {
655194Sjohnz ES_SIGN,
665194Sjohnz ES_VERIFY,
675194Sjohnz ES_REQUEST,
685194Sjohnz ES_LIST
695194Sjohnz };
705194Sjohnz
715194Sjohnz enum field_e {
725194Sjohnz FLD_UNKNOWN,
735194Sjohnz FLD_SUBJECT,
745194Sjohnz FLD_ISSUER,
755194Sjohnz FLD_FORMAT,
765194Sjohnz FLD_SIGNER,
775194Sjohnz FLD_TIME
785194Sjohnz };
795194Sjohnz
805194Sjohnz #define MIN_ARGS 3 /* The minimum # args to do anything */
815194Sjohnz #define ES_DEFAULT_KEYSIZE 1024
825194Sjohnz
835194Sjohnz static struct {
845194Sjohnz enum cmd_e cmd; /* sub command: sign | verify | request */
855194Sjohnz char *cert; /* -c <certificate_file> | */
865194Sjohnz /* -r <certificate_request_file> */
875194Sjohnz char **elfobj; /* -e <elf_object> */
885194Sjohnz int elfcnt;
895194Sjohnz enum ES_ACTION es_action;
905194Sjohnz ELFsign_t ess; /* libelfsign opaque "state" */
915194Sjohnz int extracnt;
925194Sjohnz enum field_e field; /* -f <field> */
935194Sjohnz char internal_req; /* Sun internal certificate request */
945194Sjohnz char *pinpath; /* -P <pin> */
955194Sjohnz char *privpath; /* -k <private_key> */
965194Sjohnz char *token_label; /* -T <token_label> */
975194Sjohnz boolean_t verbose; /* chatty output */
985194Sjohnz } cmd_info;
995194Sjohnz
1005194Sjohnz enum ret_e {
1015194Sjohnz EXIT_OKAY,
1025194Sjohnz EXIT_INVALID_ARG,
1035194Sjohnz EXIT_VERIFY_FAILED,
1045194Sjohnz EXIT_CANT_OPEN_ELF_OBJECT,
1055194Sjohnz EXIT_BAD_CERT,
1065194Sjohnz EXIT_BAD_PRIVATEKEY,
1075194Sjohnz EXIT_SIGN_FAILED,
1085194Sjohnz EXIT_VERIFY_FAILED_UNSIGNED,
1095194Sjohnz EXIT_CSR_FAILED,
1105194Sjohnz EXIT_MEMORY_ERROR
1115194Sjohnz };
1125194Sjohnz
1135194Sjohnz struct field_s {
1145194Sjohnz char *name;
1155194Sjohnz enum field_e field;
1165194Sjohnz } fields[] = {
1175194Sjohnz { "subject", FLD_SUBJECT },
1185194Sjohnz { "issuer", FLD_ISSUER },
1195194Sjohnz { "format", FLD_FORMAT },
1205194Sjohnz { "signer", FLD_SIGNER },
1215194Sjohnz { "time", FLD_TIME },
1225194Sjohnz NULL, 0
1235194Sjohnz };
1245194Sjohnz
1255194Sjohnz typedef enum ret_e ret_t;
1265194Sjohnz
1275194Sjohnz static void usage(void);
1285194Sjohnz static ret_t getelfobj(char *);
1295194Sjohnz static char *getpin(void);
1305194Sjohnz static ret_t do_sign(char *);
1315194Sjohnz static ret_t do_verify(char *);
1325194Sjohnz static ret_t do_cert_request(char *);
1335194Sjohnz static ret_t do_list(char *);
1345194Sjohnz static void es_error(const char *fmt, ...);
1355194Sjohnz static char *time_str(time_t t);
1365194Sjohnz static void sig_info_print(struct ELFsign_sig_info *esip);
1375194Sjohnz
1385194Sjohnz int
main(int argc,char ** argv)1395194Sjohnz main(int argc, char **argv)
1405194Sjohnz {
1415194Sjohnz extern char *optarg;
1425194Sjohnz char *scmd = NULL;
1435194Sjohnz char *opts; /* The set of flags for cmd */
1445194Sjohnz int errflag = 0; /* We had an options parse error */
1455194Sjohnz char c; /* current getopts flag */
1465194Sjohnz ret_t (*action)(char *); /* Function pointer for the action */
1475194Sjohnz ret_t ret;
1485194Sjohnz
1495194Sjohnz (void) setlocale(LC_ALL, "");
1505194Sjohnz #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
1515194Sjohnz #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
1525194Sjohnz #endif
1535194Sjohnz (void) textdomain(TEXT_DOMAIN);
1545194Sjohnz
1555194Sjohnz cryptodebug_init("elfsign");
1565194Sjohnz
1575194Sjohnz if (argc < MIN_ARGS) {
1585194Sjohnz es_error(gettext("invalid number of arguments"));
1595194Sjohnz usage();
1605194Sjohnz return (EXIT_INVALID_ARG);
1615194Sjohnz }
1625194Sjohnz
1635194Sjohnz scmd = argv[1];
1645194Sjohnz cmd_info.cert = NULL;
1655194Sjohnz cmd_info.elfobj = NULL;
1665194Sjohnz cmd_info.elfcnt = 0;
1675194Sjohnz cmd_info.es_action = ES_GET;
1685194Sjohnz cmd_info.ess = NULL;
1695194Sjohnz cmd_info.extracnt = 0;
1705194Sjohnz cmd_info.field = FLD_UNKNOWN;
1715194Sjohnz cmd_info.internal_req = '\0';
1725194Sjohnz cmd_info.pinpath = NULL;
1735194Sjohnz cmd_info.privpath = NULL;
1745194Sjohnz cmd_info.token_label = NULL;
1755194Sjohnz cmd_info.verbose = B_FALSE;
1765194Sjohnz
1775194Sjohnz if (strcmp(scmd, SIGN) == 0) {
1785194Sjohnz cmd_info.cmd = ES_SIGN;
1795194Sjohnz opts = SIGN_OPTS;
1805194Sjohnz cryptodebug("cmd=sign opts=%s", opts);
1815194Sjohnz action = do_sign;
1825194Sjohnz cmd_info.es_action = ES_UPDATE_RSA_SHA1;
1835194Sjohnz } else if (strcmp(scmd, VERIFY) == 0) {
1845194Sjohnz cmd_info.cmd = ES_VERIFY;
1855194Sjohnz opts = VERIFY_OPTS;
1865194Sjohnz cryptodebug("cmd=verify opts=%s", opts);
1875194Sjohnz action = do_verify;
1885194Sjohnz } else if (strcmp(scmd, REQUEST) == 0) {
1895194Sjohnz cmd_info.cmd = ES_REQUEST;
1905194Sjohnz opts = REQUEST_OPTS;
1915194Sjohnz cryptodebug("cmd=request opts=%s", opts);
1925194Sjohnz action = do_cert_request;
1935194Sjohnz } else if (strcmp(scmd, LIST) == 0) {
1945194Sjohnz cmd_info.cmd = ES_LIST;
1955194Sjohnz opts = LIST_OPTS;
1965194Sjohnz cryptodebug("cmd=list opts=%s", opts);
1975194Sjohnz action = do_list;
1985194Sjohnz } else {
1995194Sjohnz es_error(gettext("Unknown sub-command: %s"),
2005194Sjohnz scmd);
2015194Sjohnz usage();
2025194Sjohnz return (EXIT_INVALID_ARG);
2035194Sjohnz }
2045194Sjohnz
2055194Sjohnz /*
2065194Sjohnz * Note: There is no need to check that optarg isn't NULL
2075194Sjohnz * because getopt does that for us.
2085194Sjohnz */
2095194Sjohnz while (!errflag && (c = getopt(argc - 1, argv + 1, opts)) != EOF) {
21010671SJohn.Zolnowsky@Sun.COM if (strchr("ceFihkPTr", c) != NULL)
2115194Sjohnz cryptodebug("c=%c, '%s'", c, optarg);
2125194Sjohnz else
2135194Sjohnz cryptodebug("c=%c", c);
2145194Sjohnz
2155194Sjohnz switch (c) {
2165194Sjohnz case 'c':
2175194Sjohnz cmd_info.cert = optarg;
2185194Sjohnz break;
2195194Sjohnz case 'e':
2205194Sjohnz cmd_info.elfcnt++;
2215194Sjohnz cmd_info.elfobj = (char **)realloc(cmd_info.elfobj,
2225194Sjohnz sizeof (char *) * cmd_info.elfcnt);
2235194Sjohnz if (cmd_info.elfobj == NULL) {
2245194Sjohnz es_error(gettext(
2255194Sjohnz "Too many elf objects specified."));
2265194Sjohnz return (EXIT_INVALID_ARG);
2275194Sjohnz }
2285194Sjohnz cmd_info.elfobj[cmd_info.elfcnt - 1] = optarg;
2295194Sjohnz break;
2305194Sjohnz case 'f':
2315194Sjohnz {
2325194Sjohnz struct field_s *fp;
2335194Sjohnz cmd_info.field = FLD_UNKNOWN;
2345194Sjohnz for (fp = fields; fp->name != NULL; fp++) {
2355194Sjohnz if (strcasecmp(optarg, fp->name) == 0) {
2365194Sjohnz cmd_info.field = fp->field;
2375194Sjohnz break;
2385194Sjohnz }
2395194Sjohnz }
2405194Sjohnz if (cmd_info.field == FLD_UNKNOWN) {
2415194Sjohnz cryptodebug("Invalid field option");
2425194Sjohnz errflag++;
2435194Sjohnz }
2445194Sjohnz }
2455194Sjohnz break;
2465194Sjohnz case 'F':
2475194Sjohnz if (strcasecmp(optarg, ES_FMT_RSA_MD5_SHA1) == 0)
2485194Sjohnz cmd_info.es_action = ES_UPDATE_RSA_MD5_SHA1;
2495194Sjohnz else if (strcasecmp(optarg, ES_FMT_RSA_SHA1) == 0)
2505194Sjohnz cmd_info.es_action = ES_UPDATE_RSA_SHA1;
2515194Sjohnz else {
2525194Sjohnz cryptodebug("Invalid format option");
2535194Sjohnz errflag++;
2545194Sjohnz }
2555194Sjohnz break;
2565194Sjohnz case 'i': /* Undocumented internal Sun use only */
2575194Sjohnz cmd_info.internal_req = *optarg;
2585194Sjohnz break;
2595194Sjohnz case 'k':
2605194Sjohnz cmd_info.privpath = optarg;
2615194Sjohnz if (cmd_info.token_label != NULL ||
2625194Sjohnz cmd_info.pinpath != NULL)
2635194Sjohnz errflag++;
2645194Sjohnz break;
2655194Sjohnz case 'P':
2665194Sjohnz cmd_info.pinpath = optarg;
2675194Sjohnz if (cmd_info.privpath != NULL)
2685194Sjohnz errflag++;
2695194Sjohnz break;
2705194Sjohnz case 'r':
2715194Sjohnz cmd_info.cert = optarg;
2725194Sjohnz break;
2735194Sjohnz case 'T':
2745194Sjohnz cmd_info.token_label = optarg;
2755194Sjohnz if (cmd_info.privpath != NULL)
2765194Sjohnz errflag++;
2775194Sjohnz break;
2785194Sjohnz case 'v':
2795194Sjohnz cmd_info.verbose = B_TRUE;
2805194Sjohnz break;
2815194Sjohnz default:
2825194Sjohnz errflag++;
2835194Sjohnz }
2845194Sjohnz }
2855194Sjohnz
2865194Sjohnz optind++; /* we skipped over subcommand */
2875194Sjohnz cmd_info.extracnt = argc - optind;
2885194Sjohnz
2895194Sjohnz if (cmd_info.extracnt != 0 &&
2905194Sjohnz cmd_info.cmd != ES_SIGN && cmd_info.cmd != ES_VERIFY) {
2915194Sjohnz cryptodebug("Extra arguments, optind=%d, argc=%d",
2925194Sjohnz optind, argc);
2935194Sjohnz errflag++;
2945194Sjohnz }
2955194Sjohnz
2965194Sjohnz switch (cmd_info.cmd) {
2975194Sjohnz case ES_VERIFY:
2985194Sjohnz if (cmd_info.elfcnt + argc - optind == 0) {
2995194Sjohnz cryptodebug("Missing elfobj");
3005194Sjohnz errflag++;
3015194Sjohnz }
3025194Sjohnz break;
3035194Sjohnz
3045194Sjohnz case ES_SIGN:
3055194Sjohnz if (((cmd_info.privpath == NULL) &&
3065194Sjohnz (cmd_info.token_label == NULL)) ||
3075194Sjohnz (cmd_info.cert == NULL) ||
3085194Sjohnz (cmd_info.elfcnt + argc - optind == 0)) {
3095194Sjohnz cryptodebug("Missing privpath|token_label/cert/elfobj");
3105194Sjohnz errflag++;
3115194Sjohnz }
3125194Sjohnz break;
3135194Sjohnz
3145194Sjohnz case ES_REQUEST:
3155194Sjohnz if (((cmd_info.privpath == NULL) &&
3165194Sjohnz (cmd_info.token_label == NULL)) ||
3175194Sjohnz (cmd_info.cert == NULL)) {
3185194Sjohnz cryptodebug("Missing privpath|token_label/certreq");
3195194Sjohnz errflag++;
3205194Sjohnz }
3215194Sjohnz break;
3225194Sjohnz case ES_LIST:
3235194Sjohnz if ((cmd_info.cert != NULL) == (cmd_info.elfcnt > 0)) {
3245194Sjohnz cryptodebug("Neither or both of cert/elfobj");
3255194Sjohnz errflag++;
3265194Sjohnz }
3275194Sjohnz break;
3285194Sjohnz }
3295194Sjohnz
3305194Sjohnz if (errflag) {
3315194Sjohnz usage();
3325194Sjohnz return (EXIT_INVALID_ARG);
3335194Sjohnz }
3345194Sjohnz
3355194Sjohnz switch (cmd_info.cmd) {
3365194Sjohnz case ES_REQUEST:
3375194Sjohnz case ES_LIST:
3385194Sjohnz ret = action(NULL);
3395194Sjohnz break;
3405194Sjohnz default:
3415194Sjohnz {
3425194Sjohnz int i;
3435194Sjohnz ret_t iret;
3445194Sjohnz
3455194Sjohnz ret = EXIT_OKAY;
3465194Sjohnz iret = EXIT_OKAY;
3475194Sjohnz for (i = 0; i < cmd_info.elfcnt &&
3485194Sjohnz (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) {
3495194Sjohnz iret = action(cmd_info.elfobj[i]);
3505194Sjohnz if (iret > ret)
3515194Sjohnz ret = iret;
3525194Sjohnz }
3535194Sjohnz for (i = optind; i < argc &&
3545194Sjohnz (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) {
3555194Sjohnz iret = action(argv[i]);
3565194Sjohnz if (iret > ret)
3575194Sjohnz ret = iret;
3585194Sjohnz }
3595194Sjohnz break;
3605194Sjohnz }
3615194Sjohnz }
3625194Sjohnz
3635194Sjohnz if (cmd_info.elfobj != NULL)
3645194Sjohnz free(cmd_info.elfobj);
3655194Sjohnz
3665194Sjohnz return (ret);
3675194Sjohnz }
3685194Sjohnz
3695194Sjohnz
3705194Sjohnz static void
usage(void)3715194Sjohnz usage(void)
3725194Sjohnz {
3735194Sjohnz /* BEGIN CSTYLED */
3745194Sjohnz (void) fprintf(stderr, gettext(
3755194Sjohnz "usage:\n"
376*12304SValerie.Fenwick@Oracle.COM "\telfsign sign [-v] [-e <elf_object>] -c <certificate_file>\n"
3775194Sjohnz "\t\t[-F <format>] -k <private_key_file> [elf_object]..."
3785194Sjohnz "\n"
379*12304SValerie.Fenwick@Oracle.COM "\telfsign sign [-v] [-e <elf_object>] -c <certificate_file>\n"
3805194Sjohnz "\t\t[-F <format>] -T <token_label> [-P <pin_file>] [elf_object]..."
3815194Sjohnz "\n\n"
3825194Sjohnz "\telfsign verify [-v] [-c <certificate_file>] [-e <elf_object>]\n"
3835194Sjohnz "\t\t[elf_object]..."
3845194Sjohnz "\n\n"
3855194Sjohnz "\telfsign request -r <certificate_request_file> -k <private_key_file>"
3865194Sjohnz "\n"
3875194Sjohnz "\telfsign request -r <certificate_request_file> -T <token_label>"
3885194Sjohnz "\n\n"
3895194Sjohnz "\telfsign list -f field -c <certificate_file>"
3905194Sjohnz "\n"
3915194Sjohnz "\telfsign list -f field -e <elf_object>"
3925194Sjohnz "\n"));
3935194Sjohnz /* END CSTYLED */
3945194Sjohnz }
3955194Sjohnz
3965194Sjohnz static ret_t
getelfobj(char * elfpath)3975194Sjohnz getelfobj(char *elfpath)
3985194Sjohnz {
3995194Sjohnz ELFsign_status_t estatus;
4005980Sjohnz ret_t ret = EXIT_SIGN_FAILED;
4015194Sjohnz
4025194Sjohnz estatus = elfsign_begin(elfpath, cmd_info.es_action, &(cmd_info.ess));
4035194Sjohnz switch (estatus) {
4045194Sjohnz case ELFSIGN_SUCCESS:
4055194Sjohnz ret = EXIT_OKAY;
4065194Sjohnz break;
4075194Sjohnz case ELFSIGN_INVALID_ELFOBJ:
4085194Sjohnz es_error(gettext(
4095194Sjohnz "Unable to open %s as an ELF object."),
4105194Sjohnz elfpath);
4115194Sjohnz ret = EXIT_CANT_OPEN_ELF_OBJECT;
4125194Sjohnz break;
4135194Sjohnz default:
4145194Sjohnz es_error(gettext("unexpected failure: %d"), estatus);
4155194Sjohnz if (cmd_info.cmd == ES_SIGN) {
4165194Sjohnz ret = EXIT_SIGN_FAILED;
4175194Sjohnz } else if (cmd_info.cmd == ES_VERIFY) {
4185194Sjohnz ret = EXIT_VERIFY_FAILED;
4195194Sjohnz }
4205194Sjohnz }
4215194Sjohnz
4225194Sjohnz return (ret);
4235194Sjohnz }
4245194Sjohnz
4255194Sjohnz static ret_t
setcertpath(void)4265194Sjohnz setcertpath(void)
4275194Sjohnz {
4285194Sjohnz ELFsign_status_t estatus;
4295980Sjohnz ret_t ret = EXIT_SIGN_FAILED;
4305194Sjohnz
4315194Sjohnz if (cmd_info.cert == NULL)
4325194Sjohnz return (EXIT_OKAY);
4335194Sjohnz estatus = elfsign_setcertpath(cmd_info.ess, cmd_info.cert);
4345194Sjohnz switch (estatus) {
4355194Sjohnz case ELFSIGN_SUCCESS:
4365194Sjohnz ret = EXIT_OKAY;
4375194Sjohnz break;
4385194Sjohnz case ELFSIGN_INVALID_CERTPATH:
4395194Sjohnz if (cmd_info.cert != NULL) {
4405194Sjohnz es_error(gettext("Unable to open %s as a certificate."),
4415194Sjohnz cmd_info.cert);
4425194Sjohnz }
4435194Sjohnz ret = EXIT_BAD_CERT;
4445194Sjohnz break;
4455194Sjohnz default:
4466960Sbubbva es_error(gettext("unusable certificate: %s"), cmd_info.cert);
4475194Sjohnz if (cmd_info.cmd == ES_SIGN) {
4485194Sjohnz ret = EXIT_SIGN_FAILED;
4495194Sjohnz } else if (cmd_info.cmd == ES_VERIFY) {
4505194Sjohnz ret = EXIT_VERIFY_FAILED;
4515194Sjohnz }
4525194Sjohnz }
4535194Sjohnz
4545194Sjohnz return (ret);
4555194Sjohnz }
4565194Sjohnz
4575194Sjohnz /*
4585194Sjohnz * getpin - return pointer to token PIN in static storage
4595194Sjohnz */
4605194Sjohnz static char *
getpin(void)4615194Sjohnz getpin(void)
4625194Sjohnz {
4635194Sjohnz static char pinbuf[PASS_MAX + 1];
4645194Sjohnz char *pp;
4655194Sjohnz FILE *pinfile;
4665194Sjohnz
4675194Sjohnz if (cmd_info.pinpath == NULL)
4685194Sjohnz return (getpassphrase(
4695194Sjohnz gettext("Enter PIN for PKCS#11 token: ")));
4705194Sjohnz if ((pinfile = fopen(cmd_info.pinpath, "r")) == NULL) {
4715194Sjohnz es_error(gettext("failed to open %s."),
4725194Sjohnz cmd_info.pinpath);
4735194Sjohnz return (NULL);
4745194Sjohnz }
4755194Sjohnz
4765194Sjohnz pp = fgets(pinbuf, sizeof (pinbuf), pinfile);
4775194Sjohnz (void) fclose(pinfile);
4785194Sjohnz if (pp == NULL) {
4795194Sjohnz es_error(gettext("failed to read PIN from %s."),
4805194Sjohnz cmd_info.pinpath);
4815194Sjohnz return (NULL);
4825194Sjohnz }
4835194Sjohnz pp = &pinbuf[strlen(pinbuf) - 1];
4845194Sjohnz if (*pp == '\n')
4855194Sjohnz *pp = '\0';
4865194Sjohnz return (pinbuf);
4875194Sjohnz }
4885194Sjohnz
4895194Sjohnz /*
4905194Sjohnz * Add the .SUNW_signature sections for the ELF signature
4915194Sjohnz */
4925194Sjohnz static ret_t
do_sign(char * object)4935194Sjohnz do_sign(char *object)
4945194Sjohnz {
4955194Sjohnz ret_t ret;
4965194Sjohnz ELFsign_status_t elfstat;
4975194Sjohnz struct filesignatures *fssp = NULL;
4985194Sjohnz size_t fs_len;
4995194Sjohnz uchar_t sig[SIG_MAX_LENGTH];
5005194Sjohnz size_t sig_len = SIG_MAX_LENGTH;
5015194Sjohnz uchar_t hash[SIG_MAX_LENGTH];
5025194Sjohnz size_t hash_len = SIG_MAX_LENGTH;
5035194Sjohnz ELFCert_t cert = NULL;
5045194Sjohnz char *dn;
5055194Sjohnz size_t dn_len;
5065194Sjohnz
5075194Sjohnz cryptodebug("do_sign");
5085194Sjohnz if ((ret = getelfobj(object)) != EXIT_OKAY)
5095194Sjohnz return (ret);
5105194Sjohnz
5115194Sjohnz if (cmd_info.token_label &&
5125194Sjohnz !elfcertlib_settoken(cmd_info.ess, cmd_info.token_label)) {
5135194Sjohnz es_error(gettext("Unable to access token: %s"),
5145194Sjohnz cmd_info.token_label);
5155194Sjohnz ret = EXIT_SIGN_FAILED;
5165194Sjohnz goto cleanup;
5175194Sjohnz }
5185194Sjohnz
5195194Sjohnz if ((ret = setcertpath()) != EXIT_OKAY)
5205194Sjohnz goto cleanup;
5215194Sjohnz
5225194Sjohnz if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert,
5235194Sjohnz cmd_info.es_action)) {
5245194Sjohnz es_error(gettext("Unable to load certificate: %s"),
5255194Sjohnz cmd_info.cert);
5265194Sjohnz ret = EXIT_BAD_CERT;
5275194Sjohnz goto cleanup;
5285194Sjohnz }
5295194Sjohnz
5305194Sjohnz if (cmd_info.privpath != NULL) {
5315194Sjohnz if (!elfcertlib_loadprivatekey(cmd_info.ess, cert,
5325194Sjohnz cmd_info.privpath)) {
5335194Sjohnz es_error(gettext("Unable to load private key: %s"),
5345194Sjohnz cmd_info.privpath);
5355194Sjohnz ret = EXIT_BAD_PRIVATEKEY;
5365194Sjohnz goto cleanup;
5375194Sjohnz }
5385194Sjohnz } else {
5395194Sjohnz char *pin = getpin();
5405194Sjohnz if (pin == NULL) {
5415194Sjohnz es_error(gettext("Unable to get PIN"));
5425194Sjohnz ret = EXIT_BAD_PRIVATEKEY;
5435194Sjohnz goto cleanup;
5445194Sjohnz }
5455194Sjohnz if (!elfcertlib_loadtokenkey(cmd_info.ess, cert,
5465194Sjohnz cmd_info.token_label, pin)) {
5475194Sjohnz es_error(gettext("Unable to access private key "
5485194Sjohnz "in token %s"), cmd_info.token_label);
5495194Sjohnz ret = EXIT_BAD_PRIVATEKEY;
5505194Sjohnz goto cleanup;
5515194Sjohnz }
5525194Sjohnz }
5535194Sjohnz
5545194Sjohnz /*
5555194Sjohnz * Get the DN from the certificate.
5565194Sjohnz */
5575194Sjohnz if ((dn = elfcertlib_getdn(cert)) == NULL) {
5585194Sjohnz es_error(gettext("Unable to find DN in certificate %s"),
5595194Sjohnz cmd_info.cert);
5605194Sjohnz ret = EXIT_SIGN_FAILED;
5615194Sjohnz goto cleanup;
5625194Sjohnz }
5635194Sjohnz dn_len = strlen(dn);
5645194Sjohnz cryptodebug("DN = %s", dn);
5655194Sjohnz
5665194Sjohnz elfstat = elfsign_signatures(cmd_info.ess, &fssp, &fs_len, ES_GET);
5675194Sjohnz if (elfstat != ELFSIGN_SUCCESS) {
5685194Sjohnz if (elfstat != ELFSIGN_NOTSIGNED) {
5695194Sjohnz es_error(gettext("Unable to retrieve existing "
5705194Sjohnz "signature block in %s"), object);
5715194Sjohnz ret = EXIT_SIGN_FAILED;
5725194Sjohnz goto cleanup;
5735194Sjohnz }
5745194Sjohnz fssp = NULL;
5755194Sjohnz /*
5765194Sjohnz * force creation and naming of signature section
5775194Sjohnz * so the hash doesn't change
5785194Sjohnz */
5795194Sjohnz if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len,
5805194Sjohnz cmd_info.es_action) != ELFSIGN_SUCCESS) {
5815194Sjohnz es_error(gettext("Unable to insert "
5825194Sjohnz "signature block into %s"), object);
5835194Sjohnz ret = EXIT_SIGN_FAILED;
5845194Sjohnz goto cleanup;
5855194Sjohnz }
5865194Sjohnz }
5875194Sjohnz
5885194Sjohnz bzero(hash, sizeof (hash));
5895194Sjohnz if (elfsign_hash(cmd_info.ess, hash, &hash_len) != ELFSIGN_SUCCESS) {
5905194Sjohnz es_error(gettext("Unable to calculate hash of ELF object %s"),
5915194Sjohnz object);
5925194Sjohnz ret = EXIT_SIGN_FAILED;
5935194Sjohnz goto cleanup;
5945194Sjohnz }
5955194Sjohnz
5965194Sjohnz bzero(sig, sizeof (sig));
5975194Sjohnz if (!elfcertlib_sign(cmd_info.ess, cert,
5985194Sjohnz hash, hash_len, sig, &sig_len)) {
5995194Sjohnz es_error(gettext("Unable to sign %s using key from %s"),
6005194Sjohnz object, cmd_info.privpath ?
6015194Sjohnz cmd_info.privpath : cmd_info.token_label);
6025194Sjohnz ret = EXIT_SIGN_FAILED;
6035194Sjohnz goto cleanup;
6045194Sjohnz }
6055194Sjohnz
6065194Sjohnz { /* DEBUG START */
6075194Sjohnz const int sigstr_len = sizeof (char) * sig_len * 2 + 1;
6085194Sjohnz char *sigstr = malloc(sigstr_len);
6095194Sjohnz
6105194Sjohnz tohexstr(sig, sig_len, sigstr, sigstr_len);
6115194Sjohnz cryptodebug("sig value is: %s", sigstr);
6125194Sjohnz free(sigstr);
6135194Sjohnz } /* DEBUG END */
6145194Sjohnz
6155194Sjohnz fssp = elfsign_insert_dso(cmd_info.ess, fssp,
6165194Sjohnz dn, dn_len, sig, sig_len, NULL, 0);
6175194Sjohnz if (fssp == NULL) {
6185194Sjohnz es_error(gettext("Unable to prepare signature for %s"),
6195194Sjohnz object);
6205194Sjohnz ret = EXIT_SIGN_FAILED;
6215194Sjohnz goto cleanup;
6225194Sjohnz }
6235194Sjohnz if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len,
6245194Sjohnz cmd_info.es_action) != ELFSIGN_SUCCESS) {
6255194Sjohnz es_error(gettext("Unable to update %s: with signature"),
6265194Sjohnz object);
6275194Sjohnz ret = EXIT_SIGN_FAILED;
6285194Sjohnz goto cleanup;
6295194Sjohnz }
6305194Sjohnz if (cmd_info.verbose || (cmd_info.elfcnt + cmd_info.extracnt) > 1) {
6315194Sjohnz (void) fprintf(stdout,
6325194Sjohnz gettext("elfsign: %s signed successfully.\n"),
6335194Sjohnz object);
6345194Sjohnz }
6355194Sjohnz if (cmd_info.verbose) {
6365194Sjohnz struct ELFsign_sig_info *esip;
6375194Sjohnz
6385194Sjohnz if (elfsign_sig_info(fssp, &esip)) {
6395194Sjohnz sig_info_print(esip);
6405194Sjohnz elfsign_sig_info_free(esip);
6415194Sjohnz }
6425194Sjohnz }
6435194Sjohnz
6445194Sjohnz ret = EXIT_OKAY;
6455194Sjohnz
6465194Sjohnz cleanup:
6475194Sjohnz free(fssp);
6485194Sjohnz bzero(sig, sig_len);
6495194Sjohnz bzero(hash, hash_len);
6505194Sjohnz
6515194Sjohnz if (cert != NULL)
6525194Sjohnz elfcertlib_releasecert(cmd_info.ess, cert);
6535194Sjohnz if (cmd_info.ess != NULL)
6545194Sjohnz elfsign_end(cmd_info.ess);
6555194Sjohnz
6565194Sjohnz return (ret);
6575194Sjohnz }
6585194Sjohnz
6595194Sjohnz /*
6605194Sjohnz * Verify the signature of the object
6615194Sjohnz * This subcommand is intended to be used by developers during their build
6625194Sjohnz * processes. Therefore we can not assume that the certificate is in
6635194Sjohnz * /etc/crypto/certs so we must use the path we got from the commandline.
6645194Sjohnz */
6655194Sjohnz static ret_t
do_verify(char * object)6665194Sjohnz do_verify(char *object)
6675194Sjohnz {
6685194Sjohnz ELFsign_status_t res;
6695194Sjohnz struct ELFsign_sig_info *esip;
6705194Sjohnz ret_t retval;
6715194Sjohnz
6725194Sjohnz cryptodebug("do_verify");
6735194Sjohnz if ((retval = getelfobj(object)) != EXIT_OKAY)
6745194Sjohnz return (retval);
6755194Sjohnz
6765194Sjohnz if ((retval = setcertpath()) != EXIT_OKAY) {
6775194Sjohnz elfsign_end(cmd_info.ess);
6785194Sjohnz return (retval);
6795194Sjohnz }
6805194Sjohnz
6815194Sjohnz res = elfsign_verify_signature(cmd_info.ess, &esip);
6825194Sjohnz switch (res) {
6835194Sjohnz case ELFSIGN_SUCCESS:
6845194Sjohnz (void) fprintf(stdout,
6855194Sjohnz gettext("elfsign: verification of %s passed.\n"),
6865194Sjohnz object);
6875194Sjohnz if (cmd_info.verbose)
6885194Sjohnz sig_info_print(esip);
6895194Sjohnz retval = EXIT_OKAY;
6905194Sjohnz break;
6915194Sjohnz case ELFSIGN_FAILED:
6925194Sjohnz case ELFSIGN_INVALID_CERTPATH:
6935194Sjohnz es_error(gettext("verification of %s failed."),
6945194Sjohnz object);
6955194Sjohnz if (cmd_info.verbose)
6965194Sjohnz sig_info_print(esip);
6975194Sjohnz retval = EXIT_VERIFY_FAILED;
6985194Sjohnz break;
6995194Sjohnz case ELFSIGN_NOTSIGNED:
7005194Sjohnz es_error(gettext("no signature found in %s."),
7015194Sjohnz object);
7025194Sjohnz retval = EXIT_VERIFY_FAILED_UNSIGNED;
7035194Sjohnz break;
7045194Sjohnz default:
7055194Sjohnz es_error(gettext("unexpected failure attempting verification "
7065194Sjohnz "of %s."), object);
7075194Sjohnz retval = EXIT_VERIFY_FAILED_UNSIGNED;
7085194Sjohnz break;
7095194Sjohnz }
7105194Sjohnz
7115194Sjohnz if (esip != NULL)
7125194Sjohnz elfsign_sig_info_free(esip);
7135194Sjohnz if (cmd_info.ess != NULL)
7145194Sjohnz elfsign_end(cmd_info.ess);
7155194Sjohnz return (retval);
7165194Sjohnz }
7175194Sjohnz
7185194Sjohnz #define SET_VALUE(f, s) \
7195194Sjohnz kmfrv = f; \
7205194Sjohnz if (kmfrv != KMF_OK) { \
7215194Sjohnz char *e = NULL; \
72210671SJohn.Zolnowsky@Sun.COM (void) kmf_get_kmf_error_str(kmfrv, &e); \
7235194Sjohnz cryptoerror(LOG_STDERR, \
7245194Sjohnz gettext("Failed to %s: %s\n"), \
7255194Sjohnz s, (e ? e : "unknown error")); \
7265194Sjohnz if (e) free(e); \
7275194Sjohnz goto cleanup; \
7285194Sjohnz }
7295194Sjohnz
7305194Sjohnz static KMF_RETURN
create_csr(char * dn)7315194Sjohnz create_csr(char *dn)
7325194Sjohnz {
7335194Sjohnz KMF_RETURN kmfrv = KMF_OK;
7345194Sjohnz KMF_HANDLE_T kmfhandle = NULL;
7355194Sjohnz KMF_KEY_HANDLE pubk, prik;
7365194Sjohnz KMF_X509_NAME csrSubject;
7375194Sjohnz KMF_CSR_DATA csr;
7385194Sjohnz KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
7395194Sjohnz KMF_DATA signedCsr = { NULL, 0 };
7405194Sjohnz char *err;
74110671SJohn.Zolnowsky@Sun.COM KMF_ATTRIBUTE attrlist[16];
74210671SJohn.Zolnowsky@Sun.COM KMF_ENCODE_FORMAT format;
74310671SJohn.Zolnowsky@Sun.COM KMF_KEYSTORE_TYPE kstype;
74410671SJohn.Zolnowsky@Sun.COM KMF_KEY_ALG keytype;
74510671SJohn.Zolnowsky@Sun.COM uint32_t keylength;
74610671SJohn.Zolnowsky@Sun.COM KMF_CREDENTIAL cred;
74710671SJohn.Zolnowsky@Sun.COM char *pin = NULL;
74810671SJohn.Zolnowsky@Sun.COM int numattr;
7495194Sjohnz
75010671SJohn.Zolnowsky@Sun.COM if ((kmfrv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
75110671SJohn.Zolnowsky@Sun.COM (void) kmf_get_kmf_error_str(kmfrv, &err);
7525194Sjohnz cryptoerror(LOG_STDERR,
7535194Sjohnz gettext("Error initializing KMF: %s\n"),
7545194Sjohnz (err ? err : "unknown error"));
7555194Sjohnz if (err)
7565194Sjohnz free(err);
7575194Sjohnz return (kmfrv);
7585194Sjohnz }
7595194Sjohnz (void) memset(&csr, 0, sizeof (csr));
7605194Sjohnz (void) memset(&csrSubject, 0, sizeof (csrSubject));
7615194Sjohnz
7625194Sjohnz if (cmd_info.privpath != NULL) {
76310671SJohn.Zolnowsky@Sun.COM kstype = KMF_KEYSTORE_OPENSSL;
76410671SJohn.Zolnowsky@Sun.COM format = KMF_FORMAT_ASN1;
76510671SJohn.Zolnowsky@Sun.COM } else {
76610671SJohn.Zolnowsky@Sun.COM boolean_t readonly;
76710671SJohn.Zolnowsky@Sun.COM /* args checking verified (cmd_info.token_label != NULL) */
7685194Sjohnz
7695194Sjohnz /* Get a PIN to store the private key in the token */
77010671SJohn.Zolnowsky@Sun.COM pin = getpin();
7715194Sjohnz
7725194Sjohnz if (pin == NULL) {
77310671SJohn.Zolnowsky@Sun.COM (void) kmf_finalize(kmfhandle);
7745194Sjohnz return (KMF_ERR_AUTH_FAILED);
7755194Sjohnz }
7765194Sjohnz
77710671SJohn.Zolnowsky@Sun.COM kstype = KMF_KEYSTORE_PK11TOKEN;
77810671SJohn.Zolnowsky@Sun.COM readonly = B_FALSE;
7795194Sjohnz
78010671SJohn.Zolnowsky@Sun.COM numattr = 0;
78110671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
78210671SJohn.Zolnowsky@Sun.COM KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
78310671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
78410671SJohn.Zolnowsky@Sun.COM KMF_TOKEN_LABEL_ATTR, cmd_info.token_label,
78510671SJohn.Zolnowsky@Sun.COM strlen(cmd_info.token_label));
78610671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
78710671SJohn.Zolnowsky@Sun.COM KMF_READONLY_ATTR, &readonly, sizeof (readonly));
78810671SJohn.Zolnowsky@Sun.COM kmfrv = kmf_configure_keystore(kmfhandle, numattr, attrlist);
7895194Sjohnz if (kmfrv != KMF_OK) {
7905194Sjohnz goto cleanup;
7915194Sjohnz }
7925194Sjohnz }
7935194Sjohnz
7945194Sjohnz /* Create the RSA keypair */
79510671SJohn.Zolnowsky@Sun.COM keytype = KMF_RSA;
79610671SJohn.Zolnowsky@Sun.COM keylength = ES_DEFAULT_KEYSIZE;
79710671SJohn.Zolnowsky@Sun.COM (void) memset(&prik, 0, sizeof (prik));
79810671SJohn.Zolnowsky@Sun.COM (void) memset(&pubk, 0, sizeof (pubk));
7995194Sjohnz
80010671SJohn.Zolnowsky@Sun.COM numattr = 0;
80110671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
80210671SJohn.Zolnowsky@Sun.COM KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
80310671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
80410671SJohn.Zolnowsky@Sun.COM KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
80510671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
80610671SJohn.Zolnowsky@Sun.COM KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
80710671SJohn.Zolnowsky@Sun.COM if (pin != NULL) {
80810671SJohn.Zolnowsky@Sun.COM cred.cred = pin;
80910671SJohn.Zolnowsky@Sun.COM cred.credlen = strlen(pin);
81010671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
81110671SJohn.Zolnowsky@Sun.COM KMF_CREDENTIAL_ATTR, &cred, sizeof (KMF_CREDENTIAL));
81210671SJohn.Zolnowsky@Sun.COM }
81310671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
81410671SJohn.Zolnowsky@Sun.COM KMF_PRIVKEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
81510671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
81610671SJohn.Zolnowsky@Sun.COM KMF_PUBKEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
81710671SJohn.Zolnowsky@Sun.COM if (kstype == KMF_KEYSTORE_OPENSSL) {
81810671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
81910671SJohn.Zolnowsky@Sun.COM KMF_KEY_FILENAME_ATTR, cmd_info.privpath,
82010671SJohn.Zolnowsky@Sun.COM strlen(cmd_info.privpath));
82110671SJohn.Zolnowsky@Sun.COM kmf_set_attr_at_index(attrlist, numattr++,
82210671SJohn.Zolnowsky@Sun.COM KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format));
82310671SJohn.Zolnowsky@Sun.COM }
82410671SJohn.Zolnowsky@Sun.COM
82510671SJohn.Zolnowsky@Sun.COM kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
8265194Sjohnz if (kmfrv != KMF_OK) {
82710671SJohn.Zolnowsky@Sun.COM (void) kmf_get_kmf_error_str(kmfrv, &err);
82810671SJohn.Zolnowsky@Sun.COM cryptoerror(LOG_STDERR,
82910671SJohn.Zolnowsky@Sun.COM gettext("Create RSA keypair failed: %s"),
83010671SJohn.Zolnowsky@Sun.COM (err ? err : "unknown error"));
83110671SJohn.Zolnowsky@Sun.COM free(err);
8325194Sjohnz goto cleanup;
8335194Sjohnz }
8345194Sjohnz
83510671SJohn.Zolnowsky@Sun.COM kmfrv = kmf_dn_parser(dn, &csrSubject);
8365194Sjohnz if (kmfrv != KMF_OK) {
83710671SJohn.Zolnowsky@Sun.COM (void) kmf_get_kmf_error_str(kmfrv, &err);
83810671SJohn.Zolnowsky@Sun.COM cryptoerror(LOG_STDERR,
83910671SJohn.Zolnowsky@Sun.COM gettext("Error parsing subject name: %s\n"),
84010671SJohn.Zolnowsky@Sun.COM (err ? err : "unknown error"));
84110671SJohn.Zolnowsky@Sun.COM free(err);
8425194Sjohnz goto cleanup;
8435194Sjohnz }
8445194Sjohnz
84510671SJohn.Zolnowsky@Sun.COM SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
8465194Sjohnz
84710671SJohn.Zolnowsky@Sun.COM SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
8485194Sjohnz
84910671SJohn.Zolnowsky@Sun.COM SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
8505194Sjohnz
85110671SJohn.Zolnowsky@Sun.COM SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "SignatureAlgorithm");
8525194Sjohnz
85310671SJohn.Zolnowsky@Sun.COM if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
8545194Sjohnz KMF_OK) {
85510671SJohn.Zolnowsky@Sun.COM kmfrv = kmf_create_csr_file(&signedCsr, KMF_FORMAT_PEM,
8565194Sjohnz cmd_info.cert);
8575194Sjohnz }
8585194Sjohnz
8595194Sjohnz cleanup:
86010671SJohn.Zolnowsky@Sun.COM (void) kmf_free_kmf_key(kmfhandle, &prik);
86110671SJohn.Zolnowsky@Sun.COM (void) kmf_free_data(&signedCsr);
86210671SJohn.Zolnowsky@Sun.COM (void) kmf_free_signed_csr(&csr);
86310671SJohn.Zolnowsky@Sun.COM (void) kmf_finalize(kmfhandle);
8645194Sjohnz
8655194Sjohnz return (kmfrv);
8665194Sjohnz }
8675194Sjohnz
8685194Sjohnz
8695194Sjohnz #define CN_MAX_LENGTH 64 /* Verisign implementation limit */
8705194Sjohnz /*
8715194Sjohnz * Generate a certificate request into the file named cmd_info.cert
8725194Sjohnz */
8735194Sjohnz /*ARGSUSED*/
8745194Sjohnz static ret_t
do_cert_request(char * object)8755194Sjohnz do_cert_request(char *object)
8765194Sjohnz {
8775194Sjohnz const char PartnerDNFMT[] =
8785194Sjohnz "CN=%s, "
8795194Sjohnz "OU=Class B, "
880*12304SValerie.Fenwick@Oracle.COM "OU=Solaris Cryptographic Framework, "
8815194Sjohnz "OU=Partner Object Signing, "
8825194Sjohnz "O=Sun Microsystems Inc";
8835194Sjohnz const char SunCDNFMT[] =
8845194Sjohnz "CN=%s, "
8855194Sjohnz "OU=Class B, "
886*12304SValerie.Fenwick@Oracle.COM "OU=Solaris Cryptographic Framework, "
8875194Sjohnz "OU=Corporate Object Signing, "
8885194Sjohnz "O=Sun Microsystems Inc";
8895194Sjohnz const char SunSDNFMT[] =
8905194Sjohnz "CN=%s, "
8915194Sjohnz "OU=Class B, "
892*12304SValerie.Fenwick@Oracle.COM "OU=Solaris Signed Execution, "
8935194Sjohnz "OU=Corporate Object Signing, "
8945194Sjohnz "O=Sun Microsystems Inc";
8955194Sjohnz const char *dnfmt = NULL;
8965194Sjohnz char cn[CN_MAX_LENGTH + 1];
8975194Sjohnz char *dn = NULL;
8985194Sjohnz size_t dn_len;
8995194Sjohnz KMF_RETURN kmfret;
9005194Sjohnz cryptodebug("do_cert_request");
9015194Sjohnz
9025194Sjohnz /*
9035194Sjohnz * Get the DN prefix from the user
9045194Sjohnz */
9055194Sjohnz switch (cmd_info.internal_req) {
9065194Sjohnz case 'c':
9075194Sjohnz dnfmt = SunCDNFMT;
9085194Sjohnz (void) fprintf(stdout, gettext(
9095194Sjohnz "Enter Sun Microsystems, Inc. Release name.\n"
9105194Sjohnz "This will be the prefix of the Certificate DN: "));
9115194Sjohnz break;
9125194Sjohnz case 's':
9135194Sjohnz dnfmt = SunSDNFMT;
9145194Sjohnz (void) fprintf(stdout, gettext(
9155194Sjohnz "Enter Sun Microsystems, Inc. Release name.\n"
9165194Sjohnz "This will be the prefix of the Certificate DN: "));
9175194Sjohnz break;
9185194Sjohnz default:
9195194Sjohnz dnfmt = PartnerDNFMT;
9205194Sjohnz (void) fprintf(stdout, gettext(
9215194Sjohnz "Enter Company Name / Stock Symbol"
9225194Sjohnz " or some other globally unique identifier.\n"
9235194Sjohnz "This will be the prefix of the Certificate DN: "));
9245194Sjohnz break;
9255194Sjohnz }
9265194Sjohnz
9275194Sjohnz (void) fgets(cn, sizeof (cn), stdin);
9285194Sjohnz if ((cn == NULL) || (cn[0] == '\n')) {
9295194Sjohnz es_error(gettext("you must specify a Certificate DN prefix"));
9305194Sjohnz return (EXIT_INVALID_ARG);
9315194Sjohnz }
9325194Sjohnz
9335194Sjohnz if (cn[strlen(cn) - 1] == '\n') {
9345194Sjohnz cn[strlen(cn) - 1] = '\0'; /* chop trailing \n */
9355194Sjohnz } else {
9365194Sjohnz es_error(gettext("You must specify a Certificate DN prefix "
9375194Sjohnz "of no more than %d characters"), CN_MAX_LENGTH);
9385194Sjohnz return (EXIT_INVALID_ARG);
9395194Sjohnz }
9405194Sjohnz
9415194Sjohnz /* Update DN string */
942*12304SValerie.Fenwick@Oracle.COM dn_len = strlen(cn) + strlen(dnfmt);
9435194Sjohnz dn = malloc(dn_len + 1);
944*12304SValerie.Fenwick@Oracle.COM (void) snprintf(dn, dn_len, dnfmt, cn);
9455194Sjohnz
9465194Sjohnz cryptodebug("Generating Certificate request for DN: %s", dn);
9475194Sjohnz kmfret = create_csr(dn);
9485194Sjohnz free(dn);
9495194Sjohnz if (kmfret == KMF_OK)
9505194Sjohnz return (EXIT_OKAY);
9515194Sjohnz else
9525194Sjohnz return (EXIT_CSR_FAILED);
9535194Sjohnz }
9545194Sjohnz
9555194Sjohnz static void
str_print(char * s)9565194Sjohnz str_print(char *s)
9575194Sjohnz {
9585194Sjohnz if (s == NULL)
9595194Sjohnz return;
9605194Sjohnz (void) fprintf(stdout, "%s\n", s);
9615194Sjohnz }
9625194Sjohnz
9635194Sjohnz /*ARGSUSED*/
9645194Sjohnz static ret_t
do_list(char * object)9655194Sjohnz do_list(char *object)
9665194Sjohnz {
9675194Sjohnz ret_t retval;
9685194Sjohnz
9695194Sjohnz if (cmd_info.elfcnt > 0) {
9705194Sjohnz ELFsign_status_t elfstat;
9715194Sjohnz struct filesignatures *fssp = NULL;
9725194Sjohnz size_t fs_len;
9735194Sjohnz struct ELFsign_sig_info *esip;
9745194Sjohnz
9755194Sjohnz if ((retval = getelfobj(cmd_info.elfobj[0])) != EXIT_OKAY)
9765194Sjohnz return (retval);
9775194Sjohnz elfstat = elfsign_signatures(cmd_info.ess,
9785194Sjohnz &fssp, &fs_len, ES_GET);
9795194Sjohnz if (elfstat == ELFSIGN_SUCCESS) {
9805194Sjohnz retval = EXIT_OKAY;
9815194Sjohnz if (elfsign_sig_info(fssp, &esip)) {
9825194Sjohnz switch (cmd_info.field) {
9835194Sjohnz case FLD_FORMAT:
9845194Sjohnz str_print(esip->esi_format);
9855194Sjohnz break;
9865194Sjohnz case FLD_SIGNER:
9875194Sjohnz str_print(esip->esi_signer);
9885194Sjohnz break;
9895194Sjohnz case FLD_TIME:
9905194Sjohnz if (esip->esi_time == 0)
9915194Sjohnz retval = EXIT_INVALID_ARG;
9925194Sjohnz else
9935194Sjohnz str_print(time_str(
9945194Sjohnz esip->esi_time));
9955194Sjohnz break;
9965194Sjohnz default:
9975194Sjohnz retval = EXIT_INVALID_ARG;
9985194Sjohnz }
9995194Sjohnz elfsign_sig_info_free(esip);
10005194Sjohnz }
10015194Sjohnz free(fssp);
10025194Sjohnz } else
10035194Sjohnz retval = EXIT_VERIFY_FAILED_UNSIGNED;
10045194Sjohnz elfsign_end(cmd_info.ess);
10055194Sjohnz } else {
10065194Sjohnz ELFCert_t cert;
10075194Sjohnz /*
10085194Sjohnz * Initialize the ESS record here even though we are not
10095194Sjohnz * actually opening any ELF files.
10105194Sjohnz */
10115194Sjohnz if (elfsign_begin(NULL, ES_GET, &(cmd_info.ess)) !=
10125194Sjohnz ELFSIGN_SUCCESS)
10135194Sjohnz return (EXIT_MEMORY_ERROR);
10145194Sjohnz
10155194Sjohnz if (elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL,
10165194Sjohnz &cert, cmd_info.es_action)) {
10175194Sjohnz retval = EXIT_OKAY;
10185194Sjohnz switch (cmd_info.field) {
10195194Sjohnz case FLD_SUBJECT:
10205194Sjohnz str_print(elfcertlib_getdn(cert));
10215194Sjohnz break;
10225194Sjohnz case FLD_ISSUER:
10235194Sjohnz str_print(elfcertlib_getissuer(cert));
10245194Sjohnz break;
10255194Sjohnz default:
10265194Sjohnz retval = EXIT_INVALID_ARG;
10275194Sjohnz }
10285194Sjohnz elfcertlib_releasecert(cmd_info.ess, cert);
10295194Sjohnz } else
10305194Sjohnz retval = EXIT_BAD_CERT;
10315194Sjohnz elfsign_end(cmd_info.ess);
10325194Sjohnz }
10335194Sjohnz
10345194Sjohnz return (retval);
10355194Sjohnz }
10365194Sjohnz
10375194Sjohnz static void
es_error(const char * fmt,...)10385194Sjohnz es_error(const char *fmt, ...)
10395194Sjohnz {
10405194Sjohnz char msgbuf[BUFSIZ];
10415194Sjohnz va_list args;
10425194Sjohnz
10435194Sjohnz va_start(args, fmt);
10445194Sjohnz (void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args);
10455194Sjohnz va_end(args);
10465194Sjohnz (void) fflush(stdout);
10475194Sjohnz cryptoerror(LOG_STDERR, "%s", msgbuf);
10485194Sjohnz (void) fflush(stderr);
10495194Sjohnz }
10505194Sjohnz
10515194Sjohnz static char *
time_str(time_t t)10525194Sjohnz time_str(time_t t)
10535194Sjohnz {
10545194Sjohnz static char buf[80];
10555194Sjohnz char *bufp;
10565194Sjohnz
10575194Sjohnz bufp = buf;
10585194Sjohnz if (strftime(buf, sizeof (buf), NULL, localtime(&t)) == 0)
10595194Sjohnz bufp = ctime(&t);
10605194Sjohnz return (bufp);
10615194Sjohnz }
10625194Sjohnz
10635194Sjohnz static void
sig_info_print(struct ELFsign_sig_info * esip)10645194Sjohnz sig_info_print(struct ELFsign_sig_info *esip)
10655194Sjohnz {
10665194Sjohnz if (esip == NULL)
10675194Sjohnz return;
10685194Sjohnz (void) fprintf(stdout, gettext("format: %s.\n"), esip->esi_format);
10695194Sjohnz (void) fprintf(stdout, gettext("signer: %s.\n"), esip->esi_signer);
10705194Sjohnz if (esip->esi_time == 0)
10715194Sjohnz return;
10725194Sjohnz (void) fprintf(stdout, gettext("signed on: %s.\n"),
10735194Sjohnz time_str(esip->esi_time));
10745194Sjohnz }
1075