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