xref: /titanic_53/usr/src/cmd/cmd-crypto/elfsign/elfsign.c (revision df8bdeb362277e8d95a74d6c097341fe97409948)
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