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