comparison usr/src/cmd/cmd-crypto/elfsign/elfsign.c @ 0:c9caec207d52 b86

Initial porting based on b86
author Koji Uno <koji.uno@sun.com>
date Tue, 02 Jun 2009 18:56:50 +0900
parents
children 1a15d5aaf794
comparison
equal deleted inserted replaced
-1:000000000000 0:c9caec207d52
1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #pragma ident "@(#)elfsign.c 1.20 08/02/04 SMI"
28
29 /*
30 * Developer command for adding the signature section to an ELF object
31 * PSARC 2001/488
32 *
33 * DEBUG Information:
34 * This command uses the cryptodebug() function from libcryptoutil.
35 * Set SUNW_CRYPTO_DEBUG to stderr or syslog for all debug to go to auth.debug
36 */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <stdarg.h>
41 #include <limits.h>
42 #include <time.h>
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <libintl.h>
48 #include <locale.h>
49 #include <errno.h>
50 #include <strings.h>
51 #include <langinfo.h>
52
53 #include <cryptoutil.h>
54 #include <sys/crypto/elfsign.h>
55 #include <libelfsign.h>
56
57 #include <kmfapi.h>
58
59 #define SIGN "sign"
60 #define SIGN_OPTS "ac:e:F:k:P:T:v"
61 #define VERIFY "verify"
62 #define VERIFY_OPTS "c:e:v"
63 #define REQUEST "request"
64 #define REQUEST_OPTS "i:k:r:T:"
65 #define LIST "list"
66 #define LIST_OPTS "c:e:f:"
67
68 enum cmd_e {
69 ES_SIGN,
70 ES_VERIFY,
71 ES_REQUEST,
72 ES_LIST
73 };
74
75 enum field_e {
76 FLD_UNKNOWN,
77 FLD_SUBJECT,
78 FLD_ISSUER,
79 FLD_FORMAT,
80 FLD_SIGNER,
81 FLD_TIME
82 };
83
84 #define MIN_ARGS 3 /* The minimum # args to do anything */
85 #define ES_DEFAULT_KEYSIZE 1024
86
87 static struct {
88 enum cmd_e cmd; /* sub command: sign | verify | request */
89 char *cert; /* -c <certificate_file> | */
90 /* -r <certificate_request_file> */
91 char **elfobj; /* -e <elf_object> */
92 int elfcnt;
93 enum ES_ACTION es_action;
94 ELFsign_t ess; /* libelfsign opaque "state" */
95 int extracnt;
96 enum field_e field; /* -f <field> */
97 char internal_req; /* Sun internal certificate request */
98 char *pinpath; /* -P <pin> */
99 char *privpath; /* -k <private_key> */
100 char *token_label; /* -T <token_label> */
101 boolean_t verbose; /* chatty output */
102 } cmd_info;
103
104 enum ret_e {
105 EXIT_OKAY,
106 EXIT_INVALID_ARG,
107 EXIT_VERIFY_FAILED,
108 EXIT_CANT_OPEN_ELF_OBJECT,
109 EXIT_BAD_CERT,
110 EXIT_BAD_PRIVATEKEY,
111 EXIT_SIGN_FAILED,
112 EXIT_VERIFY_FAILED_UNSIGNED,
113 EXIT_CSR_FAILED,
114 EXIT_MEMORY_ERROR
115 };
116
117 struct field_s {
118 char *name;
119 enum field_e field;
120 } fields[] = {
121 { "subject", FLD_SUBJECT },
122 { "issuer", FLD_ISSUER },
123 { "format", FLD_FORMAT },
124 { "signer", FLD_SIGNER },
125 { "time", FLD_TIME },
126 NULL, 0
127 };
128
129 typedef enum ret_e ret_t;
130
131 static void usage(void);
132 static ret_t getelfobj(char *);
133 static char *getpin(void);
134 static ret_t do_sign(char *);
135 static ret_t do_verify(char *);
136 static ret_t do_cert_request(char *);
137 static ret_t do_gen_esa(char *);
138 static ret_t do_list(char *);
139 static void es_error(const char *fmt, ...);
140 static char *time_str(time_t t);
141 static void sig_info_print(struct ELFsign_sig_info *esip);
142
143 int
144 main(int argc, char **argv)
145 {
146 extern char *optarg;
147 char *scmd = NULL;
148 char *opts; /* The set of flags for cmd */
149 int errflag = 0; /* We had an options parse error */
150 char c; /* current getopts flag */
151 ret_t (*action)(char *); /* Function pointer for the action */
152 ret_t ret;
153
154 (void) setlocale(LC_ALL, "");
155 #if !defined(TEXT_DOMAIN) /* Should be defiend by cc -D */
156 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
157 #endif
158 (void) textdomain(TEXT_DOMAIN);
159
160 cryptodebug_init("elfsign");
161
162 if (argc < MIN_ARGS) {
163 es_error(gettext("invalid number of arguments"));
164 usage();
165 return (EXIT_INVALID_ARG);
166 }
167
168 scmd = argv[1];
169 cmd_info.cert = NULL;
170 cmd_info.elfobj = NULL;
171 cmd_info.elfcnt = 0;
172 cmd_info.es_action = ES_GET;
173 cmd_info.ess = NULL;
174 cmd_info.extracnt = 0;
175 cmd_info.field = FLD_UNKNOWN;
176 cmd_info.internal_req = '\0';
177 cmd_info.pinpath = NULL;
178 cmd_info.privpath = NULL;
179 cmd_info.token_label = NULL;
180 cmd_info.verbose = B_FALSE;
181
182 if (strcmp(scmd, SIGN) == 0) {
183 cmd_info.cmd = ES_SIGN;
184 opts = SIGN_OPTS;
185 cryptodebug("cmd=sign opts=%s", opts);
186 action = do_sign;
187 cmd_info.es_action = ES_UPDATE_RSA_SHA1;
188 } else if (strcmp(scmd, VERIFY) == 0) {
189 cmd_info.cmd = ES_VERIFY;
190 opts = VERIFY_OPTS;
191 cryptodebug("cmd=verify opts=%s", opts);
192 action = do_verify;
193 } else if (strcmp(scmd, REQUEST) == 0) {
194 cmd_info.cmd = ES_REQUEST;
195 opts = REQUEST_OPTS;
196 cryptodebug("cmd=request opts=%s", opts);
197 action = do_cert_request;
198 } else if (strcmp(scmd, LIST) == 0) {
199 cmd_info.cmd = ES_LIST;
200 opts = LIST_OPTS;
201 cryptodebug("cmd=list opts=%s", opts);
202 action = do_list;
203 } else {
204 es_error(gettext("Unknown sub-command: %s"),
205 scmd);
206 usage();
207 return (EXIT_INVALID_ARG);
208 }
209
210 /*
211 * Note: There is no need to check that optarg isn't NULL
212 * because getopt does that for us.
213 */
214 while (!errflag && (c = getopt(argc - 1, argv + 1, opts)) != EOF) {
215 if (strchr("ceFihkPr", c) != NULL)
216 cryptodebug("c=%c, '%s'", c, optarg);
217 else
218 cryptodebug("c=%c", c);
219
220 switch (c) {
221 case 'a':
222 /* not a normal sign operation, change the action */
223 cmd_info.es_action = ES_GET;
224 action = do_gen_esa;
225 break;
226 case 'c':
227 cmd_info.cert = optarg;
228 break;
229 case 'e':
230 cmd_info.elfcnt++;
231 cmd_info.elfobj = (char **)realloc(cmd_info.elfobj,
232 sizeof (char *) * cmd_info.elfcnt);
233 if (cmd_info.elfobj == NULL) {
234 es_error(gettext(
235 "Too many elf objects specified."));
236 return (EXIT_INVALID_ARG);
237 }
238 cmd_info.elfobj[cmd_info.elfcnt - 1] = optarg;
239 break;
240 case 'f':
241 {
242 struct field_s *fp;
243 cmd_info.field = FLD_UNKNOWN;
244 for (fp = fields; fp->name != NULL; fp++) {
245 if (strcasecmp(optarg, fp->name) == 0) {
246 cmd_info.field = fp->field;
247 break;
248 }
249 }
250 if (cmd_info.field == FLD_UNKNOWN) {
251 cryptodebug("Invalid field option");
252 errflag++;
253 }
254 }
255 break;
256 case 'F':
257 if (strcasecmp(optarg, ES_FMT_RSA_MD5_SHA1) == 0)
258 cmd_info.es_action = ES_UPDATE_RSA_MD5_SHA1;
259 else if (strcasecmp(optarg, ES_FMT_RSA_SHA1) == 0)
260 cmd_info.es_action = ES_UPDATE_RSA_SHA1;
261 else {
262 cryptodebug("Invalid format option");
263 errflag++;
264 }
265 break;
266 case 'i': /* Undocumented internal Sun use only */
267 cmd_info.internal_req = *optarg;
268 break;
269 case 'k':
270 cmd_info.privpath = optarg;
271 if (cmd_info.token_label != NULL ||
272 cmd_info.pinpath != NULL)
273 errflag++;
274 break;
275 case 'P':
276 cmd_info.pinpath = optarg;
277 if (cmd_info.privpath != NULL)
278 errflag++;
279 break;
280 case 'r':
281 cmd_info.cert = optarg;
282 break;
283 case 'T':
284 cmd_info.token_label = optarg;
285 if (cmd_info.privpath != NULL)
286 errflag++;
287 break;
288 case 'v':
289 cmd_info.verbose = B_TRUE;
290 break;
291 default:
292 errflag++;
293 }
294 }
295
296 optind++; /* we skipped over subcommand */
297 cmd_info.extracnt = argc - optind;
298
299 if (cmd_info.extracnt != 0 &&
300 cmd_info.cmd != ES_SIGN && cmd_info.cmd != ES_VERIFY) {
301 cryptodebug("Extra arguments, optind=%d, argc=%d",
302 optind, argc);
303 errflag++;
304 }
305
306 switch (cmd_info.cmd) {
307 case ES_VERIFY:
308 if (cmd_info.elfcnt + argc - optind == 0) {
309 cryptodebug("Missing elfobj");
310 errflag++;
311 }
312 break;
313
314 case ES_SIGN:
315 if (((cmd_info.privpath == NULL) &&
316 (cmd_info.token_label == NULL)) ||
317 (cmd_info.cert == NULL) ||
318 (cmd_info.elfcnt + argc - optind == 0)) {
319 cryptodebug("Missing privpath|token_label/cert/elfobj");
320 errflag++;
321 }
322 break;
323
324 case ES_REQUEST:
325 if (((cmd_info.privpath == NULL) &&
326 (cmd_info.token_label == NULL)) ||
327 (cmd_info.cert == NULL)) {
328 cryptodebug("Missing privpath|token_label/certreq");
329 errflag++;
330 }
331 break;
332 case ES_LIST:
333 if ((cmd_info.cert != NULL) == (cmd_info.elfcnt > 0)) {
334 cryptodebug("Neither or both of cert/elfobj");
335 errflag++;
336 }
337 break;
338 }
339
340 if (errflag) {
341 usage();
342 return (EXIT_INVALID_ARG);
343 }
344
345 switch (cmd_info.cmd) {
346 case ES_REQUEST:
347 case ES_LIST:
348 ret = action(NULL);
349 break;
350 default:
351 {
352 int i;
353 ret_t iret;
354
355 ret = EXIT_OKAY;
356 iret = EXIT_OKAY;
357 for (i = 0; i < cmd_info.elfcnt &&
358 (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) {
359 iret = action(cmd_info.elfobj[i]);
360 if (iret > ret)
361 ret = iret;
362 }
363 for (i = optind; i < argc &&
364 (ret == EXIT_OKAY || cmd_info.cmd != ES_SIGN); i++) {
365 iret = action(argv[i]);
366 if (iret > ret)
367 ret = iret;
368 }
369 break;
370 }
371 }
372
373 if (cmd_info.elfobj != NULL)
374 free(cmd_info.elfobj);
375
376 return (ret);
377 }
378
379
380 static void
381 usage(void)
382 {
383 /* BEGIN CSTYLED */
384 (void) fprintf(stderr, gettext(
385 "usage:\n"
386 "\telfsign sign [-a] [-v] [-e <elf_object>] -c <certificate_file>\n"
387 "\t\t[-F <format>] -k <private_key_file> [elf_object]..."
388 "\n"
389 "\telfsign sign [-a] [-v] [-e <elf_object>] -c <certificate_file>\n"
390 "\t\t[-F <format>] -T <token_label> [-P <pin_file>] [elf_object]..."
391 "\n\n"
392 "\telfsign verify [-v] [-c <certificate_file>] [-e <elf_object>]\n"
393 "\t\t[elf_object]..."
394 "\n\n"
395 "\telfsign request -r <certificate_request_file> -k <private_key_file>"
396 "\n"
397 "\telfsign request -r <certificate_request_file> -T <token_label>"
398 "\n\n"
399 "\telfsign list -f field -c <certificate_file>"
400 "\n"
401 "\telfsign list -f field -e <elf_object>"
402 "\n"));
403 /* END CSTYLED */
404 }
405
406 static ret_t
407 getelfobj(char *elfpath)
408 {
409 ELFsign_status_t estatus;
410 ret_t ret = EXIT_SIGN_FAILED;
411
412 estatus = elfsign_begin(elfpath, cmd_info.es_action, &(cmd_info.ess));
413 switch (estatus) {
414 case ELFSIGN_SUCCESS:
415 case ELFSIGN_RESTRICTED:
416 ret = EXIT_OKAY;
417 break;
418 case ELFSIGN_INVALID_ELFOBJ:
419 es_error(gettext(
420 "Unable to open %s as an ELF object."),
421 elfpath);
422 ret = EXIT_CANT_OPEN_ELF_OBJECT;
423 break;
424 default:
425 es_error(gettext("unexpected failure: %d"), estatus);
426 if (cmd_info.cmd == ES_SIGN) {
427 ret = EXIT_SIGN_FAILED;
428 } else if (cmd_info.cmd == ES_VERIFY) {
429 ret = EXIT_VERIFY_FAILED;
430 }
431 }
432
433 return (ret);
434 }
435
436 static ret_t
437 setcertpath(void)
438 {
439 ELFsign_status_t estatus;
440 ret_t ret = EXIT_SIGN_FAILED;
441
442 if (cmd_info.cert == NULL)
443 return (EXIT_OKAY);
444 estatus = elfsign_setcertpath(cmd_info.ess, cmd_info.cert);
445 switch (estatus) {
446 case ELFSIGN_SUCCESS:
447 ret = EXIT_OKAY;
448 break;
449 case ELFSIGN_INVALID_CERTPATH:
450 if (cmd_info.cert != NULL) {
451 es_error(gettext("Unable to open %s as a certificate."),
452 cmd_info.cert);
453 }
454 ret = EXIT_BAD_CERT;
455 break;
456 default:
457 es_error(gettext("unusable certificate: %d"), cmd_info.cert);
458 if (cmd_info.cmd == ES_SIGN) {
459 ret = EXIT_SIGN_FAILED;
460 } else if (cmd_info.cmd == ES_VERIFY) {
461 ret = EXIT_VERIFY_FAILED;
462 }
463 }
464
465 return (ret);
466 }
467
468 /*
469 * getpin - return pointer to token PIN in static storage
470 */
471 static char *
472 getpin(void)
473 {
474 static char pinbuf[PASS_MAX + 1];
475 char *pp;
476 FILE *pinfile;
477
478 if (cmd_info.pinpath == NULL)
479 return (getpassphrase(
480 gettext("Enter PIN for PKCS#11 token: ")));
481 if ((pinfile = fopen(cmd_info.pinpath, "r")) == NULL) {
482 es_error(gettext("failed to open %s."),
483 cmd_info.pinpath);
484 return (NULL);
485 }
486
487 pp = fgets(pinbuf, sizeof (pinbuf), pinfile);
488 (void) fclose(pinfile);
489 if (pp == NULL) {
490 es_error(gettext("failed to read PIN from %s."),
491 cmd_info.pinpath);
492 return (NULL);
493 }
494 pp = &pinbuf[strlen(pinbuf) - 1];
495 if (*pp == '\n')
496 *pp = '\0';
497 return (pinbuf);
498 }
499
500 /*
501 * Add the .SUNW_signature sections for the ELF signature
502 */
503 static ret_t
504 do_sign(char *object)
505 {
506 ret_t ret;
507 ELFsign_status_t elfstat;
508 struct filesignatures *fssp = NULL;
509 size_t fs_len;
510 uchar_t sig[SIG_MAX_LENGTH];
511 size_t sig_len = SIG_MAX_LENGTH;
512 uchar_t hash[SIG_MAX_LENGTH];
513 size_t hash_len = SIG_MAX_LENGTH;
514 ELFCert_t cert = NULL;
515 char *dn;
516 size_t dn_len;
517
518 cryptodebug("do_sign");
519 if ((ret = getelfobj(object)) != EXIT_OKAY)
520 return (ret);
521
522 if (cmd_info.token_label &&
523 !elfcertlib_settoken(cmd_info.ess, cmd_info.token_label)) {
524 es_error(gettext("Unable to access token: %s"),
525 cmd_info.token_label);
526 ret = EXIT_SIGN_FAILED;
527 goto cleanup;
528 }
529
530 if ((ret = setcertpath()) != EXIT_OKAY)
531 goto cleanup;
532
533 if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert,
534 cmd_info.es_action)) {
535 es_error(gettext("Unable to load certificate: %s"),
536 cmd_info.cert);
537 ret = EXIT_BAD_CERT;
538 goto cleanup;
539 }
540
541 if (cmd_info.privpath != NULL) {
542 if (!elfcertlib_loadprivatekey(cmd_info.ess, cert,
543 cmd_info.privpath)) {
544 es_error(gettext("Unable to load private key: %s"),
545 cmd_info.privpath);
546 ret = EXIT_BAD_PRIVATEKEY;
547 goto cleanup;
548 }
549 } else {
550 char *pin = getpin();
551 if (pin == NULL) {
552 es_error(gettext("Unable to get PIN"));
553 ret = EXIT_BAD_PRIVATEKEY;
554 goto cleanup;
555 }
556 if (!elfcertlib_loadtokenkey(cmd_info.ess, cert,
557 cmd_info.token_label, pin)) {
558 es_error(gettext("Unable to access private key "
559 "in token %s"), cmd_info.token_label);
560 ret = EXIT_BAD_PRIVATEKEY;
561 goto cleanup;
562 }
563 }
564
565 /*
566 * Get the DN from the certificate.
567 */
568 if ((dn = elfcertlib_getdn(cert)) == NULL) {
569 es_error(gettext("Unable to find DN in certificate %s"),
570 cmd_info.cert);
571 ret = EXIT_SIGN_FAILED;
572 goto cleanup;
573 }
574 dn_len = strlen(dn);
575 cryptodebug("DN = %s", dn);
576
577 elfstat = elfsign_signatures(cmd_info.ess, &fssp, &fs_len, ES_GET);
578 if (elfstat != ELFSIGN_SUCCESS) {
579 if (elfstat != ELFSIGN_NOTSIGNED) {
580 es_error(gettext("Unable to retrieve existing "
581 "signature block in %s"), object);
582 ret = EXIT_SIGN_FAILED;
583 goto cleanup;
584 }
585 fssp = NULL;
586 /*
587 * force creation and naming of signature section
588 * so the hash doesn't change
589 */
590 if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len,
591 cmd_info.es_action) != ELFSIGN_SUCCESS) {
592 es_error(gettext("Unable to insert "
593 "signature block into %s"), object);
594 ret = EXIT_SIGN_FAILED;
595 goto cleanup;
596 }
597 }
598
599 bzero(hash, sizeof (hash));
600 if (elfsign_hash(cmd_info.ess, hash, &hash_len) != ELFSIGN_SUCCESS) {
601 es_error(gettext("Unable to calculate hash of ELF object %s"),
602 object);
603 ret = EXIT_SIGN_FAILED;
604 goto cleanup;
605 }
606
607 bzero(sig, sizeof (sig));
608 if (!elfcertlib_sign(cmd_info.ess, cert,
609 hash, hash_len, sig, &sig_len)) {
610 es_error(gettext("Unable to sign %s using key from %s"),
611 object, cmd_info.privpath ?
612 cmd_info.privpath : cmd_info.token_label);
613 ret = EXIT_SIGN_FAILED;
614 goto cleanup;
615 }
616
617 { /* DEBUG START */
618 const int sigstr_len = sizeof (char) * sig_len * 2 + 1;
619 char *sigstr = malloc(sigstr_len);
620
621 tohexstr(sig, sig_len, sigstr, sigstr_len);
622 cryptodebug("sig value is: %s", sigstr);
623 free(sigstr);
624 } /* DEBUG END */
625
626 fssp = elfsign_insert_dso(cmd_info.ess, fssp,
627 dn, dn_len, sig, sig_len, NULL, 0);
628 if (fssp == NULL) {
629 es_error(gettext("Unable to prepare signature for %s"),
630 object);
631 ret = EXIT_SIGN_FAILED;
632 goto cleanup;
633 }
634 if (elfsign_signatures(cmd_info.ess, &fssp, &fs_len,
635 cmd_info.es_action) != ELFSIGN_SUCCESS) {
636 es_error(gettext("Unable to update %s: with signature"),
637 object);
638 ret = EXIT_SIGN_FAILED;
639 goto cleanup;
640 }
641 if (cmd_info.verbose || (cmd_info.elfcnt + cmd_info.extracnt) > 1) {
642 (void) fprintf(stdout,
643 gettext("elfsign: %s signed successfully.\n"),
644 object);
645 }
646 if (cmd_info.verbose) {
647 struct ELFsign_sig_info *esip;
648
649 if (elfsign_sig_info(fssp, &esip)) {
650 sig_info_print(esip);
651 elfsign_sig_info_free(esip);
652 }
653 }
654
655 ret = EXIT_OKAY;
656
657 cleanup:
658 free(fssp);
659 bzero(sig, sig_len);
660 bzero(hash, hash_len);
661
662 if (cert != NULL)
663 elfcertlib_releasecert(cmd_info.ess, cert);
664 if (cmd_info.ess != NULL)
665 elfsign_end(cmd_info.ess);
666
667 return (ret);
668 }
669
670 #define ESA_ERROR(str, esa_file) { \
671 int realerrno = errno; \
672 es_error(gettext(str), esa_file, strerror(realerrno)); \
673 goto clean_esa; \
674 }
675
676 /*
677 * Generate the elfsign activation file (.esa) for this request.
678 * The .esa file should contain the signature of main binary
679 * signed with an unlimited certificate, the DN and its own signature.
680 *
681 * The format is as follows:
682 * -----------------------------
683 * A | main signature length |
684 * -----------------------------
685 * B | main signature (copy of |
686 * | signature from original |
687 * | limited-use binary |
688 * -----------------------------
689 * C | signing DN length |
690 * -----------------------------
691 * D | signing DN |
692 * -----------------------------
693 * E | esa signature length |
694 * -----------------------------
695 * F | esa signature = |
696 * | RSA(HASH(A||B) |
697 * -----------------------------
698 * (lengths are in the same endianness as the original object)
699 *
700 * cmd_info.ess set for the main binary is correct here, since this
701 * is the only elf object we are actually dealing with during the .esa
702 * generation.
703 */
704 static ret_t
705 do_gen_esa(char *object)
706 {
707 ret_t ret;
708
709 /* variables used for signing and writing to .esa file */
710 char *elfobj_esa;
711 size_t elfobj_esa_len;
712 int esa_fd;
713 mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH;
714 uchar_t *esa_buf = NULL;
715 size_t esa_buf_len = 0;
716 uchar_t hash[SIG_MAX_LENGTH], *hash_ptr = hash;
717 size_t hash_len = SIG_MAX_LENGTH;
718 uchar_t esa_sig[SIG_MAX_LENGTH];
719 size_t esa_sig_len = SIG_MAX_LENGTH;
720 struct filesignatures *fssp = NULL;
721 size_t fslen;
722 ELFCert_t cert = NULL;
723 char *dn;
724 size_t dn_len;
725 uchar_t tmp_buf[sizeof (uint32_t)];
726 int realerrno = 0;
727
728 /*
729 * variables used for finding information on signer of main
730 * elfobject.
731 */
732 uchar_t orig_signature[SIG_MAX_LENGTH];
733 size_t orig_sig_len = sizeof (orig_signature);
734
735 cryptodebug("do_gen_esa");
736 if ((ret = getelfobj(object)) != EXIT_OKAY)
737 return (ret);
738 ret = EXIT_SIGN_FAILED;
739
740 /*
741 * Find the certificate we need to sign the activation file with.
742 */
743 if (!elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL, &cert,
744 cmd_info.es_action)) {
745 es_error(gettext("Unable to load certificate: %s"),
746 cmd_info.cert);
747 ret = EXIT_BAD_CERT;
748 goto clean_esa;
749 }
750
751 if (cmd_info.privpath != NULL) {
752 if (!elfcertlib_loadprivatekey(cmd_info.ess, cert,
753 cmd_info.privpath)) {
754 es_error(gettext("Unable to load private key: %s"),
755 cmd_info.privpath);
756 ret = EXIT_BAD_PRIVATEKEY;
757 goto clean_esa;
758 }
759 } else {
760 char *pin = getpin();
761
762 if (pin == NULL) {
763 cryptoerror(LOG_STDERR, gettext("Unable to get PIN"));
764 ret = EXIT_BAD_PRIVATEKEY;
765 goto clean_esa;
766 }
767 if (!elfcertlib_loadtokenkey(cmd_info.ess, cert,
768 cmd_info.token_label, pin)) {
769 es_error(gettext("Unable to access private key "
770 "in token %s"), cmd_info.token_label);
771 ret = EXIT_BAD_PRIVATEKEY;
772 goto clean_esa;
773 }
774 }
775
776 /*
777 * Get the DN from the certificate.
778 */
779 if ((dn = elfcertlib_getdn(cert)) == NULL) {
780 es_error(gettext("Unable to find DN in certifiate %s"),
781 cmd_info.cert);
782 goto clean_esa;
783 }
784 dn_len = strlen(dn);
785 cryptodebug("DN = %s", dn);
786
787 /*
788 * Make sure they are not trying to sign .esa file with a
789 * limited certificate.
790 */
791 if (strstr(dn, USAGELIMITED) != NULL) {
792 es_error(gettext("Activation file must be signed with a "
793 "certficate without %s."), USAGELIMITED);
794 goto clean_esa;
795 }
796
797 /*
798 * Find information in the associated elfobject that will
799 * be needed to generate the activation file.
800 */
801 if (elfsign_signatures(cmd_info.ess, &fssp, &fslen, ES_GET) !=
802 ELFSIGN_SUCCESS) {
803 es_error(gettext("%s must be signed first, before an "
804 "associated activation file can be created."),
805 object);
806 goto clean_esa;
807 }
808 if (elfsign_extract_sig(cmd_info.ess, fssp,
809 orig_signature, &orig_sig_len) == FILESIG_UNKNOWN) {
810 es_error(gettext("elfsign can not create "
811 "an associated activation file for the "
812 "signature format of %s."),
813 object);
814 goto clean_esa;
815 }
816 { /* DEBUG START */
817 const int sigstr_len = orig_sig_len * 2 + 1;
818 char *sigstr = malloc(sigstr_len);
819
820 tohexstr(orig_signature, orig_sig_len, sigstr, sigstr_len);
821 cryptodebug("signature value is: %s", sigstr);
822 cryptodebug("sig size value is: %d", orig_sig_len);
823 free(sigstr);
824 } /* DEBUG END */
825
826 esa_buf_len = sizeof (uint32_t) + orig_sig_len;
827 esa_buf = malloc(esa_buf_len);
828 if (esa_buf == NULL) {
829 es_error(gettext("Unable to allocate memory for .esa buffer"));
830 goto clean_esa;
831 }
832
833 /*
834 * Write eventual contents of .esa file to a temporary
835 * buffer, so we can sign it before writing out to
836 * the file.
837 */
838 elfsign_buffer_len(cmd_info.ess, &orig_sig_len, esa_buf, ES_UPDATE);
839 (void) memcpy(esa_buf + sizeof (uint32_t), orig_signature,
840 orig_sig_len);
841
842 if (elfsign_hash_esa(cmd_info.ess, esa_buf, esa_buf_len,
843 &hash_ptr, &hash_len) != ELFSIGN_SUCCESS) {
844 es_error(gettext("Unable to calculate activation hash"));
845 goto clean_esa;
846 }
847
848 /*
849 * sign the buffer for the .esa file
850 */
851 if (!elfcertlib_sign(cmd_info.ess, cert,
852 hash_ptr, hash_len, esa_sig, &esa_sig_len)) {
853 es_error(gettext("Unable to sign .esa data using key from %s"),
854 cmd_info.privpath ?
855 cmd_info.privpath : cmd_info.token_label);
856 goto clean_esa;
857 }
858
859 { /* DEBUG START */
860 const int sigstr_len = esa_sig_len * 2 + 1;
861 char *sigstr = malloc(sigstr_len);
862
863 tohexstr(esa_sig, esa_sig_len, sigstr, sigstr_len);
864 cryptodebug("esa signature value is: %s", sigstr);
865 cryptodebug("esa size value is: %d", esa_sig_len);
866 free(sigstr);
867 } /* DEBUG END */
868
869 /*
870 * Create the empty activation file once we know
871 * we are working with the good data.
872 */
873 elfobj_esa_len = strlen(object) + ESA_LEN + 1;
874 elfobj_esa = malloc(elfobj_esa_len);
875
876 if (elfobj_esa == NULL) {
877 es_error(gettext("Unable to allocate buffer for esa filename"));
878 goto clean_esa;
879 }
880
881 (void) strlcpy(elfobj_esa, object, elfobj_esa_len);
882 (void) strlcat(elfobj_esa, ESA, elfobj_esa_len);
883
884 cryptodebug("Creating .esa file: %s", elfobj_esa);
885
886 if ((esa_fd = open(elfobj_esa, O_WRONLY|O_CREAT|O_EXCL, mode)) == -1) {
887 ESA_ERROR("Unable to create activation file: %s. %s.",
888 elfobj_esa);
889 }
890
891 if (write(esa_fd, esa_buf, esa_buf_len) != esa_buf_len) {
892 ESA_ERROR("Unable to write contents to %s. %s.",
893 elfobj_esa);
894 }
895
896 { /* DEBUG START */
897 const int sigstr_len = dn_len * 2 + 1;
898 char *sigstr = malloc(sigstr_len);
899
900 tohexstr((uchar_t *)dn, dn_len, sigstr, sigstr_len);
901 cryptodebug("dn value is: %s", sigstr);
902 cryptodebug("dn size value is: %d", dn_len);
903 free(sigstr);
904 } /* DEBUG END */
905
906 elfsign_buffer_len(cmd_info.ess, &dn_len, tmp_buf, ES_UPDATE);
907 if (write(esa_fd, tmp_buf, sizeof (tmp_buf)) != sizeof (tmp_buf)) {
908 ESA_ERROR("Unable to write dn_len to %s. %s.", elfobj_esa);
909 }
910
911 if (write(esa_fd, dn, dn_len) != dn_len) {
912 ESA_ERROR("Unable to write dn to %s. %s.", elfobj_esa);
913 }
914
915 elfsign_buffer_len(cmd_info.ess, &esa_sig_len, tmp_buf, ES_UPDATE);
916 if (write(esa_fd, tmp_buf, sizeof (tmp_buf)) != sizeof (tmp_buf)) {
917 ESA_ERROR("Unable to write .esa signature len to %s. %s.",
918 elfobj_esa);
919 }
920
921 if (write(esa_fd, esa_sig, esa_sig_len) != esa_sig_len) {
922 realerrno = errno;
923 es_error(gettext("Unable to write .esa signature. %s."),
924 strerror(realerrno));
925 goto clean_esa;
926 }
927
928 ret = EXIT_OKAY;
929
930 clean_esa:
931 free(fssp);
932 if (esa_fd != -1)
933 (void) close(esa_fd);
934
935 if (esa_buf != NULL)
936 free(esa_buf);
937
938 bzero(esa_sig, esa_sig_len);
939
940 if (cert != NULL)
941 elfcertlib_releasecert(cmd_info.ess, cert);
942 if (cmd_info.ess != NULL)
943 elfsign_end(cmd_info.ess);
944
945 return (ret);
946 }
947
948 /*
949 * Verify the signature of the object
950 * This subcommand is intended to be used by developers during their build
951 * processes. Therefore we can not assume that the certificate is in
952 * /etc/crypto/certs so we must use the path we got from the commandline.
953 */
954 static ret_t
955 do_verify(char *object)
956 {
957 ELFsign_status_t res;
958 struct ELFsign_sig_info *esip;
959 ret_t retval;
960
961 cryptodebug("do_verify");
962 if ((retval = getelfobj(object)) != EXIT_OKAY)
963 return (retval);
964
965 if ((retval = setcertpath()) != EXIT_OKAY) {
966 elfsign_end(cmd_info.ess);
967 return (retval);
968 }
969
970 res = elfsign_verify_signature(cmd_info.ess, &esip);
971 switch (res) {
972 case ELFSIGN_SUCCESS:
973 (void) fprintf(stdout,
974 gettext("elfsign: verification of %s passed.\n"),
975 object);
976 if (cmd_info.verbose)
977 sig_info_print(esip);
978 retval = EXIT_OKAY;
979 break;
980 case ELFSIGN_RESTRICTED:
981 (void) fprintf(stdout,
982 gettext("elfsign: verification of %s passed, "
983 "but restricted.\n"), object);
984 if (cmd_info.verbose)
985 sig_info_print(esip);
986 retval = EXIT_OKAY;
987 break;
988 case ELFSIGN_FAILED:
989 case ELFSIGN_INVALID_CERTPATH:
990 es_error(gettext("verification of %s failed."),
991 object);
992 if (cmd_info.verbose)
993 sig_info_print(esip);
994 retval = EXIT_VERIFY_FAILED;
995 break;
996 case ELFSIGN_NOTSIGNED:
997 es_error(gettext("no signature found in %s."),
998 object);
999 retval = EXIT_VERIFY_FAILED_UNSIGNED;
1000 break;
1001 default:
1002 es_error(gettext("unexpected failure attempting verification "
1003 "of %s."), object);
1004 retval = EXIT_VERIFY_FAILED_UNSIGNED;
1005 break;
1006 }
1007
1008 if (esip != NULL)
1009 elfsign_sig_info_free(esip);
1010 if (cmd_info.ess != NULL)
1011 elfsign_end(cmd_info.ess);
1012 return (retval);
1013 }
1014
1015 #define SET_VALUE(f, s) \
1016 kmfrv = f; \
1017 if (kmfrv != KMF_OK) { \
1018 char *e = NULL; \
1019 (void) KMF_GetKMFErrorString(kmfrv, &e); \
1020 cryptoerror(LOG_STDERR, \
1021 gettext("Failed to %s: %s\n"), \
1022 s, (e ? e : "unknown error")); \
1023 if (e) free(e); \
1024 goto cleanup; \
1025 }
1026
1027 static KMF_RETURN
1028 create_csr(char *dn)
1029 {
1030 KMF_RETURN kmfrv = KMF_OK;
1031 KMF_HANDLE_T kmfhandle = NULL;
1032 KMF_CREATEKEYPAIR_PARAMS kp_params;
1033 KMF_KEY_HANDLE pubk, prik;
1034 KMF_X509_NAME csrSubject;
1035 KMF_CSR_DATA csr;
1036 KMF_ALGORITHM_INDEX sigAlg = KMF_ALGID_MD5WithRSA;
1037 KMF_DATA signedCsr = { NULL, 0 };
1038 KMF_CONFIG_PARAMS config;
1039 char *err;
1040
1041 if ((kmfrv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
1042 (void) KMF_GetKMFErrorString(kmfrv, &err);
1043 cryptoerror(LOG_STDERR,
1044 gettext("Error initializing KMF: %s\n"),
1045 (err ? err : "unknown error"));
1046 if (err)
1047 free(err);
1048 return (kmfrv);
1049 }
1050 (void) memset(&csr, 0, sizeof (csr));
1051 (void) memset(&csrSubject, 0, sizeof (csrSubject));
1052 (void) memset(&kp_params, 0, sizeof (kp_params));
1053
1054 if (cmd_info.privpath != NULL) {
1055 kp_params.kstype = KMF_KEYSTORE_OPENSSL;
1056 kp_params.sslparms.keyfile = cmd_info.privpath;
1057 kp_params.sslparms.format = KMF_FORMAT_ASN1;
1058 } else if (cmd_info.token_label != NULL) {
1059
1060 /* Get a PIN to store the private key in the token */
1061 char *pin = getpin();
1062
1063 if (pin == NULL) {
1064 (void) KMF_Finalize(kmfhandle);
1065 return (KMF_ERR_AUTH_FAILED);
1066 }
1067
1068 kp_params.kstype = KMF_KEYSTORE_PK11TOKEN;
1069 kp_params.cred.cred = pin;
1070 kp_params.cred.credlen = strlen(pin);
1071
1072 (void) memset(&config, 0, sizeof (config));
1073 config.kstype = KMF_KEYSTORE_PK11TOKEN;
1074 config.pkcs11config.label = cmd_info.token_label;
1075 config.pkcs11config.readonly = FALSE;
1076 kmfrv = KMF_ConfigureKeystore(kmfhandle, &config);
1077 if (kmfrv != KMF_OK) {
1078 goto cleanup;
1079 }
1080 }
1081
1082 /* Create the RSA keypair */
1083 kp_params.keytype = KMF_RSA;
1084 kp_params.keylength = ES_DEFAULT_KEYSIZE;
1085
1086 kmfrv = KMF_CreateKeypair(kmfhandle, &kp_params, &prik, &pubk);
1087 if (kmfrv != KMF_OK) {
1088 (void) KMF_GetKMFErrorString(kmfrv, &err);
1089 if (err != NULL) {
1090 cryptoerror(LOG_STDERR,
1091 gettext("Create RSA keypair failed: %s"), err);
1092 free(err);
1093 }
1094 goto cleanup;
1095 }
1096
1097 kmfrv = KMF_DNParser(dn, &csrSubject);
1098 if (kmfrv != KMF_OK) {
1099 (void) KMF_GetKMFErrorString(kmfrv, &err);
1100 if (err != NULL) {
1101 cryptoerror(LOG_STDERR,
1102 gettext("Error parsing subject name: %s\n"), err);
1103 free(err);
1104 }
1105 goto cleanup;
1106 }
1107
1108 SET_VALUE(KMF_SetCSRPubKey(kmfhandle, &pubk, &csr), "keypair");
1109
1110 SET_VALUE(KMF_SetCSRVersion(&csr, 2), "version number");
1111
1112 SET_VALUE(KMF_SetCSRSubjectName(&csr, &csrSubject), "subject name");
1113
1114 SET_VALUE(KMF_SetCSRSignatureAlgorithm(&csr, sigAlg),
1115 "SignatureAlgorithm");
1116
1117 if ((kmfrv = KMF_SignCSR(kmfhandle, &csr, &prik, &signedCsr)) ==
1118 KMF_OK) {
1119 kmfrv = KMF_CreateCSRFile(&signedCsr, KMF_FORMAT_PEM,
1120 cmd_info.cert);
1121 }
1122
1123 cleanup:
1124 (void) KMF_FreeKMFKey(kmfhandle, &prik);
1125 (void) KMF_FreeData(&signedCsr);
1126 (void) KMF_FreeSignedCSR(&csr);
1127 (void) KMF_Finalize(kmfhandle);
1128
1129 return (kmfrv);
1130 }
1131
1132 static boolean_t
1133 is_restricted(void)
1134 {
1135 char nr[80]; /* Non-retail provider? big buffer for l10n */
1136 char *yeschar = nl_langinfo(YESSTR);
1137 char *nochar = nl_langinfo(NOSTR);
1138
1139 /*
1140 * Find out if user will need an activation file.
1141 * These questions cover cases #1 and #2 from the Jumbo Export
1142 * Control case. The logic of these questions should not be modified
1143 * without consulting the jumbo case, unless there is a new
1144 * export case or a change in export/import regulations for Sun
1145 * and Sun customers.
1146 * Case #3 should be covered in the developer documentation.
1147 */
1148 /* BEGIN CSTYLED */
1149 (void) fprintf(stdout, gettext("\n"
1150 "The government of the United States of America restricts the export of \n"
1151 "\"open cryptographic interfaces\", also known as \"crypto-with-a-hole\".\n"
1152 "Due to this restriction, all providers for the Solaris cryptographic\n"
1153 "framework must be signed, regardless of the country of origin.\n\n"));
1154
1155 (void) fprintf(stdout, gettext(
1156 "The terms \"retail\" and \"non-retail\" refer to export classifications \n"
1157 "for products manufactured in the USA. These terms define the portion of the\n"
1158 "world where the product may be shipped. Roughly speaking, \"retail\" is \n"
1159 "worldwide (minus certain excluded nations) and \"non-retail\" is domestic \n"
1160 "only (plus some highly favored nations). If your provider is subject to\n"
1161 "USA export control, then you must obtain an export approval (classification)\n"
1162 "from the government of the USA before exporting your provider. It is\n"
1163 "critical that you specify the obtained (or expected, when used during \n"
1164 "development) classification to the following questions so that your provider\n"
1165 "will be appropriately signed.\n\n"));
1166
1167 for (;;) {
1168 (void) fprintf(stdout, gettext(
1169 "Do you have retail export approval for use without restrictions based \n"
1170 "on the caller (for example, IPsec)? [Yes/No] "));
1171 /* END CSTYLED */
1172
1173 (void) fflush(stdout);
1174
1175 (void) fgets(nr, sizeof (nr), stdin);
1176 if (nr == NULL)
1177 goto demand_answer;
1178
1179 nr[strlen(nr) - 1] = '\0';
1180
1181 if (strncasecmp(nochar, nr, 1) == 0) {
1182 /* BEGIN CSTYLED */
1183 (void) fprintf(stdout, gettext("\n"
1184 "If you have non-retail export approval for unrestricted use of your provider\n"
1185 "by callers, are you also planning to receive retail approval by restricting \n"
1186 "which export sensitive callers (for example, IPsec) may use your \n"
1187 "provider? [Yes/No] "));
1188 /* END CSTYLED */
1189
1190 (void) fflush(stdout);
1191
1192 (void) fgets(nr, sizeof (nr), stdin);
1193
1194 /*
1195 * flush standard input so any remaining text
1196 * does not affect next read.
1197 */
1198 (void) fflush(stdin);
1199
1200 if (nr == NULL)
1201 goto demand_answer;
1202
1203 nr[strlen(nr) - 1] = '\0';
1204
1205 if (strncasecmp(nochar, nr, 1) == 0) {
1206 return (B_FALSE);
1207 } else if (strncasecmp(yeschar, nr, 1) == 0) {
1208 return (B_TRUE);
1209 } else
1210 goto demand_answer;
1211
1212 } else if (strncasecmp(yeschar, nr, 1) == 0) {
1213 return (B_FALSE);
1214 }
1215
1216 demand_answer:
1217 (void) fprintf(stdout,
1218 gettext("You must specify an answer.\n\n"));
1219 }
1220 }
1221
1222 #define CN_MAX_LENGTH 64 /* Verisign implementation limit */
1223 /*
1224 * Generate a certificate request into the file named cmd_info.cert
1225 */
1226 /*ARGSUSED*/
1227 static ret_t
1228 do_cert_request(char *object)
1229 {
1230 const char PartnerDNFMT[] =
1231 "CN=%s, "
1232 "OU=Class B, "
1233 "%sOU=Solaris Cryptographic Framework, "
1234 "OU=Partner Object Signing, "
1235 "O=Sun Microsystems Inc";
1236 const char SunCDNFMT[] =
1237 "CN=%s, "
1238 "OU=Class B, "
1239 "%sOU=Solaris Cryptographic Framework, "
1240 "OU=Corporate Object Signing, "
1241 "O=Sun Microsystems Inc";
1242 const char SunSDNFMT[] =
1243 "CN=%s, "
1244 "OU=Class B, "
1245 "%sOU=Solaris Signed Execution, "
1246 "OU=Corporate Object Signing, "
1247 "O=Sun Microsystems Inc";
1248 const char *dnfmt = NULL;
1249 char cn[CN_MAX_LENGTH + 1];
1250 char *dn = NULL;
1251 size_t dn_len;
1252 char *restriction = "";
1253 KMF_RETURN kmfret;
1254 cryptodebug("do_cert_request");
1255
1256 /*
1257 * Get the DN prefix from the user
1258 */
1259 switch (cmd_info.internal_req) {
1260 case 'c':
1261 dnfmt = SunCDNFMT;
1262 (void) fprintf(stdout, gettext(
1263 "Enter Sun Microsystems, Inc. Release name.\n"
1264 "This will be the prefix of the Certificate DN: "));
1265 break;
1266 case 's':
1267 dnfmt = SunSDNFMT;
1268 (void) fprintf(stdout, gettext(
1269 "Enter Sun Microsystems, Inc. Release name.\n"
1270 "This will be the prefix of the Certificate DN: "));
1271 break;
1272 default:
1273 dnfmt = PartnerDNFMT;
1274 (void) fprintf(stdout, gettext(
1275 "Enter Company Name / Stock Symbol"
1276 " or some other globally unique identifier.\n"
1277 "This will be the prefix of the Certificate DN: "));
1278 break;
1279 }
1280
1281 (void) fgets(cn, sizeof (cn), stdin);
1282 if ((cn == NULL) || (cn[0] == '\n')) {
1283 es_error(gettext("you must specify a Certificate DN prefix"));
1284 return (EXIT_INVALID_ARG);
1285 }
1286
1287 if (cn[strlen(cn) - 1] == '\n') {
1288 cn[strlen(cn) - 1] = '\0'; /* chop trailing \n */
1289 } else {
1290 es_error(gettext("You must specify a Certificate DN prefix "
1291 "of no more than %d characters"), CN_MAX_LENGTH);
1292 return (EXIT_INVALID_ARG);
1293 }
1294
1295 /*
1296 * determine if there is an export restriction
1297 */
1298 switch (cmd_info.internal_req) {
1299 case 's':
1300 restriction = "";
1301 break;
1302 default:
1303 restriction = is_restricted() ? USAGELIMITED ", " : "";
1304 break;
1305 }
1306
1307 /* Update DN string */
1308 dn_len = strlen(cn) + strlen(dnfmt) + strlen(restriction);
1309 dn = malloc(dn_len + 1);
1310 (void) snprintf(dn, dn_len, dnfmt, cn, restriction);
1311
1312 cryptodebug("Generating Certificate request for DN: %s", dn);
1313 kmfret = create_csr(dn);
1314 free(dn);
1315 if (kmfret == KMF_OK)
1316 return (EXIT_OKAY);
1317 else
1318 return (EXIT_CSR_FAILED);
1319 }
1320
1321 static void
1322 str_print(char *s)
1323 {
1324 if (s == NULL)
1325 return;
1326 (void) fprintf(stdout, "%s\n", s);
1327 }
1328
1329 /*ARGSUSED*/
1330 static ret_t
1331 do_list(char *object)
1332 {
1333 ret_t retval;
1334
1335 if (cmd_info.elfcnt > 0) {
1336 ELFsign_status_t elfstat;
1337 struct filesignatures *fssp = NULL;
1338 size_t fs_len;
1339 struct ELFsign_sig_info *esip;
1340
1341 if ((retval = getelfobj(cmd_info.elfobj[0])) != EXIT_OKAY)
1342 return (retval);
1343 elfstat = elfsign_signatures(cmd_info.ess,
1344 &fssp, &fs_len, ES_GET);
1345 if (elfstat == ELFSIGN_SUCCESS) {
1346 retval = EXIT_OKAY;
1347 if (elfsign_sig_info(fssp, &esip)) {
1348 switch (cmd_info.field) {
1349 case FLD_FORMAT:
1350 str_print(esip->esi_format);
1351 break;
1352 case FLD_SIGNER:
1353 str_print(esip->esi_signer);
1354 break;
1355 case FLD_TIME:
1356 if (esip->esi_time == 0)
1357 retval = EXIT_INVALID_ARG;
1358 else
1359 str_print(time_str(
1360 esip->esi_time));
1361 break;
1362 default:
1363 retval = EXIT_INVALID_ARG;
1364 }
1365 elfsign_sig_info_free(esip);
1366 }
1367 free(fssp);
1368 } else
1369 retval = EXIT_VERIFY_FAILED_UNSIGNED;
1370 elfsign_end(cmd_info.ess);
1371 } else {
1372 ELFCert_t cert;
1373 /*
1374 * Initialize the ESS record here even though we are not
1375 * actually opening any ELF files.
1376 */
1377 if (elfsign_begin(NULL, ES_GET, &(cmd_info.ess)) !=
1378 ELFSIGN_SUCCESS)
1379 return (EXIT_MEMORY_ERROR);
1380
1381 if (elfcertlib_getcert(cmd_info.ess, cmd_info.cert, NULL,
1382 &cert, cmd_info.es_action)) {
1383 retval = EXIT_OKAY;
1384 switch (cmd_info.field) {
1385 case FLD_SUBJECT:
1386 str_print(elfcertlib_getdn(cert));
1387 break;
1388 case FLD_ISSUER:
1389 str_print(elfcertlib_getissuer(cert));
1390 break;
1391 default:
1392 retval = EXIT_INVALID_ARG;
1393 }
1394 elfcertlib_releasecert(cmd_info.ess, cert);
1395 } else
1396 retval = EXIT_BAD_CERT;
1397 elfsign_end(cmd_info.ess);
1398 }
1399
1400 return (retval);
1401 }
1402
1403 static void
1404 es_error(const char *fmt, ...)
1405 {
1406 char msgbuf[BUFSIZ];
1407 va_list args;
1408
1409 va_start(args, fmt);
1410 (void) vsnprintf(msgbuf, sizeof (msgbuf), fmt, args);
1411 va_end(args);
1412 (void) fflush(stdout);
1413 cryptoerror(LOG_STDERR, "%s", msgbuf);
1414 (void) fflush(stderr);
1415 }
1416
1417 static char *
1418 time_str(time_t t)
1419 {
1420 static char buf[80];
1421 char *bufp;
1422
1423 bufp = buf;
1424 if (strftime(buf, sizeof (buf), NULL, localtime(&t)) == 0)
1425 bufp = ctime(&t);
1426 return (bufp);
1427 }
1428
1429 static void
1430 sig_info_print(struct ELFsign_sig_info *esip)
1431 {
1432 if (esip == NULL)
1433 return;
1434 (void) fprintf(stdout, gettext("format: %s.\n"), esip->esi_format);
1435 (void) fprintf(stdout, gettext("signer: %s.\n"), esip->esi_signer);
1436 if (esip->esi_time == 0)
1437 return;
1438 (void) fprintf(stdout, gettext("signed on: %s.\n"),
1439 time_str(esip->esi_time));
1440 }