xref: /onnv-gate/usr/src/cmd/cmd-crypto/elfsign/elfsign.c (revision 12304:bcfa0838b31e)
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