xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/signcsr.c (revision 374ae87f60894937d3c6e53ec4a739188e702ea5)
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  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * This file implements the sign CSR operation for this tool.
30  */
31 
32 #include <stdio.h>
33 #include <errno.h>
34 #include <string.h>
35 #include <cryptoutil.h>
36 #include <security/cryptoki.h>
37 #include "common.h"
38 
39 #include <kmfapi.h>
40 #define	SET_VALUE(f, s) \
41 	rv = f; \
42 	if (rv != KMF_OK) { \
43 		cryptoerror(LOG_STDERR, \
44 		    gettext("Failed to set %s: 0x%02x\n"), s, rv); \
45 		goto cleanup; \
46 	}
47 
48 
49 static int
50 read_csrdata(KMF_HANDLE_T handle, char *csrfile, KMF_CSR_DATA *csrdata)
51 {
52 	KMF_RETURN rv = KMF_OK;
53 	KMF_ENCODE_FORMAT csrfmt;
54 	KMF_DATA csrfiledata = {NULL, 0};
55 	KMF_DATA rawcsr = {NULL, 0};
56 
57 	rv = kmf_get_file_format(csrfile, &csrfmt);
58 	if (rv != KMF_OK)
59 		return (rv);
60 
61 	rv = kmf_read_input_file(handle, csrfile, &csrfiledata);
62 	if (rv != KMF_OK)
63 		return (rv);
64 
65 	if (csrfmt == KMF_FORMAT_PEM) {
66 		rv = kmf_pem_to_der(csrfiledata.Data, csrfiledata.Length,
67 		    &rawcsr.Data, (int *)&rawcsr.Length);
68 		if (rv != KMF_OK)
69 			return (rv);
70 
71 		kmf_free_data(&csrfiledata);
72 	} else {
73 		rawcsr.Data = csrfiledata.Data;
74 		rawcsr.Length = csrfiledata.Length;
75 	}
76 
77 	rv = kmf_decode_csr(handle, &rawcsr, csrdata);
78 	kmf_free_data(&rawcsr);
79 
80 	return (rv);
81 }
82 
83 static int
84 build_cert_from_csr(KMF_CSR_DATA *csrdata,
85 	KMF_X509_CERTIFICATE *signedCert,
86 	KMF_BIGINT *serial,
87 	uint32_t ltime,
88 	char *issuer, char *subject,
89 	char *altname,
90 	KMF_GENERALNAMECHOICES alttype,
91 	int altcrit,
92 	uint16_t kubits,
93 	int kucrit,
94 	EKU_LIST *ekulist)
95 {
96 	KMF_RETURN rv = KMF_OK;
97 	KMF_X509_NAME issuerDN, subjectDN;
98 
99 	/*
100 	 * If the CSR is ok, now we can generate the final certificate.
101 	 */
102 	(void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE));
103 	(void) memset(&issuerDN, 0, sizeof (issuerDN));
104 	(void) memset(&subjectDN, 0, sizeof (subjectDN));
105 
106 	SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number");
107 
108 	SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number");
109 
110 	SET_VALUE(kmf_set_cert_validity(signedCert, NULL, ltime),
111 	    "validity time");
112 
113 	if (issuer) {
114 		if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) {
115 			cryptoerror(LOG_STDERR,
116 			    gettext("Issuer name cannot be parsed\n"));
117 			return (PK_ERR_USAGE);
118 		}
119 		SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN),
120 		    "Issuer Name");
121 	}
122 	if (subject) {
123 		if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) {
124 			cryptoerror(LOG_STDERR,
125 			    gettext("Subject name cannot be parsed\n"));
126 			return (PK_ERR_USAGE);
127 		}
128 		SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN),
129 		    "Subject Name");
130 	} else {
131 		signedCert->certificate.subject = csrdata->csr.subject;
132 	}
133 
134 	signedCert->certificate.subjectPublicKeyInfo =
135 	    csrdata->csr.subjectPublicKeyInfo;
136 
137 	signedCert->certificate.extensions = csrdata->csr.extensions;
138 
139 	signedCert->certificate.signature =
140 	    csrdata->signature.algorithmIdentifier;
141 
142 	if (kubits != 0) {
143 		SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
144 		    "KeyUsage");
145 	}
146 	if (altname != NULL) {
147 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
148 		    altcrit, alttype, altname), "subjectAltName");
149 	}
150 	if (ekulist != NULL) {
151 		int i;
152 		for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) {
153 			SET_VALUE(kmf_add_cert_eku(signedCert,
154 			    &ekulist->ekulist[i],
155 			    ekulist->critlist[i]), "Extended Key Usage");
156 		}
157 	}
158 cleanup:
159 	if (issuer != NULL)
160 		kmf_free_dn(&issuerDN);
161 	if (subject != NULL)
162 		kmf_free_dn(&subjectDN);
163 
164 	return (rv);
165 }
166 
167 static int
168 pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert,
169 	KMF_KEY_HANDLE *key, KMF_DATA *outdata)
170 {
171 	KMF_RETURN rv;
172 	int numattr;
173 	KMF_ATTRIBUTE attrlist[4];
174 
175 	numattr = 0;
176 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
177 	    &key->kstype, sizeof (KMF_KEYSTORE_TYPE));
178 	numattr++;
179 
180 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
181 	    key, sizeof (KMF_KEY_HANDLE_ATTR));
182 	numattr++;
183 
184 	/* cert data that is to be signed */
185 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
186 	    cert, sizeof (KMF_X509_CERTIFICATE));
187 	numattr++;
188 
189 	/* output buffer for the signed cert */
190 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
191 	    outdata, sizeof (KMF_DATA));
192 	numattr++;
193 
194 	if ((rv = kmf_sign_cert(handle, numattr, attrlist)) != KMF_OK) {
195 		cryptoerror(LOG_STDERR,
196 		    gettext("Failed to sign certificate.\n"));
197 		return (rv);
198 	}
199 
200 	return (rv);
201 }
202 
203 static int
204 pk_signcsr_files(KMF_HANDLE_T handle,
205 	char *signkey,
206 	char *csrfile,
207 	KMF_BIGINT *serial,
208 	char *certfile,
209 	char *issuer,
210 	char *subject,
211 	char *altname,
212 	KMF_GENERALNAMECHOICES alttype,
213 	int altcrit,
214 	uint16_t kubits,
215 	int kucrit,
216 	EKU_LIST *ekulist,
217 	uint32_t ltime,
218 	KMF_ENCODE_FORMAT fmt)
219 {
220 	KMF_RETURN rv = KMF_OK;
221 	KMF_CSR_DATA csrdata;
222 	KMF_ATTRIBUTE attrlist[16];
223 	KMF_X509_CERTIFICATE signedCert;
224 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
225 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
226 	KMF_KEY_HANDLE cakey;
227 	KMF_DATA certdata = {NULL, 0};
228 	int numattr, count;
229 
230 	rv = read_csrdata(handle, csrfile, &csrdata);
231 	if (rv != KMF_OK) {
232 		cryptoerror(LOG_STDERR,
233 		    gettext("Error reading CSR data\n"));
234 		return (rv);
235 	}
236 
237 	/* verify the signature first */
238 	numattr = 0;
239 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
240 	    &csrdata, sizeof (csrdata));
241 	numattr++;
242 
243 	rv = kmf_verify_csr(handle, numattr, attrlist);
244 	if (rv != KMF_OK) {
245 		cryptoerror(LOG_STDERR, gettext("CSR signature "
246 		    "verification failed.\n"));
247 		goto cleanup;
248 	}
249 
250 	rv = build_cert_from_csr(&csrdata, &signedCert, serial, ltime,
251 	    issuer, subject, altname, alttype, altcrit, kubits,
252 	    kucrit, ekulist);
253 
254 	if (rv != KMF_OK)
255 		goto cleanup;
256 
257 	/*
258 	 * Find the signing key.
259 	 */
260 	(void) memset(&cakey, 0, sizeof (cakey));
261 
262 	numattr = 0;
263 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
264 	    &kstype, sizeof (kstype));
265 	numattr++;
266 
267 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
268 	    signkey, strlen(signkey));
269 	numattr++;
270 
271 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
272 	    &keyclass, sizeof (keyclass));
273 	numattr++;
274 
275 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
276 	    &cakey, sizeof (cakey));
277 	numattr++;
278 
279 	count = 1;
280 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
281 	    &count, sizeof (count));
282 	numattr++;
283 
284 	rv = kmf_find_key(handle, numattr, attrlist);
285 	if (rv != KMF_OK) {
286 		cryptoerror(LOG_STDERR, gettext(
287 		    "Error finding CA signing key\n"));
288 		goto cleanup;
289 	}
290 
291 	rv = pk_sign_cert(handle, &signedCert, &cakey, &certdata);
292 	if (rv != KMF_OK) {
293 		cryptoerror(LOG_STDERR, gettext(
294 		    "Error signing certificate.\n"));
295 		goto cleanup;
296 	}
297 
298 	rv = kmf_create_cert_file(&certdata, fmt, certfile);
299 
300 cleanup:
301 	kmf_free_signed_csr(&csrdata);
302 	kmf_free_data(&certdata);
303 	kmf_free_kmf_key(handle, &cakey);
304 	return (rv);
305 }
306 
307 static int
308 pk_signcsr_pk11_nss(KMF_HANDLE_T handle,
309 	KMF_KEYSTORE_TYPE kstype,
310 	char *dir, char *prefix,
311 	char *token, KMF_CREDENTIAL *cred,
312 	char *signkey, char *csrfile,
313 	KMF_BIGINT *serial, char *certfile, char *issuer, char *subject,
314 	char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit,
315 	uint16_t kubits, int kucrit,
316 	EKU_LIST *ekulist, uint32_t ltime,
317 	KMF_ENCODE_FORMAT fmt, int store, char *outlabel)
318 {
319 	KMF_RETURN rv = KMF_OK;
320 	KMF_DATA outcert = {NULL, 0};
321 	KMF_CSR_DATA csrdata;
322 	KMF_KEY_HANDLE casignkey;
323 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
324 	int numattr = 0;
325 	int keys = 1;
326 	KMF_ATTRIBUTE attrlist[16];
327 	KMF_X509_CERTIFICATE signedCert;
328 	boolean_t token_bool = B_TRUE;
329 	boolean_t private_bool = B_TRUE;
330 
331 	rv = read_csrdata(handle, csrfile, &csrdata);
332 	if (rv != KMF_OK) {
333 		cryptoerror(LOG_STDERR,
334 		    gettext("Error reading CSR data\n"));
335 		return (rv);
336 	}
337 
338 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
339 		rv = select_token(handle, token, FALSE);
340 	} else if (kstype == KMF_KEYSTORE_NSS) {
341 		rv = configure_nss(handle, dir, prefix);
342 	}
343 
344 	/* verify the signature first */
345 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
346 	    &csrdata, sizeof (csrdata));
347 	numattr++;
348 
349 	rv = kmf_verify_csr(handle, numattr, attrlist);
350 	if (rv != KMF_OK) {
351 		cryptoerror(LOG_STDERR, gettext("CSR signature "
352 		    "verification failed.\n"));
353 		goto cleanup;
354 	}
355 
356 	rv = build_cert_from_csr(&csrdata,
357 	    &signedCert, serial, ltime,
358 	    issuer, subject, altname,
359 	    alttype, altcrit, kubits,
360 	    kucrit, ekulist);
361 
362 	if (rv != KMF_OK)
363 		goto cleanup;
364 
365 	/*
366 	 * Find the signing key.
367 	 */
368 	numattr = 0;
369 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
370 	    &kstype, sizeof (kstype));
371 	numattr++;
372 	if (kstype == KMF_KEYSTORE_NSS) {
373 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
374 		    token, strlen(token));
375 		numattr++;
376 	}
377 
378 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, signkey,
379 	    strlen(signkey));
380 	numattr++;
381 
382 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
383 	    &private_bool, sizeof (private_bool));
384 	numattr++;
385 
386 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
387 	    &token_bool, sizeof (token_bool));
388 	numattr++;
389 
390 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
391 	    &keyclass, sizeof (keyclass));
392 	numattr++;
393 
394 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
395 	    cred, sizeof (KMF_CREDENTIAL_ATTR));
396 	numattr++;
397 
398 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
399 	    &keys, sizeof (keys));
400 	numattr++;
401 
402 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
403 	    &casignkey, sizeof (casignkey));
404 	numattr++;
405 
406 	rv = kmf_find_key(handle, numattr, attrlist);
407 	if (rv != KMF_OK) {
408 		cryptoerror(LOG_STDERR,
409 		    gettext("Failed to find signing key\n"));
410 		goto cleanup;
411 	}
412 
413 	/*
414 	 * If we found the key, now we can sign the cert.
415 	 */
416 	rv = pk_sign_cert(handle, &signedCert, &casignkey, &outcert);
417 	if (rv != KMF_OK) {
418 		cryptoerror(LOG_STDERR, gettext(
419 		    "Error signing certificate.\n"));
420 		goto cleanup;
421 	}
422 
423 	/*
424 	 * Store it on the token if the user asked for it.
425 	 */
426 	if (store) {
427 		numattr = 0;
428 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
429 		    &kstype, sizeof (kstype));
430 		numattr++;
431 
432 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
433 		    &outcert, sizeof (KMF_DATA));
434 		numattr++;
435 
436 		if (outlabel != NULL) {
437 			kmf_set_attr_at_index(attrlist, numattr,
438 			    KMF_CERT_LABEL_ATTR,
439 			    outlabel, strlen(outlabel));
440 			numattr++;
441 		}
442 
443 		if (kstype == KMF_KEYSTORE_NSS) {
444 			if (token != NULL)
445 				kmf_set_attr_at_index(attrlist, numattr,
446 				    KMF_TOKEN_LABEL_ATTR,
447 				    token, strlen(token));
448 			numattr++;
449 		}
450 
451 		rv = kmf_store_cert(handle, numattr, attrlist);
452 		if (rv != KMF_OK) {
453 			display_error(handle, rv,
454 			    gettext("Failed to store cert "
455 			    "on PKCS#11 token.\n"));
456 			rv = KMF_OK;
457 			/* Not fatal, we can still write it to a file. */
458 		}
459 	}
460 	rv = kmf_create_cert_file(&outcert, fmt, certfile);
461 
462 cleanup:
463 	kmf_free_signed_csr(&csrdata);
464 	kmf_free_data(&outcert);
465 	kmf_free_kmf_key(handle, &casignkey);
466 
467 	return (rv);
468 }
469 
470 /*
471  * sign a CSR and generate an x509v3 certificate file.
472  */
473 int
474 pk_signcsr(int argc, char *argv[])
475 {
476 	int			opt;
477 	extern int		optind_av;
478 	extern char		*optarg_av;
479 	char			*token_spec = NULL;
480 	char			*subject = NULL;
481 	char			*issuer = NULL;
482 	char			*dir = NULL;
483 	char			*prefix = NULL;
484 	char			*csrfile = NULL;
485 	char			*serstr = NULL;
486 	char			*ekustr = NULL;
487 	char			*kustr = NULL;
488 	char			*format = NULL;
489 	char			*storestr = NULL;
490 	char			*altname = NULL;
491 	char			*certfile = NULL;
492 	char			*lifetime = NULL;
493 	char			*signkey = NULL;
494 	char			*outlabel = NULL;
495 	uint32_t		ltime = 365 * 24 * 60 * 60; /* 1 Year */
496 	int			store = 0;
497 	uint16_t		kubits = 0;
498 	int			altcrit = 0, kucrit = 0;
499 	KMF_BIGINT		serial = { NULL, 0 };
500 	EKU_LIST		*ekulist = NULL;
501 	KMF_KEYSTORE_TYPE	kstype = 0;
502 	KMF_RETURN		rv = KMF_OK;
503 	KMF_HANDLE_T		kmfhandle = NULL;
504 	KMF_CREDENTIAL		tokencred = {NULL, 0};
505 	KMF_GENERALNAMECHOICES	alttype = 0;
506 	KMF_ENCODE_FORMAT	fmt = KMF_FORMAT_PEM;
507 
508 	/* Parse command line options.  Do NOT i18n/l10n. */
509 	while ((opt = getopt_av(argc, argv,
510 	    "k:(keystore)c:(csr)T:(token)d:(dir)"
511 	    "p:(prefix)S:(serial)s:(subject)a:(altname)"
512 	    "t:(store)F:(format)K:(keyusage)l:(signkey)"
513 	    "L:(lifetime)e:(eku)i:(issuer)"
514 	    "n:(outlabel)o:(outcert)")) != EOF) {
515 		if (EMPTYSTRING(optarg_av))
516 			return (PK_ERR_USAGE);
517 		switch (opt) {
518 			case 'k':
519 				if (kstype != 0)
520 					return (PK_ERR_USAGE);
521 				kstype = KS2Int(optarg_av);
522 				if (kstype == 0)
523 					return (PK_ERR_USAGE);
524 				break;
525 			case 't':
526 				if (storestr != NULL)
527 					return (PK_ERR_USAGE);
528 				storestr = optarg_av;
529 				store = yn_to_int(optarg_av);
530 				if (store == -1)
531 					return (PK_ERR_USAGE);
532 				break;
533 			case 'a':
534 				if (altname)
535 					return (PK_ERR_USAGE);
536 				altname = optarg_av;
537 				break;
538 			case 's':
539 				if (subject)
540 					return (PK_ERR_USAGE);
541 				subject = optarg_av;
542 				break;
543 			case 'i':
544 				if (issuer)
545 					return (PK_ERR_USAGE);
546 				issuer = optarg_av;
547 				break;
548 			case 'd':
549 				if (dir)
550 					return (PK_ERR_USAGE);
551 				dir = optarg_av;
552 				break;
553 			case 'p':
554 				if (prefix)
555 					return (PK_ERR_USAGE);
556 				prefix = optarg_av;
557 				break;
558 			case 'S':
559 				if (serstr != NULL)
560 					return (PK_ERR_USAGE);
561 				serstr = optarg_av;
562 				break;
563 			case 'c':
564 				if (csrfile)
565 					return (PK_ERR_USAGE);
566 				csrfile = optarg_av;
567 				break;
568 			case 'T':	/* token specifier */
569 				if (token_spec)
570 					return (PK_ERR_USAGE);
571 				token_spec = optarg_av;
572 				break;
573 			case 'l':	/* object with specific label */
574 				if (signkey)
575 					return (PK_ERR_USAGE);
576 				signkey = optarg_av;
577 				break;
578 			case 'e':
579 				if (ekustr != NULL)
580 					return (PK_ERR_USAGE);
581 				ekustr = optarg_av;
582 				break;
583 			case 'K':
584 				if (kustr != NULL)
585 					return (PK_ERR_USAGE);
586 				kustr = optarg_av;
587 				break;
588 			case 'F':
589 				if (format != NULL)
590 					return (PK_ERR_USAGE);
591 				format = optarg_av;
592 				break;
593 			case 'o':
594 				if (certfile != NULL)
595 					return (PK_ERR_USAGE);
596 				certfile = optarg_av;
597 				break;
598 			case 'L':
599 				if (lifetime != NULL)
600 					return (PK_ERR_USAGE);
601 				lifetime = optarg_av;
602 				break;
603 			case 'n':
604 				if (outlabel != NULL)
605 					return (PK_ERR_USAGE);
606 				outlabel = optarg_av;
607 				break;
608 			default:
609 				return (PK_ERR_USAGE);
610 		}
611 	}
612 	/* No additional args allowed. */
613 	argc -= optind_av;
614 	argv += optind_av;
615 	if (argc)
616 		return (PK_ERR_USAGE);
617 
618 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
619 		return (rv);
620 	}
621 
622 	/* Assume keystore = PKCS#11 if not specified. */
623 	if (kstype == 0)
624 		kstype = KMF_KEYSTORE_PK11TOKEN;
625 
626 	if (signkey == NULL) {
627 		(void) fprintf(stderr, gettext("The signing key label "
628 		    "or filename was not specified\n"));
629 		return (PK_ERR_USAGE);
630 	}
631 	if (csrfile == NULL) {
632 		(void) fprintf(stderr, gettext("The CSR filename was not"
633 		    " specified\n"));
634 		return (PK_ERR_USAGE);
635 	}
636 	if (certfile == NULL) {
637 		(void) fprintf(stderr, gettext("The output certificate file "
638 		    "was not specified\n"));
639 		return (PK_ERR_USAGE);
640 	}
641 	if (issuer == NULL) {
642 		(void) fprintf(stderr, gettext("The issuer DN "
643 		    "was not specified\n"));
644 		return (PK_ERR_USAGE);
645 	}
646 	if (lifetime != NULL) {
647 		if (Str2Lifetime(lifetime, &ltime) != 0) {
648 			cryptoerror(LOG_STDERR,
649 			    gettext("Error parsing lifetime string\n"));
650 			return (PK_ERR_USAGE);
651 		}
652 	}
653 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
654 		token_spec = PK_DEFAULT_PK11TOKEN;
655 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
656 		token_spec = DEFAULT_NSS_TOKEN;
657 	}
658 
659 	if (serstr != NULL) {
660 		uchar_t *bytes = NULL;
661 		size_t bytelen;
662 
663 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
664 		if (rv != KMF_OK || bytes == NULL) {
665 			(void) fprintf(stderr, gettext("Serial number "
666 			    "must be specified as a hex number "
667 			    "(ex: 0x0102030405ffeeddee)\n"));
668 			return (PK_ERR_USAGE);
669 		}
670 		serial.val = bytes;
671 		serial.len = bytelen;
672 	} else {
673 		(void) fprintf(stderr, gettext("The serial number was not"
674 		    " specified\n"));
675 		return (PK_ERR_USAGE);
676 	}
677 
678 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
679 	    kstype == KMF_KEYSTORE_NSS)) {
680 		/* Need to get password for private key access */
681 		(void) get_token_password(kstype, token_spec,
682 		    &tokencred);
683 	}
684 	if (ekustr != NULL) {
685 		rv = verify_ekunames(ekustr, &ekulist);
686 		if (rv != KMF_OK) {
687 			(void) fprintf(stderr, gettext("EKUs must "
688 			    "be specified as a comma-separated list. "
689 			    "See the man page for details.\n"));
690 			rv = PK_ERR_USAGE;
691 			goto end;
692 		}
693 	}
694 	if (altname != NULL) {
695 		char *p;
696 		rv = verify_altname(altname, &alttype, &altcrit);
697 		if (rv != KMF_OK) {
698 			(void) fprintf(stderr, gettext("Subject AltName "
699 			    "must be specified as a name=value pair. "
700 			    "See the man page for details.\n"));
701 			rv = PK_ERR_USAGE;
702 			goto end;
703 		}
704 		/* advance the altname past the '=' sign */
705 		p = strchr(altname, '=');
706 		if (p != NULL)
707 			altname = p + 1;
708 	}
709 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
710 		cryptoerror(LOG_STDERR,
711 		    gettext("Error parsing format string (%s).\n"),
712 		    format);
713 		return (PK_ERR_USAGE);
714 	}
715 
716 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
717 		rv = pk_signcsr_pk11_nss(kmfhandle,
718 		    kstype, dir, prefix, token_spec, &tokencred,
719 		    signkey, csrfile, &serial, certfile, issuer, subject,
720 		    altname, alttype, altcrit, kubits, kucrit,
721 		    ekulist, ltime, fmt, store, outlabel);
722 
723 	} else if (kstype == KMF_KEYSTORE_NSS) {
724 		if (dir == NULL)
725 			dir = PK_DEFAULT_DIRECTORY;
726 
727 		rv = pk_signcsr_pk11_nss(kmfhandle,
728 		    kstype, dir, prefix, token_spec, &tokencred,
729 		    signkey, csrfile, &serial, certfile, issuer, subject,
730 		    altname, alttype, altcrit, kubits, kucrit,
731 		    ekulist, ltime, fmt, store, outlabel);
732 
733 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
734 		rv = pk_signcsr_files(kmfhandle,
735 		    signkey, csrfile, &serial, certfile, issuer, subject,
736 		    altname, alttype, altcrit, kubits, kucrit,
737 		    ekulist, ltime, fmt);
738 	}
739 
740 end:
741 	if (rv != KMF_OK) {
742 		display_error(kmfhandle, rv,
743 		    gettext("Error listing objects"));
744 	}
745 
746 	if (serial.val != NULL)
747 		free(serial.val);
748 
749 	if (tokencred.cred != NULL)
750 		free(tokencred.cred);
751 
752 	free_eku_list(ekulist);
753 
754 	(void) kmf_finalize(kmfhandle);
755 	return (rv);
756 }
757