xref: /illumos-gate/usr/src/cmd/cmd-crypto/pktool/signcsr.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 /*
27  * This file implements the sign CSR operation for this tool.
28  */
29 
30 #include <stdio.h>
31 #include <errno.h>
32 #include <string.h>
33 #include <cryptoutil.h>
34 #include <security/cryptoki.h>
35 #include "common.h"
36 
37 #include <kmfapi.h>
38 #include <kmfapiP.h>
39 
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 KMF_RETURN
84 find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid,
85 	KMF_X509_EXTENSION *outextn)
86 {
87 	int i, found = 0;
88 	KMF_X509_EXTENSION *eptr;
89 	KMF_RETURN rv = KMF_OK;
90 
91 	(void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION));
92 	for (i = 0; !found && i < extnlist->numberOfExtensions; i++) {
93 		eptr = &extnlist->extensions[i];
94 		if (IsEqualOid(extoid, &eptr->extnId)) {
95 			rv = copy_extension_data(outextn, eptr);
96 			found++;
97 		}
98 	}
99 	if (found == 0 || rv != KMF_OK)
100 		return (1);
101 	else
102 		return (rv);
103 }
104 
105 static int
106 build_cert_from_csr(KMF_CSR_DATA *csrdata,
107 	KMF_X509_CERTIFICATE *signedCert,
108 	KMF_BIGINT *serial,
109 	uint32_t ltime,
110 	char *issuer, char *subject,
111 	char *altname,
112 	KMF_GENERALNAMECHOICES alttype,
113 	int altcrit,
114 	uint16_t kubits,
115 	int kucrit,
116 	EKU_LIST *ekulist)
117 {
118 	KMF_RETURN rv = KMF_OK;
119 	KMF_X509_NAME issuerDN, subjectDN;
120 
121 	/*
122 	 * If the CSR is ok, now we can generate the final certificate.
123 	 */
124 	(void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE));
125 	(void) memset(&issuerDN, 0, sizeof (issuerDN));
126 	(void) memset(&subjectDN, 0, sizeof (subjectDN));
127 
128 	SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number");
129 
130 	SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number");
131 
132 	SET_VALUE(kmf_set_cert_validity(signedCert, NULL, ltime),
133 	    "validity time");
134 
135 	if (issuer) {
136 		if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) {
137 			cryptoerror(LOG_STDERR,
138 			    gettext("Issuer name cannot be parsed\n"));
139 			return (PK_ERR_USAGE);
140 		}
141 		SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN),
142 		    "Issuer Name");
143 	}
144 	if (subject) {
145 		if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) {
146 			cryptoerror(LOG_STDERR,
147 			    gettext("Subject name cannot be parsed\n"));
148 			return (PK_ERR_USAGE);
149 		}
150 		SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN),
151 		    "Subject Name");
152 	} else {
153 		signedCert->certificate.subject = csrdata->csr.subject;
154 	}
155 
156 	signedCert->certificate.subjectPublicKeyInfo =
157 	    csrdata->csr.subjectPublicKeyInfo;
158 
159 	signedCert->certificate.extensions = csrdata->csr.extensions;
160 
161 	signedCert->certificate.signature =
162 	    csrdata->signature.algorithmIdentifier;
163 
164 	if (kubits != 0) {
165 		KMF_X509_EXTENSION extn;
166 		uint16_t oldbits;
167 		/*
168 		 * If the CSR already has KU, merge them.
169 		 */
170 		rv = find_csr_extn(&csrdata->csr.extensions,
171 		    (KMF_OID *)&KMFOID_KeyUsage, &extn);
172 		if (rv == KMF_OK) {
173 			extn.critical |= kucrit;
174 			if (extn.value.tagAndValue->value.Length > 1) {
175 				oldbits =
176 				    extn.value.tagAndValue->value.Data[1] << 8;
177 			} else {
178 				oldbits =
179 				    extn.value.tagAndValue->value.Data[0];
180 			}
181 			oldbits |= kubits;
182 		} else {
183 			SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
184 			    "KeyUsage");
185 		}
186 	}
187 	if (altname != NULL) {
188 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
189 		    altcrit, alttype, altname), "subjectAltName");
190 	}
191 	if (ekulist != NULL) {
192 		int i;
193 		for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) {
194 			SET_VALUE(kmf_add_cert_eku(signedCert,
195 			    &ekulist->ekulist[i],
196 			    ekulist->critlist[i]), "Extended Key Usage");
197 		}
198 	}
199 cleanup:
200 	if (issuer != NULL)
201 		kmf_free_dn(&issuerDN);
202 	if (subject != NULL)
203 		kmf_free_dn(&subjectDN);
204 
205 	return (rv);
206 }
207 
208 static int
209 pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert,
210 	KMF_KEY_HANDLE *key, KMF_DATA *outdata)
211 {
212 	KMF_RETURN rv;
213 	int numattr;
214 	KMF_ATTRIBUTE attrlist[4];
215 
216 	numattr = 0;
217 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
218 	    &key->kstype, sizeof (KMF_KEYSTORE_TYPE));
219 	numattr++;
220 
221 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
222 	    key, sizeof (KMF_KEY_HANDLE_ATTR));
223 	numattr++;
224 
225 	/* cert data that is to be signed */
226 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
227 	    cert, sizeof (KMF_X509_CERTIFICATE));
228 	numattr++;
229 
230 	/* output buffer for the signed cert */
231 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
232 	    outdata, sizeof (KMF_DATA));
233 	numattr++;
234 
235 	if ((rv = kmf_sign_cert(handle, numattr, attrlist)) != KMF_OK) {
236 		cryptoerror(LOG_STDERR,
237 		    gettext("Failed to sign certificate.\n"));
238 		return (rv);
239 	}
240 
241 	return (rv);
242 }
243 
244 static int
245 pk_signcsr_files(KMF_HANDLE_T handle,
246 	char *signkey,
247 	char *csrfile,
248 	KMF_BIGINT *serial,
249 	char *certfile,
250 	char *issuer,
251 	char *subject,
252 	char *altname,
253 	KMF_GENERALNAMECHOICES alttype,
254 	int altcrit,
255 	uint16_t kubits,
256 	int kucrit,
257 	EKU_LIST *ekulist,
258 	uint32_t ltime,
259 	KMF_ENCODE_FORMAT fmt)
260 {
261 	KMF_RETURN rv = KMF_OK;
262 	KMF_CSR_DATA csrdata;
263 	KMF_ATTRIBUTE attrlist[16];
264 	KMF_X509_CERTIFICATE signedCert;
265 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
266 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
267 	KMF_KEY_HANDLE cakey;
268 	KMF_DATA certdata = {NULL, 0};
269 	int numattr, count;
270 
271 	rv = read_csrdata(handle, csrfile, &csrdata);
272 	if (rv != KMF_OK) {
273 		cryptoerror(LOG_STDERR,
274 		    gettext("Error reading CSR data\n"));
275 		return (rv);
276 	}
277 
278 	/* verify the signature first */
279 	numattr = 0;
280 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
281 	    &csrdata, sizeof (csrdata));
282 	numattr++;
283 
284 	rv = kmf_verify_csr(handle, numattr, attrlist);
285 	if (rv != KMF_OK) {
286 		cryptoerror(LOG_STDERR, gettext("CSR signature "
287 		    "verification failed.\n"));
288 		goto cleanup;
289 	}
290 
291 	rv = build_cert_from_csr(&csrdata, &signedCert, serial, ltime,
292 	    issuer, subject, altname, alttype, altcrit, kubits,
293 	    kucrit, ekulist);
294 
295 	if (rv != KMF_OK)
296 		goto cleanup;
297 
298 	/*
299 	 * Find the signing key.
300 	 */
301 	(void) memset(&cakey, 0, sizeof (cakey));
302 
303 	numattr = 0;
304 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
305 	    &kstype, sizeof (kstype));
306 	numattr++;
307 
308 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
309 	    signkey, strlen(signkey));
310 	numattr++;
311 
312 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
313 	    &keyclass, sizeof (keyclass));
314 	numattr++;
315 
316 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
317 	    &cakey, sizeof (cakey));
318 	numattr++;
319 
320 	count = 1;
321 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
322 	    &count, sizeof (count));
323 	numattr++;
324 
325 	rv = kmf_find_key(handle, numattr, attrlist);
326 	if (rv != KMF_OK) {
327 		cryptoerror(LOG_STDERR, gettext(
328 		    "Error finding CA signing key\n"));
329 		goto cleanup;
330 	}
331 
332 	rv = pk_sign_cert(handle, &signedCert, &cakey, &certdata);
333 	if (rv != KMF_OK) {
334 		cryptoerror(LOG_STDERR, gettext(
335 		    "Error signing certificate.\n"));
336 		goto cleanup;
337 	}
338 
339 	rv = kmf_create_cert_file(&certdata, fmt, certfile);
340 
341 cleanup:
342 	kmf_free_signed_csr(&csrdata);
343 	kmf_free_data(&certdata);
344 	kmf_free_kmf_key(handle, &cakey);
345 	return (rv);
346 }
347 
348 static int
349 pk_signcsr_pk11_nss(KMF_HANDLE_T handle,
350 	KMF_KEYSTORE_TYPE kstype,
351 	char *dir, char *prefix,
352 	char *token, KMF_CREDENTIAL *cred,
353 	char *signkey, char *csrfile,
354 	KMF_BIGINT *serial, char *certfile, char *issuer, char *subject,
355 	char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit,
356 	uint16_t kubits, int kucrit,
357 	EKU_LIST *ekulist, uint32_t ltime,
358 	KMF_ENCODE_FORMAT fmt, int store, char *outlabel)
359 {
360 	KMF_RETURN rv = KMF_OK;
361 	KMF_DATA outcert = {NULL, 0};
362 	KMF_CSR_DATA csrdata;
363 	KMF_KEY_HANDLE casignkey;
364 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
365 	int numattr = 0;
366 	int keys = 1;
367 	KMF_ATTRIBUTE attrlist[16];
368 	KMF_X509_CERTIFICATE signedCert;
369 	boolean_t token_bool = B_TRUE;
370 	boolean_t private_bool = B_TRUE;
371 
372 	(void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE));
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 
662 	/* Assume keystore = PKCS#11 if not specified. */
663 	if (kstype == 0)
664 		kstype = KMF_KEYSTORE_PK11TOKEN;
665 
666 	DIR_OPTION_CHECK(kstype, dir);
667 
668 	if (signkey == NULL) {
669 		(void) fprintf(stderr, gettext("The signing key label "
670 		    "or filename was not specified\n"));
671 		return (PK_ERR_USAGE);
672 	}
673 	if (csrfile == NULL) {
674 		(void) fprintf(stderr, gettext("The CSR filename was not"
675 		    " specified\n"));
676 		return (PK_ERR_USAGE);
677 	}
678 	if (certfile == NULL) {
679 		(void) fprintf(stderr, gettext("The output certificate file "
680 		    "was not specified\n"));
681 		return (PK_ERR_USAGE);
682 	}
683 	if (issuer == NULL) {
684 		(void) fprintf(stderr, gettext("The issuer DN "
685 		    "was not specified\n"));
686 		return (PK_ERR_USAGE);
687 	}
688 	if (lifetime != NULL) {
689 		if (Str2Lifetime(lifetime, &ltime) != 0) {
690 			cryptoerror(LOG_STDERR,
691 			    gettext("Error parsing lifetime string\n"));
692 			return (PK_ERR_USAGE);
693 		}
694 	}
695 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
696 		token_spec = PK_DEFAULT_PK11TOKEN;
697 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
698 		token_spec = DEFAULT_NSS_TOKEN;
699 	}
700 
701 	if (serstr != NULL) {
702 		uchar_t *bytes = NULL;
703 		size_t bytelen;
704 
705 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
706 		if (rv != KMF_OK || bytes == NULL) {
707 			(void) fprintf(stderr, gettext("Serial number "
708 			    "must be specified as a hex number "
709 			    "(ex: 0x0102030405ffeeddee)\n"));
710 			return (PK_ERR_USAGE);
711 		}
712 		serial.val = bytes;
713 		serial.len = bytelen;
714 	} else {
715 		(void) fprintf(stderr, gettext("The serial number was not"
716 		    " specified\n"));
717 		return (PK_ERR_USAGE);
718 	}
719 
720 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
721 	    kstype == KMF_KEYSTORE_NSS)) {
722 		/* Need to get password for private key access */
723 		(void) get_token_password(kstype, token_spec,
724 		    &tokencred);
725 	}
726 	if (kustr != NULL) {
727 		rv = verify_keyusage(kustr, &kubits, &kucrit);
728 		if (rv != KMF_OK) {
729 			(void) fprintf(stderr, gettext("KeyUsage "
730 			    "must be specified as a comma-separated list. "
731 			    "See the man page for details.\n"));
732 			rv = PK_ERR_USAGE;
733 			goto end;
734 		}
735 	}
736 	if (ekustr != NULL) {
737 		rv = verify_ekunames(ekustr, &ekulist);
738 		if (rv != KMF_OK) {
739 			(void) fprintf(stderr, gettext("EKUs must "
740 			    "be specified as a comma-separated list. "
741 			    "See the man page for details.\n"));
742 			rv = PK_ERR_USAGE;
743 			goto end;
744 		}
745 	}
746 	if (altname != NULL) {
747 		char *p;
748 		rv = verify_altname(altname, &alttype, &altcrit);
749 		if (rv != KMF_OK) {
750 			(void) fprintf(stderr, gettext("Subject AltName "
751 			    "must be specified as a name=value pair. "
752 			    "See the man page for details.\n"));
753 			rv = PK_ERR_USAGE;
754 			goto end;
755 		}
756 		/* advance the altname past the '=' sign */
757 		p = strchr(altname, '=');
758 		if (p != NULL)
759 			altname = p + 1;
760 	}
761 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
762 		cryptoerror(LOG_STDERR,
763 		    gettext("Error parsing format string (%s).\n"),
764 		    format);
765 		return (PK_ERR_USAGE);
766 	}
767 
768 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
769 		return (rv);
770 	}
771 
772 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
773 		rv = pk_signcsr_pk11_nss(kmfhandle,
774 		    kstype, dir, prefix, token_spec, &tokencred,
775 		    signkey, csrfile, &serial, certfile, issuer, subject,
776 		    altname, alttype, altcrit, kubits, kucrit,
777 		    ekulist, ltime, fmt, store, outlabel);
778 
779 	} else if (kstype == KMF_KEYSTORE_NSS) {
780 		if (dir == NULL)
781 			dir = PK_DEFAULT_DIRECTORY;
782 
783 		rv = pk_signcsr_pk11_nss(kmfhandle,
784 		    kstype, dir, prefix, token_spec, &tokencred,
785 		    signkey, csrfile, &serial, certfile, issuer, subject,
786 		    altname, alttype, altcrit, kubits, kucrit,
787 		    ekulist, ltime, fmt, store, outlabel);
788 
789 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
790 		rv = pk_signcsr_files(kmfhandle,
791 		    signkey, csrfile, &serial, certfile, issuer, subject,
792 		    altname, alttype, altcrit, kubits, kucrit,
793 		    ekulist, ltime, fmt);
794 	}
795 
796 end:
797 	if (rv != KMF_OK) {
798 		display_error(kmfhandle, rv,
799 		    gettext("Error listing objects"));
800 	}
801 
802 	if (serial.val != NULL)
803 		free(serial.val);
804 
805 	if (tokencred.cred != NULL)
806 		free(tokencred.cred);
807 
808 	free_eku_list(ekulist);
809 
810 	(void) kmf_finalize(kmfhandle);
811 	return (rv);
812 }
813