1df8bdeb3Sjohnz /*
2df8bdeb3Sjohnz  * CDDL HEADER START
3df8bdeb3Sjohnz  *
4df8bdeb3Sjohnz  * The contents of this file are subject to the terms of the
5df8bdeb3Sjohnz  * Common Development and Distribution License (the "License").
6df8bdeb3Sjohnz  * You may not use this file except in compliance with the License.
7df8bdeb3Sjohnz  *
8df8bdeb3Sjohnz  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9df8bdeb3Sjohnz  * or http://www.opensolaris.org/os/licensing.
10df8bdeb3Sjohnz  * See the License for the specific language governing permissions
11df8bdeb3Sjohnz  * and limitations under the License.
12df8bdeb3Sjohnz  *
13df8bdeb3Sjohnz  * When distributing Covered Code, include this CDDL HEADER in each
14df8bdeb3Sjohnz  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15df8bdeb3Sjohnz  * If applicable, add the following below this CDDL HEADER, with the
16df8bdeb3Sjohnz  * fields enclosed by brackets "[]" replaced with your own identifying
17df8bdeb3Sjohnz  * information: Portions Copyright [yyyy] [name of copyright owner]
18df8bdeb3Sjohnz  *
19df8bdeb3Sjohnz  * CDDL HEADER END
20df8bdeb3Sjohnz  */
21df8bdeb3Sjohnz 
22df8bdeb3Sjohnz /*
239b009fc1SValerie Bubb Fenwick  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
24df8bdeb3Sjohnz  */
25df8bdeb3Sjohnz 
26df8bdeb3Sjohnz /*
27df8bdeb3Sjohnz  * Developer command for adding the signature section to an ELF object
28df8bdeb3Sjohnz  * PSARC 2001/488
29df8bdeb3Sjohnz  *
30df8bdeb3Sjohnz  * DEBUG Information:
31df8bdeb3Sjohnz  * This command uses the cryptodebug() function from libcryptoutil.
32df8bdeb3Sjohnz  * Set SUNW_CRYPTO_DEBUG to stderr or syslog for all debug to go to auth.debug
33df8bdeb3Sjohnz  */
34df8bdeb3Sjohnz 
35df8bdeb3Sjohnz #include <stdio.h>
36df8bdeb3Sjohnz #include <stdlib.h>
37df8bdeb3Sjohnz #include <stdarg.h>
38df8bdeb3Sjohnz #include <limits.h>
39df8bdeb3Sjohnz #include <time.h>
40df8bdeb3Sjohnz #include <unistd.h>
41df8bdeb3Sjohnz #include <sys/types.h>
42df8bdeb3Sjohnz #include <sys/stat.h>
43df8bdeb3Sjohnz #include <fcntl.h>
44df8bdeb3Sjohnz #include <libintl.h>
45df8bdeb3Sjohnz #include <locale.h>
46df8bdeb3Sjohnz #include <errno.h>
47df8bdeb3Sjohnz #include <strings.h>
48df8bdeb3Sjohnz 
49df8bdeb3Sjohnz #include <cryptoutil.h>
50df8bdeb3Sjohnz #include <sys/crypto/elfsign.h>
51df8bdeb3Sjohnz #include <libelfsign.h>
52df8bdeb3Sjohnz 
53df8bdeb3Sjohnz #include <kmfapi.h>
54df8bdeb3Sjohnz 
55df8bdeb3Sjohnz #define	SIGN		"sign"
569b009fc1SValerie Bubb Fenwick #define	SIGN_OPTS	"c:e:F:k:P:T:v"
57df8bdeb3Sjohnz #define	VERIFY		"verify"
58df8bdeb3Sjohnz #define	VERIFY_OPTS	"c:e:v"
59df8bdeb3Sjohnz #define	REQUEST		"request"
60df8bdeb3Sjohnz #define	REQUEST_OPTS	"i:k:r:T:"
61df8bdeb3Sjohnz #define	LIST		"list"
62df8bdeb3Sjohnz #define	LIST_OPTS	"c:e:f:"
63df8bdeb3Sjohnz 
64df8bdeb3Sjohnz enum cmd_e {
65df8bdeb3Sjohnz 	ES_SIGN,
66df8bdeb3Sjohnz 	ES_VERIFY,
67df8bdeb3Sjohnz 	ES_REQUEST,
68df8bdeb3Sjohnz 	ES_LIST
69df8bdeb3Sjohnz };
70df8bdeb3Sjohnz 
71df8bdeb3Sjohnz enum field_e {
72df8bdeb3Sjohnz 	FLD_UNKNOWN,
73df8bdeb3Sjohnz 	FLD_SUBJECT,
74df8bdeb3Sjohnz 	FLD_ISSUER,
75df8bdeb3Sjohnz 	FLD_FORMAT,
76df8bdeb3Sjohnz 	FLD_SIGNER,
77df8bdeb3Sjohnz 	FLD_TIME
78df8bdeb3Sjohnz };
79df8bdeb3Sjohnz 
80df8bdeb3Sjohnz #define	MIN_ARGS	3	/* The minimum # args to do anything */
81df8bdeb3Sjohnz #define	ES_DEFAULT_KEYSIZE 1024
82df8bdeb3Sjohnz 
83df8bdeb3Sjohnz static struct {
84df8bdeb3Sjohnz 	enum cmd_e	cmd;	/* sub command: sign | verify | request */
85df8bdeb3Sjohnz 	char	*cert;		/* -c <certificate_file> | */
86df8bdeb3Sjohnz 				/* -r <certificate_request_file> */
87df8bdeb3Sjohnz 	char	**elfobj;	/* -e <elf_object> */
88df8bdeb3Sjohnz 	int	elfcnt;
89df8bdeb3Sjohnz 	enum ES_ACTION	es_action;
90df8bdeb3Sjohnz 	ELFsign_t	ess;	/* libelfsign opaque "state" */
91df8bdeb3Sjohnz 	int	extracnt;
92df8bdeb3Sjohnz 	enum field_e	field;	/* -f <field> */
93df8bdeb3Sjohnz 	char internal_req;	/* Sun internal certificate request */
94df8bdeb3Sjohnz 	char	*pinpath;	/* -P <pin> */
95df8bdeb3Sjohnz 	char	*privpath;	/* -k <private_key> */
96df8bdeb3Sjohnz 	char	*token_label;	/* -T <token_label> */
97df8bdeb3Sjohnz 	boolean_t verbose;	/* chatty output */
98df8bdeb3Sjohnz } cmd_info;
99df8bdeb3Sjohnz 
100df8bdeb3Sjohnz enum ret_e {
101df8bdeb3Sjohnz 	EXIT_OKAY,
102df8bdeb3Sjohnz 	EXIT_INVALID_ARG,
103df8bdeb3Sjohnz 	EXIT_VERIFY_FAILED,
104df8bdeb3Sjohnz 	EXIT_CANT_OPEN_ELF_OBJECT,
105df8bdeb3Sjohnz 	EXIT_BAD_CERT,
106df8bdeb3Sjohnz 	EXIT_BAD_PRIVATEKEY,
107df8bdeb3Sjohnz 	EXIT_SIGN_FAILED,
108df8bdeb3Sjohnz 	EXIT_VERIFY_FAILED_UNSIGNED,
109df8bdeb3Sjohnz 	EXIT_CSR_FAILED,
110df8bdeb3Sjohnz 	EXIT_MEMORY_ERROR
111df8bdeb3Sjohnz };
112df8bdeb3Sjohnz 
113df8bdeb3Sjohnz struct field_s {
114df8bdeb3Sjohnz 	char	*name;
115df8bdeb3Sjohnz 	enum field_e	field;
116df8bdeb3Sjohnz } fields[] = {
117df8bdeb3Sjohnz 	{ "subject", FLD_SUBJECT },
118df8bdeb3Sjohnz 	{ "issuer", FLD_ISSUER },
119df8bdeb3Sjohnz 	{ "format", FLD_FORMAT },
120df8bdeb3Sjohnz 	{ "signer", FLD_SIGNER },
121df8bdeb3Sjohnz 	{ "time", FLD_TIME },
122df8bdeb3Sjohnz 	NULL, 0
123df8bdeb3Sjohnz };
124df8bdeb3Sjohnz 
125df8bdeb3Sjohnz typedef enum ret_e ret_t;
126df8bdeb3Sjohnz 
127df8bdeb3Sjohnz static void usage(void);
128df8bdeb3Sjohnz static ret_t getelfobj(char *);
129df8bdeb3Sjohnz static char *getpin(void);
130df8bdeb3Sjohnz static ret_t do_sign(char *);
131df8bdeb3Sjohnz static ret_t do_verify(char *);
132df8bdeb3Sjohnz static ret_t do_cert_request(char *);
133df8bdeb3Sjohnz static ret_t do_list(char *);
134df8bdeb3Sjohnz static void es_error(const char *fmt, ...);
135df8bdeb3Sjohnz static char *time_str(time_t t);
136df8bdeb3Sjohnz static void sig_info_print(struct ELFsign_sig_info *esip);
137df8bdeb3Sjohnz 
138df8bdeb3Sjohnz int
main(int argc,char ** argv)139df8bdeb3Sjohnz main(int argc, char **argv)
140df8bdeb3Sjohnz {
141df8bdeb3Sjohnz 	extern char *optarg;
142df8bdeb3Sjohnz 	char *scmd = NULL;
143df8bdeb3Sjohnz 	char *opts;		/* The set of flags for cmd */
144df8bdeb3Sjohnz 	int errflag = 0;	/* We had an options parse error */
145*ef150c2bSRichard Lowe 	int c;			/* current getopts flag */
146df8bdeb3Sjohnz 	ret_t (*action)(char *);	/* Function pointer for the action */
147df8bdeb3Sjohnz 	ret_t ret;
148df8bdeb3Sjohnz 
149df8bdeb3Sjohnz 	(void) setlocale(LC_ALL, "");
150df8bdeb3Sjohnz #if !defined(TEXT_DOMAIN)	/* Should be defiend by cc -D */
151df8bdeb3Sjohnz #define	TEXT_DOMAIN "SYS_TEST"	/* Use this only if it weren't */
152df8bdeb3Sjohnz #endif
153df8bdeb3Sjohnz 	(void) textdomain(TEXT_DOMAIN);
154df8bdeb3Sjohnz 
155df8bdeb3Sjohnz 	cryptodebug_init("elfsign");
156df8bdeb3Sjohnz 
157df8bdeb3Sjohnz 	if (argc < MIN_ARGS) {
158df8bdeb3Sjohnz 		es_error(gettext("invalid number of arguments"));
159df8bdeb3Sjohnz 		usage();
160df8bdeb3Sjohnz 		return (EXIT_INVALID_ARG);
161df8bdeb3Sjohnz 	}
162df8bdeb3Sjohnz 
163df8bdeb3Sjohnz 	scmd = argv[1];
164df8bdeb3Sjohnz 	cmd_info.cert = NULL;
165df8bdeb3Sjohnz 	cmd_info.elfobj = NULL;
166df8bdeb3Sjohnz 	cmd_info.elfcnt = 0;
167df8bdeb3Sjohnz 	cmd_info.es_action = ES_GET;
168df8bdeb3Sjohnz 	cmd_info.ess = NULL;
169df8bdeb3Sjohnz 	cmd_info.extracnt = 0;
170df8bdeb3Sjohnz 	cmd_info.field = FLD_UNKNOWN;
171df8bdeb3Sjohnz 	cmd_info.internal_req = '\0';
172df8bdeb3Sjohnz 	cmd_info.pinpath = NULL;
173df8bdeb3Sjohnz 	cmd_info.privpath = NULL;
174df8bdeb3Sjohnz 	cmd_info.token_label = NULL;
175df8bdeb3Sjohnz 	cmd_info.verbose = B_FALSE;
176df8bdeb3Sjohnz 
177df8bdeb3Sjohnz 	if (strcmp(scmd, SIGN) == 0) {
178df8bdeb3Sjohnz 		cmd_info.cmd = ES_SIGN;
179df8bdeb3Sjohnz 		opts = SIGN_OPTS;
180df8bdeb3Sjohnz 		cryptodebug("cmd=sign opts=%s", opts);
181df8bdeb3Sjohnz 		action = do_sign;
182df8bdeb3Sjohnz 		cmd_info.es_action = ES_UPDATE_RSA_SHA1;
183df8bdeb3Sjohnz 	} else if (strcmp(scmd, VERIFY) == 0) {
184df8bdeb3Sjohnz 		cmd_info.cmd = ES_VERIFY;
185df8bdeb3Sjohnz 		opts = VERIFY_OPTS;
186df8bdeb3Sjohnz 		cryptodebug("cmd=verify opts=%s", opts);
187df8bdeb3Sjohnz 		action = do_verify;
188df8bdeb3Sjohnz 	} else if (strcmp(scmd, REQUEST) == 0) {
189df8bdeb3Sjohnz 		cmd_info.cmd = ES_REQUEST;
190df8bdeb3Sjohnz 		opts = REQUEST_OPTS;
191df8bdeb3Sjohnz 		cryptodebug("cmd=request opts=%s", opts);
192df8bdeb3Sjohnz 		action = do_cert_request;
193df8bdeb3Sjohnz 	} else if (strcmp(scmd, LIST) == 0) {
194df8bdeb3Sjohnz 		cmd_info.cmd = ES_LIST;
195df8bdeb3Sjohnz 		opts = LIST_OPTS;
196df8bdeb3Sjohnz 		cryptodebug("cmd=list opts=%s", opts);
197df8bdeb3Sjohnz 		action = do_list;
198df8bdeb3Sjohnz 	} else {
199df8bdeb3Sjohnz 		es_error(gettext("Unknown sub-command: %s"),
200df8bdeb3Sjohnz 		    scmd);
201df8bdeb3Sjohnz 		usage();
202df8bdeb3Sjohnz 		return (EXIT_INVALID_ARG);
203df8bdeb3Sjohnz 	}
204df8bdeb3Sjohnz 
205df8bdeb3Sjohnz 	/*
206df8bdeb3Sjohnz 	 * Note:  There is no need to check that optarg isn't NULL
207df8bdeb3Sjohnz 	 *	  because getopt does that for us.
208df8bdeb3Sjohnz 	 */
209df8bdeb3Sjohnz 	while (!errflag && (c = getopt(argc - 1, argv + 1, opts)) != EOF) {
2108bab47abSJohn.Zolnowsky@Sun.COM 		if (strchr("ceFihkPTr", c) != NULL)
211df8bdeb3Sjohnz 			cryptodebug("c=%c, '%s'", c, optarg);
212df8bdeb3Sjohnz 		else
213df8bdeb3Sjohnz 			cryptodebug("c=%c", c);
214df8bdeb3Sjohnz 
215df8bdeb3Sjohnz 		switch (c) {
216df8bdeb3Sjohnz 		case 'c':
217df8bdeb3Sjohnz 			cmd_info.cert = optarg;
218df8bdeb3Sjohnz 			break;
219df8bdeb3Sjohnz 		case 'e':
220df8bdeb3Sjohnz 			cmd_info.elfcnt++;
221df8bdeb3Sjohnz 			cmd_info.elfobj = (char **)realloc(cmd_info.elfobj,
222df8bdeb3Sjohnz 			    sizeof (char *) * cmd_info.elfcnt);
223df8bdeb3Sjohnz 			if (cmd_info.elfobj == NULL) {
224df8bdeb3Sjohnz 				es_error(gettext(
225df8bdeb3Sjohnz 				    "Too many elf objects specified."));
226df8bdeb3Sjohnz 				return (EXIT_INVALID_ARG);
227df8bdeb3Sjohnz 			}
228df8bdeb3Sjohnz 			cmd_info.elfobj[cmd_info.elfcnt - 1] = optarg;
229df8bdeb3Sjohnz 			break;
230df8bdeb3Sjohnz 		case 'f':
231df8bdeb3Sjohnz 			{
232df8bdeb3Sjohnz 				struct field_s	*fp;
233df8bdeb3Sjohnz 				cmd_info.field = FLD_UNKNOWN;
234df8bdeb3Sjohnz 				for (fp = fields; fp->name != NULL; fp++) {
235df8bdeb3Sjohnz 					if (strcasecmp(optarg, fp->name) == 0) {
236df8bdeb3Sjohnz 						cmd_info.field = fp->field;
237df8bdeb3Sjohnz 						break;
238df8bdeb3Sjohnz 					}
239df8bdeb3Sjohnz 				}
240df8bdeb3Sjohnz 				if (cmd_info.field == FLD_UNKNOWN) {
241df8bdeb3Sjohnz 					cryptodebug("Invalid field option");
242df8bdeb3Sjohnz 					errflag++;
243df8bdeb3Sjohnz 				}
244df8bdeb3Sjohnz 			}
245df8bdeb3Sjohnz 			break;
246df8bdeb3Sjohnz 		case 'F':
247df8bdeb3Sjohnz 			if (strcasecmp(optarg, ES_FMT_RSA_MD5_SHA1) == 0)
248df8bdeb3Sjohnz 				cmd_info.es_action = ES_UPDATE_RSA_MD5_SHA1;
249df8bdeb3Sjohnz 			else if (strcasecmp(optarg, ES_FMT_RSA_SHA1) == 0)
250df8bdeb3Sjohnz 				cmd_info.es_action = ES_UPDATE_RSA_SHA1;
251df8bdeb3Sjohnz 			else {
252df8bdeb3Sjohnz 				cryptodebug("Invalid format option");
253df8bdeb3Sjohnz 				errflag++;
254df8bdeb3Sjohnz 			}
255df8bdeb3Sjohnz 			break;
256df8bdeb3Sjohnz 		case 'i':	 /* Undocumented internal Sun use only */
257df8bdeb3Sjohnz 			cmd_info.internal_req = *optarg;
258df8bdeb3Sjohnz 			break;
259df8bdeb3Sjohnz 		case 'k':
260df8bdeb3Sjohnz 			cmd_info.privpath = optarg;
261df8bdeb3Sjohnz 			if (cmd_info.token_label != NULL ||
262df8bdeb3Sjohnz 			    cmd_info.pinpath != NULL)
263df8bdeb3Sjohnz 				errflag++;
264df8bdeb3Sjohnz 			break;
265df8bdeb3Sjohnz 		case 'P':
266df8bdeb3Sjohnz 			cmd_info.pinpath = optarg;
267df8bdeb3Sjohnz 			if (cmd_info.privpath != NULL)
268df8bdeb3Sjohnz 				errflag++;
269df8bdeb3Sjohnz 			break;
270df8bdeb3Sjohnz 		case 'r':
271df8bdeb3Sjohnz 			cmd_info.cert = optarg;
272df8bdeb3Sjohnz 			break;
273df8bdeb3Sjohnz 		case 'T':
274df8bdeb3Sjohnz 			cmd_info.token_label = optarg;
275df8bdeb3Sjohnz 			if (cmd_info.privpath != NULL)
276df8bdeb3Sjohnz 				errflag++;
277df8bdeb3Sjohnz 			break;
278df8bdeb3Sjohnz 		case 'v':
279df8bdeb3Sjohnz 			cmd_info.verbose = B_TRUE;
280df8bdeb3Sjohnz 			break;
281df8bdeb3Sjohnz 		default:
282df8bdeb3Sjohnz 			errflag++;
283df8bdeb3Sjohnz 		}
284df8bdeb3Sjohnz 	}
285df8bdeb3Sjohnz 
286df8bdeb3Sjohnz 	optind++;	/* we skipped over subcommand */
287df8bdeb3Sjohnz 	cmd_info.extracnt = argc - optind;
288df8bdeb3Sjohnz 
289df8bdeb3Sjohnz 	if (cmd_info.extracnt != 0 &&
290df8bdeb3Sjohnz 	    cmd_info.cmd != ES_SIGN && cmd_info.cmd != ES_VERIFY) {
291df8bdeb3Sjohnz 		cryptodebug("Extra arguments, optind=%d, argc=%d",
292df8bdeb3Sjohnz 		    optind, argc);
293df8bdeb3Sjohnz 		errflag++;
294df8bdeb3Sjohnz 	}
295df8bdeb3Sjohnz 
296df8bdeb3Sjohnz 	switch (cmd_info.cmd) {
297df8bdeb3Sjohnz 	case ES_VERIFY:
298df8bdeb3Sjohnz 		if (cmd_info.elfcnt + argc - optind == 0) {
299df8bdeb3Sjohnz 			cryptodebug("Missing elfobj");
300df8bdeb3Sjohnz 			errflag++;
301df8bdeb3Sjohnz 		}
302df8bdeb3Sjohnz 		break;
303df8bdeb3Sjohnz 
304df8bdeb3Sjohnz 	case ES_SIGN:
305df8bdeb3Sjohnz 		if (((cmd_info.privpath == NULL) &&
306df8bdeb3Sjohnz 		    (cmd_info.token_label == NULL)) ||
307df8bdeb3Sjohnz 		    (cmd_info.cert == NULL) ||
308df8bdeb3Sjohnz 		    (cmd_info.elfcnt + argc - optind == 0)) {
309df8bdeb3Sjohnz 			cryptodebug("Missing privpath|token_label/cert/elfobj");
310df8bdeb3Sjohnz 			errflag++;
311df8bdeb3Sjohnz 		}
312df8bdeb3Sjohnz 		break;
313df8bdeb3Sjohnz 
314df8bdeb3Sjohnz 	case ES_REQUEST:
315df8bdeb3Sjohnz 		if (((cmd_info.privpath == NULL) &&
316df8bdeb3Sjohnz 		    (cmd_info.token_label == NULL)) ||
317df8bdeb3Sjohnz 		    (cmd_info.cert == NULL)) {
318df8bdeb3Sjohnz 			cryptodebug("Missing privpath|token_label/certreq");
319df8bdeb3Sjohnz 			errflag++;
320df8bdeb3Sjohnz 		}
321df8bdeb3Sjohnz 		break;
322df8bdeb3Sjohnz 	case ES_LIST:
323df8bdeb3Sjohnz 		if ((cmd_info.cert != NULL) == (cmd_info.elfcnt > 0)) {
324df8bdeb3Sjohnz 			cryptodebug("Neither or both of cert/elfobj");
325df8bdeb3Sjohnz 			errflag++;
326df8bdeb3Sjohnz 		}
327df8bdeb3Sjohnz 		break;
328df8bdeb3Sjohnz 	}
329df8bdeb3Sjohnz 
330df8bdeb3Sjohnz 	if (errflag) {
331df8bdeb3Sjohnz 		usage();
332df8bdeb3Sjohnz 		return (EXIT_INVALID_ARG);
333df8bdeb3Sjohnz 	}
334df8bdeb3Sjohnz 
335df8bdeb3Sjohnz 	switch (cmd_info.cmd) {
336df8bdeb3Sjohnz 	case ES_REQUEST:
337df8bdeb3Sjohnz 	case ES_LIST:
338df8bdeb3Sjohnz 		ret = action(NULL);
339df8bdeb3Sjohnz 		break;
340df8bdeb3Sjohnz 	default:
341df8bdeb3Sjohnz 		{
342df8bdeb3Sjohnz 		int i;
343df8bdeb3Sjohnz 		ret_t	iret;
344df8bdeb3Sjohnz 
345df8bdeb3Sjohnz 		ret = EXIT_OKAY;
346df8bdeb3Sjohnz 		iret = EXIT_OKAY;
347df8bdeb3Sjohnz 		for (i = 0; i < cmd_info.elfcnt &&
348df8bdeb3Sjohnz 		    (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) {
349df8bdeb3Sjohnz 			iret = action(cmd_info.elfobj[i]);
350df8bdeb3Sjohnz 			if (iret > ret)
351df8bdeb3Sjohnz 				ret = iret;
352df8bdeb3Sjohnz 		}
353df8bdeb3Sjohnz 		for (i = optind; i < argc &&
354df8bdeb3Sjohnz 		    (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) {
355df8bdeb3Sjohnz 			iret = action(argv[i]);
356df8bdeb3Sjohnz 			if (iret > ret)
357df8bdeb3Sjohnz 				ret = iret;
358df8bdeb3Sjohnz 		}
359df8bdeb3Sjohnz 		break;
360df8bdeb3Sjohnz 		}
361df8bdeb3Sjohnz 	}
362df8bdeb3Sjohnz 
363df8bdeb3Sjohnz 	if (cmd_info.elfobj != NULL)
364df8bdeb3Sjohnz 		free(cmd_info.elfobj);
365df8bdeb3Sjohnz 
366df8bdeb3Sjohnz 	return (ret);
367df8bdeb3Sjohnz }
368df8bdeb3Sjohnz 
369df8bdeb3Sjohnz 
370df8bdeb3Sjohnz static void
usage(void)371df8bdeb3Sjohnz usage(void)
372df8bdeb3Sjohnz {
373df8bdeb3Sjohnz /* BEGIN CSTYLED */
374df8bdeb3Sjohnz 	(void) fprintf(stderr, gettext(
375df8bdeb3Sjohnz  "usage:\n"
3769b009fc1SValerie Bubb Fenwick  "\telfsign sign [-v] [-e <elf_object>] -c <certificate_file>\n"
377df8bdeb3Sjohnz  "\t\t[-F <format>] -k <private_key_file> [elf_object]..."
378df8bdeb3Sjohnz  "\n"
3799b009fc1SValerie Bubb Fenwick  "\telfsign sign [-v] [-e <elf_object>] -c <certificate_file>\n"
380df8bdeb3Sjohnz  "\t\t[-F <format>] -T <token_label> [-P <pin_file>] [elf_object]..."
381df8bdeb3Sjohnz  "\n\n"
382df8bdeb3Sjohnz  "\telfsign verify [-v] [-c <certificate_file>] [-e <elf_object>]\n"
383df8bdeb3Sjohnz  "\t\t[elf_object]..."
384df8bdeb3Sjohnz  "\n\n"
385df8bdeb3Sjohnz  "\telfsign request -r <certificate_request_file> -k <private_key_file>"
386df8bdeb3Sjohnz  "\n"
387df8bdeb3Sjohnz  "\telfsign request -r <certificate_request_file> -T <token_label>"
388df8bdeb3Sjohnz  "\n\n"
389df8bdeb3Sjohnz  "\telfsign list -f field -c <certificate_file>"
390df8bdeb3Sjohnz  "\n"
391df8bdeb3Sjohnz  "\telfsign list -f field -e <elf_object>"
392df8bdeb3Sjohnz  "\n"));
393df8bdeb3Sjohnz /* END CSTYLED */
394df8bdeb3Sjohnz }
395df8bdeb3Sjohnz 
396df8bdeb3Sjohnz static ret_t
getelfobj(char * elfpath)397df8bdeb3Sjohnz getelfobj(char *elfpath)
398df8bdeb3Sjohnz {
399df8bdeb3Sjohnz 	ELFsign_status_t estatus;
4003b0164d5Sjohnz 	ret_t	ret = EXIT_SIGN_FAILED;
401df8bdeb3Sjohnz 
402df8bdeb3Sjohnz 	estatus = elfsign_begin(elfpath, cmd_info.es_action, &(cmd_info.ess));
403df8bdeb3Sjohnz 	switch (estatus) {
404df8bdeb3Sjohnz 	case ELFSIGN_SUCCESS:
405df8bdeb3Sjohnz 		ret = EXIT_OKAY;
406df8bdeb3Sjohnz 		break;
407df8bdeb3Sjohnz 	case ELFSIGN_INVALID_ELFOBJ:
408df8bdeb3Sjohnz 		es_error(gettext(
409df8bdeb3Sjohnz 		    "Unable to open %s as an ELF object."),
410df8bdeb3Sjohnz 		    elfpath);
411df8bdeb3Sjohnz 		ret = EXIT_CANT_OPEN_ELF_OBJECT;
412df8bdeb3Sjohnz 		break;
413df8bdeb3Sjohnz 	default:
414df8bdeb3Sjohnz 		es_error(gettext("unexpected failure: %d"), estatus);
415df8bdeb3Sjohnz 		if (cmd_info.cmd == ES_SIGN) {
416df8bdeb3Sjohnz 			ret = EXIT_SIGN_FAILED;
417df8bdeb3Sjohnz 		} else if (cmd_info.cmd == ES_VERIFY) {
418df8bdeb3Sjohnz 			ret = EXIT_VERIFY_FAILED;
419df8bdeb3Sjohnz 		}
420df8bdeb3Sjohnz 	}
421df8bdeb3Sjohnz 
422df8bdeb3Sjohnz 	return (ret);
423df8bdeb3Sjohnz }
424df8bdeb3Sjohnz 
425df8bdeb3Sjohnz static ret_t
setcertpath(void)426df8bdeb3Sjohnz setcertpath(void)
427df8bdeb3Sjohnz {
428df8bdeb3Sjohnz 	ELFsign_status_t estatus;
4293b0164d5Sjohnz 	ret_t	ret = EXIT_SIGN_FAILED;
430df8bdeb3Sjohnz 
431df8bdeb3Sjohnz 	if (cmd_info.cert == NULL)
432df8bdeb3Sjohnz 		return (EXIT_OKAY);
433df8bdeb3Sjohnz 	estatus = elfsign_setcertpath(cmd_info.ess, cmd_info.cert);
434df8bdeb3Sjohnz 	switch (estatus) {
435df8bdeb3Sjohnz 	case ELFSIGN_SUCCESS:
436df8bdeb3Sjohnz 		ret = EXIT_OKAY;
437df8bdeb3Sjohnz 		break;
438df8bdeb3Sjohnz 	case ELFSIGN_INVALID_CERTPATH:
439df8bdeb3Sjohnz 		if (cmd_info.cert != NULL) {
440df8bdeb3Sjohnz 			es_error(gettext("Unable to open %s as a certificate."),
441df8bdeb3Sjohnz 			    cmd_info.cert);
442df8bdeb3Sjohnz 		}
443df8bdeb3Sjohnz 		ret = EXIT_BAD_CERT;
444df8bdeb3Sjohnz 		break;
445df8bdeb3Sjohnz 	default:
4460ebf3797Sbubbva 		es_error(gettext("unusable certificate: %s"), cmd_info.cert);
447df8bdeb3Sjohnz 		if (cmd_info.cmd == ES_SIGN) {
448df8bdeb3Sjohnz 			ret = EXIT_SIGN_FAILED;
449df8bdeb3Sjohnz 		} else if (cmd_info.cmd == ES_VERIFY) {
450df8bdeb3Sjohnz 			ret = EXIT_VERIFY_FAILED;
451df8bdeb3Sjohnz 		}
452df8bdeb3Sjohnz 	}
453df8bdeb3Sjohnz 
454df8bdeb3Sjohnz 	return (ret);
455df8bdeb3Sjohnz }
456df8bdeb3Sjohnz 
457df8bdeb3Sjohnz /*
458df8bdeb3Sjohnz  * getpin - return pointer to token PIN in static storage
459df8bdeb3Sjohnz  */
460df8bdeb3Sjohnz static char *
getpin(void)461df8bdeb3Sjohnz getpin(void)
462df8bdeb3Sjohnz {
463df8bdeb3Sjohnz 	static char	pinbuf[PASS_MAX + 1];
464df8bdeb3Sjohnz 	char	*pp;
465df8bdeb3Sjohnz 	FILE	*pinfile;
466df8bdeb3Sjohnz 
467df8bdeb3Sjohnz 	if (cmd_info.pinpath == NULL)
468df8bdeb3Sjohnz 		return (getpassphrase(
469df8bdeb3Sjohnz 		    gettext("Enter PIN for PKCS#11 token: ")));
470df8bdeb3Sjohnz 	if ((pinfile = fopen(cmd_info.pinpath, "r")) == NULL) {
471df8bdeb3Sjohnz 		es_error(gettext("failed to open %s."),
472df8bdeb3Sjohnz 		    cmd_info.pinpath);
473df8bdeb3Sjohnz 		return (NULL);
474df8bdeb3Sjohnz 	}
475df8bdeb3Sjohnz 
476df8bdeb3Sjohnz 	pp = fgets(pinbuf, sizeof (pinbuf), pinfile);
477df8bdeb3Sjohnz 	(void) fclose(pinfile);
478df8bdeb3Sjohnz 	if (pp == NULL) {
479df8bdeb3Sjohnz 		es_error(gettext("failed to read PIN from %s."),
480df8bdeb3Sjohnz 		    cmd_info.pinpath);
481df8bdeb3Sjohnz 		return (NULL);
482df8bdeb3Sjohnz 	}
483df8bdeb3Sjohnz 	pp = &pinbuf[strlen(pinbuf) - 1];
484df8bdeb3Sjohnz 	if (*pp == '\n')
485df8bdeb3Sjohnz 		*pp = '\0';
486df8bdeb3Sjohnz 	return (pinbuf);
487df8bdeb3Sjohnz }
488df8bdeb3Sjohnz 
489df8bdeb3Sjohnz /*
490df8bdeb3Sjohnz  * Add the .SUNW_signature sections for the ELF signature
491df8bdeb3Sjohnz  */
492df8bdeb3Sjohnz static ret_t
do_sign(char * object)493df8bdeb3Sjohnz do_sign(char *object)
494df8bdeb3Sjohnz {
495df8bdeb3Sjohnz 	ret_t 	ret;
496df8bdeb3Sjohnz 	ELFsign_status_t	elfstat;
497df8bdeb3Sjohnz 	struct filesignatures	*fssp = NULL;
498df8bdeb3Sjohnz 	size_t fs_len;
499df8bdeb3Sjohnz 	uchar_t sig[SIG_MAX_LENGTH];
500df8bdeb3Sjohnz 	size_t	sig_len = SIG_MAX_LENGTH;
501df8bdeb3Sjohnz 	uchar_t	hash[SIG_MAX_LENGTH];
502df8bdeb3Sjohnz 	size_t	hash_len = SIG_MAX_LENGTH;
503df8bdeb3Sjohnz 	ELFCert_t	cert = NULL;
504df8bdeb3Sjohnz 	char	*dn;
505df8bdeb3Sjohnz 	size_t	dn_len;
506df8bdeb3Sjohnz 
507df8bdeb3Sjohnz 	cryptodebug("do_sign");
508df8bdeb3Sjohnz 	if ((ret = getelfobj(object)) != EXIT_OKAY)
509df8bdeb3Sjohnz 		return (ret);
510df8bdeb3Sjohnz 
511df8bdeb3Sjohnz 	if (cmd_info.token_label &&
512df8bdeb3Sjohnz 	    !elfcertlib_settoken(cmd_info.ess, cmd_info.token_label)) {
513df8bdeb3Sjohnz 		es_error(gettext("Unable to access token: %s"),
514df8bdeb3Sjohnz 		    cmd_info.token_label);
515df8bdeb3Sjohnz 		ret = EXIT_SIGN_FAILED;
516df8bdeb3Sjohnz 		goto cleanup;
517df8bdeb3Sjohnz 	}
518df8bdeb3Sjohnz 
519df8bdeb3Sjohnz 	if ((ret = setcertpath()) != EXIT_OKAY)
520df8bdeb3Sjohnz 		goto cleanup;
521df8bdeb3Sjohnz 
522df8bdeb3Sjohnz 	if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert,
523df8bdeb3Sjohnz 	    cmd_info.es_action)) {
524df8bdeb3Sjohnz 		es_error(gettext("Unable to load certificate: %s"),
525df8bdeb3Sjohnz 		    cmd_info.cert);
526df8bdeb3Sjohnz 		ret = EXIT_BAD_CERT;
527df8bdeb3Sjohnz 		goto cleanup;
528df8bdeb3Sjohnz 	}
529df8bdeb3Sjohnz 
530df8bdeb3Sjohnz 	if (cmd_info.privpath != NULL) {
531df8bdeb3Sjohnz 		if (!elfcertlib_loadprivatekey(cmd_info.ess, cert,
532df8bdeb3Sjohnz 		    cmd_info.privpath)) {
533df8bdeb3Sjohnz 			es_error(gettext("Unable to load private key: %s"),
534df8bdeb3Sjohnz 			    cmd_info.privpath);
535df8bdeb3Sjohnz 			ret = EXIT_BAD_PRIVATEKEY;
536df8bdeb3Sjohnz 			goto cleanup;
537df8bdeb3Sjohnz 		}
538df8bdeb3Sjohnz 	} else {
539df8bdeb3Sjohnz 		char *pin = getpin();
540df8bdeb3Sjohnz 		if (pin == NULL) {
541df8bdeb3Sjohnz 			es_error(gettext("Unable to get PIN"));
542df8bdeb3Sjohnz 			ret = EXIT_BAD_PRIVATEKEY;
543df8bdeb3Sjohnz 			goto cleanup;
544df8bdeb3Sjohnz 		}
545df8bdeb3Sjohnz 		if (!elfcertlib_loadtokenkey(cmd_info.ess, cert,
546df8bdeb3Sjohnz 		    cmd_info.token_label, pin)) {
547df8bdeb3Sjohnz 			es_error(gettext("Unable to access private key "
548df8bdeb3Sjohnz 			    "in token %s"), cmd_info.token_label);
549df8bdeb3Sjohnz 			ret = EXIT_BAD_PRIVATEKEY;
550df8bdeb3Sjohnz 			goto cleanup;
551df8bdeb3Sjohnz 		}
552df8bdeb3Sjohnz 	}
553df8bdeb3Sjohnz 
554df8bdeb3Sjohnz 	/*
555df8bdeb3Sjohnz 	 * Get the DN from the certificate.
556df8bdeb3Sjohnz 	 */
557df8bdeb3Sjohnz 	if ((dn = elfcertlib_getdn(cert)) == NULL) {
558df8bdeb3Sjohnz 		es_error(gettext("Unable to find DN in certificate %s"),
559df8bdeb3Sjohnz 		    cmd_info.cert);
560df8bdeb3Sjohnz 		ret = EXIT_SIGN_FAILED;
561df8bdeb3Sjohnz 		goto cleanup;
562df8bdeb3Sjohnz 	}
563df8bdeb3Sjohnz 	dn_len = strlen(dn);
564df8bdeb3Sjohnz 	cryptodebug("DN = %s", dn);
565df8bdeb3Sjohnz 
566df8bdeb3Sjohnz 	elfstat = elfsign_signatures(cmd_info.ess, &fssp, &fs_len, ES_GET);
567df8bdeb3Sjohnz 	if (elfstat != ELFSIGN_SUCCESS) {
568df8bdeb3Sjohnz 		if (elfstat != ELFSIGN_NOTSIGNED) {
569df8bdeb3Sjohnz 			es_error(gettext("Unable to retrieve existing "
570df8bdeb3Sjohnz 			    "signature block in %s"), object);
571df8bdeb3Sjohnz 			ret = EXIT_SIGN_FAILED;
572df8bdeb3Sjohnz 			goto cleanup;
573df8bdeb3Sjohnz 		}
574df8bdeb3Sjohnz 		fssp = NULL;
575df8bdeb3Sjohnz 		/*
576df8bdeb3Sjohnz 		 * force creation and naming of signature section
577df8bdeb3Sjohnz 		 * so the hash doesn't change
578df8bdeb3Sjohnz 		 */
579df8bdeb3Sjohnz 		if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len,
580df8bdeb3Sjohnz 		    cmd_info.es_action) != ELFSIGN_SUCCESS) {
581df8bdeb3Sjohnz 			es_error(gettext("Unable to insert "
582df8bdeb3Sjohnz 			    "signature block into %s"), object);
583df8bdeb3Sjohnz 			ret = EXIT_SIGN_FAILED;
584df8bdeb3Sjohnz 			goto cleanup;
585df8bdeb3Sjohnz 		}
586df8bdeb3Sjohnz 	}
587df8bdeb3Sjohnz 
588df8bdeb3Sjohnz 	bzero(hash, sizeof (hash));
589df8bdeb3Sjohnz 	if (elfsign_hash(cmd_info.ess, hash, &hash_len) != ELFSIGN_SUCCESS) {
590df8bdeb3Sjohnz 		es_error(gettext("Unable to calculate hash of ELF object %s"),
591df8bdeb3Sjohnz 		    object);
592df8bdeb3Sjohnz 		ret = EXIT_SIGN_FAILED;
593df8bdeb3Sjohnz 		goto cleanup;
594df8bdeb3Sjohnz 	}
595df8bdeb3Sjohnz 
596df8bdeb3Sjohnz 	bzero(sig, sizeof (sig));
597df8bdeb3Sjohnz 	if (!elfcertlib_sign(cmd_info.ess, cert,
598df8bdeb3Sjohnz 	    hash, hash_len, sig, &sig_len)) {
599df8bdeb3Sjohnz 		es_error(gettext("Unable to sign %s using key from %s"),
600df8bdeb3Sjohnz 		    object, cmd_info.privpath ?
601df8bdeb3Sjohnz 		    cmd_info.privpath : cmd_info.token_label);
602df8bdeb3Sjohnz 		ret = EXIT_SIGN_FAILED;
603df8bdeb3Sjohnz 		goto cleanup;
604df8bdeb3Sjohnz 	}
605df8bdeb3Sjohnz 
606df8bdeb3Sjohnz 	{ /* DEBUG START */
607df8bdeb3Sjohnz 		const int sigstr_len = sizeof (char) * sig_len * 2 + 1;
608df8bdeb3Sjohnz 		char *sigstr = malloc(sigstr_len);
609df8bdeb3Sjohnz 
610df8bdeb3Sjohnz 		tohexstr(sig, sig_len, sigstr, sigstr_len);
611df8bdeb3Sjohnz 		cryptodebug("sig value is: %s", sigstr);
612df8bdeb3Sjohnz 		free(sigstr);
613df8bdeb3Sjohnz 	} /* DEBUG END */
614df8bdeb3Sjohnz 
615df8bdeb3Sjohnz 	fssp = elfsign_insert_dso(cmd_info.ess, fssp,
616df8bdeb3Sjohnz 	    dn, dn_len, sig, sig_len, NULL, 0);
617df8bdeb3Sjohnz 	if (fssp == NULL) {
618df8bdeb3Sjohnz 		es_error(gettext("Unable to prepare signature for %s"),
619df8bdeb3Sjohnz 		    object);
620df8bdeb3Sjohnz 		ret = EXIT_SIGN_FAILED;
621df8bdeb3Sjohnz 		goto cleanup;
622df8bdeb3Sjohnz 	}
623df8bdeb3Sjohnz 	if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len,
624df8bdeb3Sjohnz 	    cmd_info.es_action) != ELFSIGN_SUCCESS) {
625df8bdeb3Sjohnz 		es_error(gettext("Unable to update %s: with signature"),
626df8bdeb3Sjohnz 		    object);
627df8bdeb3Sjohnz 		ret = EXIT_SIGN_FAILED;
628df8bdeb3Sjohnz 		goto cleanup;
629df8bdeb3Sjohnz 	}
630df8bdeb3Sjohnz 	if (cmd_info.verbose || (cmd_info.elfcnt + cmd_info.extracnt) > 1) {
631df8bdeb3Sjohnz 		(void) fprintf(stdout,
632df8bdeb3Sjohnz 		    gettext("elfsign: %s signed successfully.\n"),
633df8bdeb3Sjohnz 		    object);
634df8bdeb3Sjohnz 	}
635df8bdeb3Sjohnz 	if (cmd_info.verbose) {
636df8bdeb3Sjohnz 		struct ELFsign_sig_info *esip;
637df8bdeb3Sjohnz 
638df8bdeb3Sjohnz 		if (elfsign_sig_info(fssp, &esip)) {
639df8bdeb3Sjohnz 			sig_info_print(esip);
640df8bdeb3Sjohnz 			elfsign_sig_info_free(esip);
641df8bdeb3Sjohnz 		}
642df8bdeb3Sjohnz 	}
643df8bdeb3Sjohnz 
644df8bdeb3Sjohnz 	ret = EXIT_OKAY;
645df8bdeb3Sjohnz 
646df8bdeb3Sjohnz cleanup:
647df8bdeb3Sjohnz 	free(fssp);
648df8bdeb3Sjohnz 	bzero(sig, sig_len);
649df8bdeb3Sjohnz 	bzero(hash, hash_len);
650df8bdeb3Sjohnz 
651df8bdeb3Sjohnz 	if (cert != NULL)
652df8bdeb3Sjohnz 		elfcertlib_releasecert(cmd_info.ess, cert);
653df8bdeb3Sjohnz 	if (cmd_info.ess != NULL)
654df8bdeb3Sjohnz 		elfsign_end(cmd_info.ess);
655df8bdeb3Sjohnz 
656df8bdeb3Sjohnz 	return (ret);
657df8bdeb3Sjohnz }
658df8bdeb3Sjohnz 
659df8bdeb3Sjohnz /*
660df8bdeb3Sjohnz  * Verify the signature of the object
661df8bdeb3Sjohnz  * This subcommand is intended to be used by developers during their build
662df8bdeb3Sjohnz  * processes.  Therefore we can not assume that the certificate is in
663df8bdeb3Sjohnz  * /etc/crypto/certs so we must use the path we got from the commandline.
664df8bdeb3Sjohnz  */
665df8bdeb3Sjohnz static ret_t
do_verify(char * object)666df8bdeb3Sjohnz do_verify(char *object)
667df8bdeb3Sjohnz {
668df8bdeb3Sjohnz 	ELFsign_status_t res;
669df8bdeb3Sjohnz 	struct ELFsign_sig_info	*esip;
670df8bdeb3Sjohnz 	ret_t	retval;
671df8bdeb3Sjohnz 
672df8bdeb3Sjohnz 	cryptodebug("do_verify");
673df8bdeb3Sjohnz 	if ((retval = getelfobj(object)) != EXIT_OKAY)
674df8bdeb3Sjohnz 		return (retval);
675df8bdeb3Sjohnz 
676df8bdeb3Sjohnz 	if ((retval = setcertpath()) != EXIT_OKAY) {
677df8bdeb3Sjohnz 		elfsign_end(cmd_info.ess);
678df8bdeb3Sjohnz 		return (retval);
679df8bdeb3Sjohnz 	}
680df8bdeb3Sjohnz 
681df8bdeb3Sjohnz 	res = elfsign_verify_signature(cmd_info.ess, &esip);
682df8bdeb3Sjohnz 	switch (res) {
683df8bdeb3Sjohnz 	case ELFSIGN_SUCCESS:
684df8bdeb3Sjohnz 		(void) fprintf(stdout,
685df8bdeb3Sjohnz 		    gettext("elfsign: verification of %s passed.\n"),
686df8bdeb3Sjohnz 		    object);
687df8bdeb3Sjohnz 		if (cmd_info.verbose)
688df8bdeb3Sjohnz 			sig_info_print(esip);
689df8bdeb3Sjohnz 		retval = EXIT_OKAY;
690df8bdeb3Sjohnz 		break;
691df8bdeb3Sjohnz 	case ELFSIGN_FAILED:
692df8bdeb3Sjohnz 	case ELFSIGN_INVALID_CERTPATH:
693df8bdeb3Sjohnz 		es_error(gettext("verification of %s failed."),
694df8bdeb3Sjohnz 		    object);
695df8bdeb3Sjohnz 		if (cmd_info.verbose)
696df8bdeb3Sjohnz 			sig_info_print(esip);
697df8bdeb3Sjohnz 		retval = EXIT_VERIFY_FAILED;
698df8bdeb3Sjohnz 		break;
699df8bdeb3Sjohnz 	case ELFSIGN_NOTSIGNED:
700df8bdeb3Sjohnz 		es_error(gettext("no signature found in %s."),
701df8bdeb3Sjohnz 		    object);
702df8bdeb3Sjohnz 		retval = EXIT_VERIFY_FAILED_UNSIGNED;
703df8bdeb3Sjohnz 		break;
704df8bdeb3Sjohnz 	default:
705df8bdeb3Sjohnz 		es_error(gettext("unexpected failure attempting verification "
706df8bdeb3Sjohnz 		    "of %s."), object);
707df8bdeb3Sjohnz 		retval = EXIT_VERIFY_FAILED_UNSIGNED;
708df8bdeb3Sjohnz 		break;
709df8bdeb3Sjohnz 	}
710df8bdeb3Sjohnz 
711df8bdeb3Sjohnz 	if (esip != NULL)
712df8bdeb3Sjohnz 		elfsign_sig_info_free(esip);
713df8bdeb3Sjohnz 	if (cmd_info.ess != NULL)
714df8bdeb3Sjohnz 		elfsign_end(cmd_info.ess);
715df8bdeb3Sjohnz 	return (retval);
716df8bdeb3Sjohnz }
717df8bdeb3Sjohnz 
718df8bdeb3Sjohnz #define	SET_VALUE(f, s) \
719df8bdeb3Sjohnz 	kmfrv = f; \
720df8bdeb3Sjohnz 	if (kmfrv != KMF_OK) { \
721df8bdeb3Sjohnz 		char *e = NULL; \
7228bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(kmfrv, &e); \
723df8bdeb3Sjohnz 		cryptoerror(LOG_STDERR, \
724df8bdeb3Sjohnz 			gettext("Failed to %s: %s\n"), \
725df8bdeb3Sjohnz 			s, (e ? e : "unknown error")); \
726df8bdeb3Sjohnz 		if (e) free(e); \
727df8bdeb3Sjohnz 		goto cleanup; \
728df8bdeb3Sjohnz 	}
729df8bdeb3Sjohnz 
730df8bdeb3Sjohnz static KMF_RETURN
create_csr(char * dn)731df8bdeb3Sjohnz create_csr(char *dn)
732df8bdeb3Sjohnz {
733df8bdeb3Sjohnz 	KMF_RETURN kmfrv = KMF_OK;
734df8bdeb3Sjohnz 	KMF_HANDLE_T kmfhandle = NULL;
735df8bdeb3Sjohnz 	KMF_KEY_HANDLE pubk, prik;
736df8bdeb3Sjohnz 	KMF_X509_NAME csrSubject;
737df8bdeb3Sjohnz 	KMF_CSR_DATA csr;
738df8bdeb3Sjohnz 	KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
7396b35cb3cSRichard PALO 	KMF_DATA signedCsr = { 0, NULL };
740df8bdeb3Sjohnz 	char *err;
7418bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ATTRIBUTE	attrlist[16];
7428bab47abSJohn.Zolnowsky@Sun.COM 	KMF_ENCODE_FORMAT	format;
7438bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEYSTORE_TYPE	kstype;
7448bab47abSJohn.Zolnowsky@Sun.COM 	KMF_KEY_ALG	keytype;
7458bab47abSJohn.Zolnowsky@Sun.COM 	uint32_t	keylength;
7468bab47abSJohn.Zolnowsky@Sun.COM 	KMF_CREDENTIAL	cred;
7478bab47abSJohn.Zolnowsky@Sun.COM 	char	*pin = NULL;
7488bab47abSJohn.Zolnowsky@Sun.COM 	int	numattr;
7498bab47abSJohn.Zolnowsky@Sun.COM 
7508bab47abSJohn.Zolnowsky@Sun.COM 	if ((kmfrv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
7518bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(kmfrv, &err);
752df8bdeb3Sjohnz 		cryptoerror(LOG_STDERR,
753df8bdeb3Sjohnz 		    gettext("Error initializing KMF: %s\n"),
754df8bdeb3Sjohnz 		    (err ? err : "unknown error"));
755df8bdeb3Sjohnz 		if (err)
756df8bdeb3Sjohnz 			free(err);
757df8bdeb3Sjohnz 		return (kmfrv);
758df8bdeb3Sjohnz 	}
759df8bdeb3Sjohnz 	(void) memset(&csr, 0, sizeof (csr));
760df8bdeb3Sjohnz 	(void) memset(&csrSubject, 0, sizeof (csrSubject));
761df8bdeb3Sjohnz 
762df8bdeb3Sjohnz 	if (cmd_info.privpath != NULL) {
7638bab47abSJohn.Zolnowsky@Sun.COM 		kstype = KMF_KEYSTORE_OPENSSL;
7648bab47abSJohn.Zolnowsky@Sun.COM 		format = KMF_FORMAT_ASN1;
7658bab47abSJohn.Zolnowsky@Sun.COM 	} else {
7668bab47abSJohn.Zolnowsky@Sun.COM 		boolean_t	readonly;
7678bab47abSJohn.Zolnowsky@Sun.COM 		/* args checking verified (cmd_info.token_label != NULL) */
768df8bdeb3Sjohnz 
769df8bdeb3Sjohnz 		/* Get a PIN to store the private key in the token */
7708bab47abSJohn.Zolnowsky@Sun.COM 		pin = getpin();
771df8bdeb3Sjohnz 
772df8bdeb3Sjohnz 		if (pin == NULL) {
7738bab47abSJohn.Zolnowsky@Sun.COM 			(void) kmf_finalize(kmfhandle);
774df8bdeb3Sjohnz 			return (KMF_ERR_AUTH_FAILED);
775df8bdeb3Sjohnz 		}
776df8bdeb3Sjohnz 
7778bab47abSJohn.Zolnowsky@Sun.COM 		kstype = KMF_KEYSTORE_PK11TOKEN;
7788bab47abSJohn.Zolnowsky@Sun.COM 		readonly = B_FALSE;
7798bab47abSJohn.Zolnowsky@Sun.COM 
7808bab47abSJohn.Zolnowsky@Sun.COM 		numattr = 0;
7818bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
7828bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
7838bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
7848bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_TOKEN_LABEL_ATTR, cmd_info.token_label,
7858bab47abSJohn.Zolnowsky@Sun.COM 		    strlen(cmd_info.token_label));
7868bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
7878bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_READONLY_ATTR, &readonly, sizeof (readonly));
7888bab47abSJohn.Zolnowsky@Sun.COM 		kmfrv = kmf_configure_keystore(kmfhandle, numattr, attrlist);
789df8bdeb3Sjohnz 		if (kmfrv != KMF_OK) {
790df8bdeb3Sjohnz 			goto cleanup;
791df8bdeb3Sjohnz 		}
792df8bdeb3Sjohnz 	}
793df8bdeb3Sjohnz 
794df8bdeb3Sjohnz 	/* Create the RSA keypair */
7958bab47abSJohn.Zolnowsky@Sun.COM 	keytype = KMF_RSA;
7968bab47abSJohn.Zolnowsky@Sun.COM 	keylength = ES_DEFAULT_KEYSIZE;
7978bab47abSJohn.Zolnowsky@Sun.COM 	(void) memset(&prik, 0, sizeof (prik));
7988bab47abSJohn.Zolnowsky@Sun.COM 	(void) memset(&pubk, 0, sizeof (pubk));
7998bab47abSJohn.Zolnowsky@Sun.COM 
8008bab47abSJohn.Zolnowsky@Sun.COM 	numattr = 0;
8018bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
8028bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
8038bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
8048bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYALG_ATTR, &keytype, sizeof (keytype));
8058bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
8068bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_KEYLENGTH_ATTR, &keylength, sizeof (keylength));
8078bab47abSJohn.Zolnowsky@Sun.COM 	if (pin != NULL) {
8088bab47abSJohn.Zolnowsky@Sun.COM 		cred.cred = pin;
8098bab47abSJohn.Zolnowsky@Sun.COM 		cred.credlen = strlen(pin);
8108bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
8118bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_CREDENTIAL_ATTR, &cred, sizeof (KMF_CREDENTIAL));
8128bab47abSJohn.Zolnowsky@Sun.COM 	}
8138bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
8148bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_PRIVKEY_HANDLE_ATTR, &prik, sizeof (KMF_KEY_HANDLE));
8158bab47abSJohn.Zolnowsky@Sun.COM 	kmf_set_attr_at_index(attrlist, numattr++,
8168bab47abSJohn.Zolnowsky@Sun.COM 	    KMF_PUBKEY_HANDLE_ATTR, &pubk, sizeof (KMF_KEY_HANDLE));
8178bab47abSJohn.Zolnowsky@Sun.COM 	if (kstype == KMF_KEYSTORE_OPENSSL) {
8188bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
8198bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_KEY_FILENAME_ATTR, cmd_info.privpath,
8208bab47abSJohn.Zolnowsky@Sun.COM 		    strlen(cmd_info.privpath));
8218bab47abSJohn.Zolnowsky@Sun.COM 		kmf_set_attr_at_index(attrlist, numattr++,
8228bab47abSJohn.Zolnowsky@Sun.COM 		    KMF_ENCODE_FORMAT_ATTR, &format, sizeof (format));
8238bab47abSJohn.Zolnowsky@Sun.COM 	}
824df8bdeb3Sjohnz 
8258bab47abSJohn.Zolnowsky@Sun.COM 	kmfrv = kmf_create_keypair(kmfhandle, numattr, attrlist);
826df8bdeb3Sjohnz 	if (kmfrv != KMF_OK) {
8278bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(kmfrv, &err);
8288bab47abSJohn.Zolnowsky@Sun.COM 		cryptoerror(LOG_STDERR,
8298bab47abSJohn.Zolnowsky@Sun.COM 		    gettext("Create RSA keypair failed: %s"),
8308bab47abSJohn.Zolnowsky@Sun.COM 		    (err ? err : "unknown error"));
8318bab47abSJohn.Zolnowsky@Sun.COM 		free(err);
832df8bdeb3Sjohnz 		goto cleanup;
833df8bdeb3Sjohnz 	}
834df8bdeb3Sjohnz 
8358bab47abSJohn.Zolnowsky@Sun.COM 	kmfrv = kmf_dn_parser(dn, &csrSubject);
836df8bdeb3Sjohnz 	if (kmfrv != KMF_OK) {
8378bab47abSJohn.Zolnowsky@Sun.COM 		(void) kmf_get_kmf_error_str(kmfrv, &err);
8388bab47abSJohn.Zolnowsky@Sun.COM 		cryptoerror(LOG_STDERR,
8398bab47abSJohn.Zolnowsky@Sun.COM 		    gettext("Error parsing subject name: %s\n"),
8408bab47abSJohn.Zolnowsky@Sun.COM 		    (err ? err : "unknown error"));
8418bab47abSJohn.Zolnowsky@Sun.COM 		free(err);
842df8bdeb3Sjohnz 		goto cleanup;
843df8bdeb3Sjohnz 	}
844df8bdeb3Sjohnz 
8458bab47abSJohn.Zolnowsky@Sun.COM 	SET_VALUE(kmf_set_csr_pubkey(kmfhandle, &pubk, &csr), "keypair");
846df8bdeb3Sjohnz 
8478bab47abSJohn.Zolnowsky@Sun.COM 	SET_VALUE(kmf_set_csr_version(&csr, 2), "version number");
848df8bdeb3Sjohnz 
8498bab47abSJohn.Zolnowsky@Sun.COM 	SET_VALUE(kmf_set_csr_subject(&csr, &csrSubject), "subject name");
850df8bdeb3Sjohnz 
8518bab47abSJohn.Zolnowsky@Sun.COM 	SET_VALUE(kmf_set_csr_sig_alg(&csr, sigAlg), "SignatureAlgorithm");
852df8bdeb3Sjohnz 
8538bab47abSJohn.Zolnowsky@Sun.COM 	if ((kmfrv = kmf_sign_csr(kmfhandle, &csr, &prik, &signedCsr)) ==
854df8bdeb3Sjohnz 	    KMF_OK) {
8558bab47abSJohn.Zolnowsky@Sun.COM 		kmfrv = kmf_create_csr_file(&signedCsr, KMF_FORMAT_PEM,
856df8bdeb3Sjohnz 		    cmd_info.cert);
857df8bdeb3Sjohnz 	}
858df8bdeb3Sjohnz 
859df8bdeb3Sjohnz cleanup:
8608bab47abSJohn.Zolnowsky@Sun.COM 	(void) kmf_free_kmf_key(kmfhandle, &prik);
8618bab47abSJohn.Zolnowsky@Sun.COM 	(void) kmf_free_data(&signedCsr);
8628bab47abSJohn.Zolnowsky@Sun.COM 	(void) kmf_free_signed_csr(&csr);
8638bab47abSJohn.Zolnowsky@Sun.COM 	(void) kmf_finalize(kmfhandle);
864df8bdeb3Sjohnz 
865df8bdeb3Sjohnz 	return (kmfrv);
866df8bdeb3Sjohnz }
867df8bdeb3Sjohnz 
868df8bdeb3Sjohnz 
869df8bdeb3Sjohnz #define	CN_MAX_LENGTH	64	/* Verisign implementation limit */
870df8bdeb3Sjohnz /*
871df8bdeb3Sjohnz  * Generate a certificate request into the file named cmd_info.cert
872df8bdeb3Sjohnz  */
873df8bdeb3Sjohnz /*ARGSUSED*/
874df8bdeb3Sjohnz static ret_t
do_cert_request(char * object)875df8bdeb3Sjohnz do_cert_request(char *object)
876df8bdeb3Sjohnz {
877df8bdeb3Sjohnz 	const char	 PartnerDNFMT[] =
878df8bdeb3Sjohnz 	    "CN=%s, "
879df8bdeb3Sjohnz 	    "OU=Class B, "
8809b009fc1SValerie Bubb Fenwick 	    "OU=Solaris Cryptographic Framework, "
881df8bdeb3Sjohnz 	    "OU=Partner Object Signing, "
882df8bdeb3Sjohnz 	    "O=Sun Microsystems Inc";
883df8bdeb3Sjohnz 	const char	 SunCDNFMT[] =
884df8bdeb3Sjohnz 	    "CN=%s, "
885df8bdeb3Sjohnz 	    "OU=Class B, "
8869b009fc1SValerie Bubb Fenwick 	    "OU=Solaris Cryptographic Framework, "
887df8bdeb3Sjohnz 	    "OU=Corporate Object Signing, "
888df8bdeb3Sjohnz 	    "O=Sun Microsystems Inc";
889df8bdeb3Sjohnz 	const char	 SunSDNFMT[] =
890df8bdeb3Sjohnz 	    "CN=%s, "
891df8bdeb3Sjohnz 	    "OU=Class B, "
8929b009fc1SValerie Bubb Fenwick 	    "OU=Solaris Signed Execution, "
893df8bdeb3Sjohnz 	    "OU=Corporate Object Signing, "
894df8bdeb3Sjohnz 	    "O=Sun Microsystems Inc";
895df8bdeb3Sjohnz 	const char	 *dnfmt = NULL;
896df8bdeb3Sjohnz 	char	cn[CN_MAX_LENGTH + 1];
897df8bdeb3Sjohnz 	char	*dn = NULL;
898df8bdeb3Sjohnz 	size_t	dn_len;
899df8bdeb3Sjohnz 	KMF_RETURN   kmfret;
900df8bdeb3Sjohnz 	cryptodebug("do_cert_request");
901df8bdeb3Sjohnz 
902df8bdeb3Sjohnz 	/*
903df8bdeb3Sjohnz 	 * Get the DN prefix from the user
904df8bdeb3Sjohnz 	 */
905df8bdeb3Sjohnz 	switch (cmd_info.internal_req) {
906df8bdeb3Sjohnz 	case 'c':
907df8bdeb3Sjohnz 		dnfmt = SunCDNFMT;
908df8bdeb3Sjohnz 		(void) fprintf(stdout, gettext(
909df8bdeb3Sjohnz 		    "Enter Sun Microsystems, Inc. Release name.\n"
910df8bdeb3Sjohnz 		    "This will be the prefix of the Certificate DN: "));
911df8bdeb3Sjohnz 		break;
912df8bdeb3Sjohnz 	case 's':
913df8bdeb3Sjohnz 		dnfmt = SunSDNFMT;
914df8bdeb3Sjohnz 		(void) fprintf(stdout, gettext(
915df8bdeb3Sjohnz 		    "Enter Sun Microsystems, Inc. Release name.\n"
916df8bdeb3Sjohnz 		    "This will be the prefix of the Certificate DN: "));
917df8bdeb3Sjohnz 		break;
918df8bdeb3Sjohnz 	default:
919df8bdeb3Sjohnz 		dnfmt = PartnerDNFMT;
920df8bdeb3Sjohnz 		(void) fprintf(stdout, gettext(
921df8bdeb3Sjohnz 		    "Enter Company Name / Stock Symbol"
922df8bdeb3Sjohnz 		    " or some other globally unique identifier.\n"
923df8bdeb3Sjohnz 		    "This will be the prefix of the Certificate DN: "));
924df8bdeb3Sjohnz 		break;
925df8bdeb3Sjohnz 	}
9265a45682cSRichard Lowe 	if ((fgets(cn, sizeof (cn), stdin) == NULL) || (cn[0] == '\n')) {
927df8bdeb3Sjohnz 		es_error(gettext("you must specify a Certificate DN prefix"));
928df8bdeb3Sjohnz 		return (EXIT_INVALID_ARG);
929df8bdeb3Sjohnz 	}
930df8bdeb3Sjohnz 
931df8bdeb3Sjohnz 	if (cn[strlen(cn) - 1] == '\n') {
932df8bdeb3Sjohnz 		cn[strlen(cn) - 1] = '\0';	/* chop trailing \n */
933df8bdeb3Sjohnz 	} else {
934df8bdeb3Sjohnz 		es_error(gettext("You must specify a Certificate DN prefix "
935df8bdeb3Sjohnz 		    "of no more than %d characters"), CN_MAX_LENGTH);
936df8bdeb3Sjohnz 		return (EXIT_INVALID_ARG);
937df8bdeb3Sjohnz 	}
938df8bdeb3Sjohnz 
939df8bdeb3Sjohnz 	/* Update DN string */
9409b009fc1SValerie Bubb Fenwick 	dn_len = strlen(cn) + strlen(dnfmt);
941df8bdeb3Sjohnz 	dn = malloc(dn_len + 1);
9429b009fc1SValerie Bubb Fenwick 	(void) snprintf(dn, dn_len, dnfmt, cn);
943df8bdeb3Sjohnz 
944df8bdeb3Sjohnz 	cryptodebug("Generating Certificate request for DN: %s", dn);
945df8bdeb3Sjohnz 	kmfret = create_csr(dn);
946df8bdeb3Sjohnz 	free(dn);
947df8bdeb3Sjohnz 	if (kmfret == KMF_OK)
948df8bdeb3Sjohnz 		return (EXIT_OKAY);
949df8bdeb3Sjohnz 	else
950df8bdeb3Sjohnz 		return (EXIT_CSR_FAILED);
951df8bdeb3Sjohnz }
952df8bdeb3Sjohnz 
953df8bdeb3Sjohnz static void
str_print(char * s)954df8bdeb3Sjohnz str_print(char *s)
955df8bdeb3Sjohnz {
956df8bdeb3Sjohnz 	if (s == NULL)
957df8bdeb3Sjohnz 		return;
958df8bdeb3Sjohnz 	(void) fprintf(stdout, "%s\n", s);
959df8bdeb3Sjohnz }
960df8bdeb3Sjohnz 
961df8bdeb3Sjohnz /*ARGSUSED*/
962df8bdeb3Sjohnz static ret_t
do_list(char * object)963df8bdeb3Sjohnz do_list(char *object)
964df8bdeb3Sjohnz {
965df8bdeb3Sjohnz 	ret_t	retval;
966df8bdeb3Sjohnz 
967df8bdeb3Sjohnz 	if (cmd_info.elfcnt > 0) {
968df8bdeb3Sjohnz 		ELFsign_status_t	elfstat;
969df8bdeb3Sjohnz 		struct filesignatures	*fssp = NULL;
970df8bdeb3Sjohnz 		size_t fs_len;
971df8bdeb3Sjohnz 		struct ELFsign_sig_info	*esip;
972df8bdeb3Sjohnz 
973df8bdeb3Sjohnz 		if ((retval = getelfobj(cmd_info.elfobj[0])) != EXIT_OKAY)
974df8bdeb3Sjohnz 			return (retval);
975df8bdeb3Sjohnz 		elfstat = elfsign_signatures(cmd_info.ess,
976df8bdeb3Sjohnz 		    &fssp, &fs_len, ES_GET);
977df8bdeb3Sjohnz 		if (elfstat == ELFSIGN_SUCCESS) {
978df8bdeb3Sjohnz 			retval = EXIT_OKAY;
979df8bdeb3Sjohnz 			if (elfsign_sig_info(fssp, &esip)) {
980df8bdeb3Sjohnz 				switch (cmd_info.field) {
981df8bdeb3Sjohnz 				case FLD_FORMAT:
982df8bdeb3Sjohnz 					str_print(esip->esi_format);
983df8bdeb3Sjohnz 					break;
984df8bdeb3Sjohnz 				case FLD_SIGNER:
985df8bdeb3Sjohnz 					str_print(esip->esi_signer);
986df8bdeb3Sjohnz 					break;
987df8bdeb3Sjohnz 				case FLD_TIME:
988df8bdeb3Sjohnz 					if (esip->esi_time == 0)
989df8bdeb3Sjohnz 						retval = EXIT_INVALID_ARG;
990df8bdeb3Sjohnz 					else
991df8bdeb3Sjohnz 						str_print(time_str(
992df8bdeb3Sjohnz 						    esip->esi_time));
993df8bdeb3Sjohnz 					break;
994df8bdeb3Sjohnz 				default:
995df8bdeb3Sjohnz 					retval = EXIT_INVALID_ARG;
996df8bdeb3Sjohnz 				}
997df8bdeb3Sjohnz 				elfsign_sig_info_free(esip);
998df8bdeb3Sjohnz 			}
999df8bdeb3Sjohnz 			free(fssp);
1000df8bdeb3Sjohnz 		} else
1001df8bdeb3Sjohnz 			retval = EXIT_VERIFY_FAILED_UNSIGNED;
1002df8bdeb3Sjohnz 		elfsign_end(cmd_info.ess);
1003df8bdeb3Sjohnz 	} else {
1004df8bdeb3Sjohnz 		ELFCert_t	cert;
1005df8bdeb3Sjohnz 		/*
1006df8bdeb3Sjohnz 		 * Initialize the ESS record here even though we are not
1007df8bdeb3Sjohnz 		 * actually opening any ELF files.
1008df8bdeb3Sjohnz 		 */
1009df8bdeb3Sjohnz 		if (elfsign_begin(NULL, ES_GET, &(cmd_info.ess)) !=
1010df8bdeb3Sjohnz 		    ELFSIGN_SUCCESS)
1011df8bdeb3Sjohnz 			return (EXIT_MEMORY_ERROR);
1012df8bdeb3Sjohnz 
1013df8bdeb3Sjohnz 		if (elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL,
1014df8bdeb3Sjohnz 		    &cert, cmd_info.es_action)) {
1015df8bdeb3Sjohnz 			retval = EXIT_OKAY;
1016df8bdeb3Sjohnz 			switch (cmd_info.field) {
1017df8bdeb3Sjohnz 			case FLD_SUBJECT:
1018df8bdeb3Sjohnz 				str_print(elfcertlib_getdn(cert));
1019df8bdeb3Sjohnz 				break;
1020df8bdeb3Sjohnz 			case FLD_ISSUER:
1021df8bdeb3Sjohnz 				str_print(elfcertlib_getissuer(cert));
1022df8bdeb3Sjohnz 				break;
1023df8bdeb3Sjohnz 			default:
1024df8bdeb3Sjohnz 				retval = EXIT_INVALID_ARG;
1025df8bdeb3Sjohnz 			}
1026df8bdeb3Sjohnz 			elfcertlib_releasecert(cmd_info.ess, cert);
1027df8bdeb3Sjohnz 		} else
1028df8bdeb3Sjohnz 			retval = EXIT_BAD_CERT;
1029df8bdeb3Sjohnz 		elfsign_end(cmd_info.ess);
1030df8bdeb3Sjohnz 	}
1031df8bdeb3Sjohnz 
1032df8bdeb3Sjohnz 	return (retval);
1033df8bdeb3Sjohnz }
1034df8bdeb3Sjohnz 
1035df8bdeb3Sjohnz static void
es_error(const char * fmt,...)1036df8bdeb3Sjohnz es_error(const char *fmt, ...)
1037df8bdeb3Sjohnz {
1038df8bdeb3Sjohnz 	char msgbuf[BUFSIZ];
1039df8bdeb3Sjohnz 	va_list	args;
1040df8bdeb3Sjohnz 
1041df8bdeb3Sjohnz 	va_start(args, fmt);
1042df8bdeb3Sjohnz 	(void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args);
1043df8bdeb3Sjohnz 	va_end(args);
1044df8bdeb3Sjohnz 	(void) fflush(stdout);
1045df8bdeb3Sjohnz 	cryptoerror(LOG_STDERR, "%s", msgbuf);
1046df8bdeb3Sjohnz 	(void) fflush(stderr);
1047df8bdeb3Sjohnz }
1048df8bdeb3Sjohnz 
1049df8bdeb3Sjohnz static char *
time_str(time_t t)1050df8bdeb3Sjohnz time_str(time_t t)
1051df8bdeb3Sjohnz {
1052df8bdeb3Sjohnz 	static char	buf[80];
1053df8bdeb3Sjohnz 	char		*bufp;
1054df8bdeb3Sjohnz 
1055df8bdeb3Sjohnz 	bufp = buf;
1056df8bdeb3Sjohnz 	if (strftime(buf, sizeof (buf), NULL, localtime(&t)) == 0)
1057df8bdeb3Sjohnz 		bufp = ctime(&t);
1058df8bdeb3Sjohnz 	return (bufp);
1059df8bdeb3Sjohnz }
1060df8bdeb3Sjohnz 
1061df8bdeb3Sjohnz static void
sig_info_print(struct ELFsign_sig_info * esip)1062df8bdeb3Sjohnz sig_info_print(struct ELFsign_sig_info *esip)
1063df8bdeb3Sjohnz {
1064df8bdeb3Sjohnz 	if (esip == NULL)
1065df8bdeb3Sjohnz 		return;
1066df8bdeb3Sjohnz 	(void) fprintf(stdout, gettext("format: %s.\n"), esip->esi_format);
1067df8bdeb3Sjohnz 	(void) fprintf(stdout, gettext("signer: %s.\n"), esip->esi_signer);
1068df8bdeb3Sjohnz 	if (esip->esi_time == 0)
1069df8bdeb3Sjohnz 		return;
1070df8bdeb3Sjohnz 	(void) fprintf(stdout, gettext("signed on: %s.\n"),
1071df8bdeb3Sjohnz 	    time_str(esip->esi_time));
1072df8bdeb3Sjohnz }
1073