signcsr.c revision 12234:cd6642d6b7dd
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
47static int
48read_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 = {NULL, 0};
53	KMF_DATA rawcsr = {NULL, 0};
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
81static KMF_RETURN
82find_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
103static int
104build_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, NULL, 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	}
197cleanup:
198	if (issuer != NULL)
199		kmf_free_dn(&issuerDN);
200	if (subject != NULL)
201		kmf_free_dn(&subjectDN);
202
203	return (rv);
204}
205
206static int
207pk_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
244static int
245pk_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	(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
344cleanup:
345	kmf_free_signed_csr(&csrdata);
346	kmf_free_data(&certdata);
347	kmf_free_kmf_key(handle, &cakey);
348	return (rv);
349}
350
351static int
352pk_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 = {NULL, 0};
365	KMF_CSR_DATA csrdata = {NULL, 0};
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
509cleanup:
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 */
520int
521pk_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
800end:
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