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