1d00756ccSwyllys /*
2d00756ccSwyllys  * CDDL HEADER START
3d00756ccSwyllys  *
4d00756ccSwyllys  * The contents of this file are subject to the terms of the
5d00756ccSwyllys  * Common Development and Distribution License (the "License").
6d00756ccSwyllys  * You may not use this file except in compliance with the License.
7d00756ccSwyllys  *
8d00756ccSwyllys  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9d00756ccSwyllys  * or http://www.opensolaris.org/os/licensing.
10d00756ccSwyllys  * See the License for the specific language governing permissions
11d00756ccSwyllys  * and limitations under the License.
12d00756ccSwyllys  *
13d00756ccSwyllys  * When distributing Covered Code, include this CDDL HEADER in each
14d00756ccSwyllys  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15d00756ccSwyllys  * If applicable, add the following below this CDDL HEADER, with the
16d00756ccSwyllys  * fields enclosed by brackets "[]" replaced with your own identifying
17d00756ccSwyllys  * information: Portions Copyright [yyyy] [name of copyright owner]
18d00756ccSwyllys  *
19d00756ccSwyllys  * CDDL HEADER END
2072ca8cc9SWyllys Ingersoll  *
212c9a247fSWyllys Ingersoll  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
22d00756ccSwyllys  */
23d00756ccSwyllys 
24d00756ccSwyllys /*
25d00756ccSwyllys  * This file implements the sign CSR operation for this tool.
26d00756ccSwyllys  */
27d00756ccSwyllys 
28d00756ccSwyllys #include <stdio.h>
29d00756ccSwyllys #include <errno.h>
30d00756ccSwyllys #include <string.h>
31d00756ccSwyllys #include <cryptoutil.h>
32d00756ccSwyllys #include <security/cryptoki.h>
33d00756ccSwyllys #include "common.h"
34d00756ccSwyllys 
35d00756ccSwyllys #include <kmfapi.h>
36448b8615Swyllys #include <kmfapiP.h>
37448b8615Swyllys 
38d00756ccSwyllys #define	SET_VALUE(f, s) \
39d00756ccSwyllys 	rv = f; \
40d00756ccSwyllys 	if (rv != KMF_OK) { \
41d00756ccSwyllys 		cryptoerror(LOG_STDERR, \
42d00756ccSwyllys 		    gettext("Failed to set %s: 0x%02x\n"), s, rv); \
43d00756ccSwyllys 		goto cleanup; \
44d00756ccSwyllys 	}
45d00756ccSwyllys 
46d00756ccSwyllys 
47d00756ccSwyllys static int
read_csrdata(KMF_HANDLE_T handle,char * csrfile,KMF_CSR_DATA * csrdata)48d00756ccSwyllys read_csrdata(KMF_HANDLE_T handle, char *csrfile, KMF_CSR_DATA *csrdata)
49d00756ccSwyllys {
50d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
51d00756ccSwyllys 	KMF_ENCODE_FORMAT csrfmt;
526b35cb3cSRichard PALO 	KMF_DATA csrfiledata = { 0, NULL };
536b35cb3cSRichard PALO 	KMF_DATA rawcsr = { 0, NULL };
54d00756ccSwyllys 
55d00756ccSwyllys 	rv = kmf_get_file_format(csrfile, &csrfmt);
56d00756ccSwyllys 	if (rv != KMF_OK)
57d00756ccSwyllys 		return (rv);
58d00756ccSwyllys 
59d00756ccSwyllys 	rv = kmf_read_input_file(handle, csrfile, &csrfiledata);
60d00756ccSwyllys 	if (rv != KMF_OK)
61d00756ccSwyllys 		return (rv);
62d00756ccSwyllys 
63d00756ccSwyllys 	if (csrfmt == KMF_FORMAT_PEM) {
64d00756ccSwyllys 		rv = kmf_pem_to_der(csrfiledata.Data, csrfiledata.Length,
65d00756ccSwyllys 		    &rawcsr.Data, (int *)&rawcsr.Length);
66d00756ccSwyllys 		if (rv != KMF_OK)
67d00756ccSwyllys 			return (rv);
68d00756ccSwyllys 
69d00756ccSwyllys 		kmf_free_data(&csrfiledata);
70d00756ccSwyllys 	} else {
71d00756ccSwyllys 		rawcsr.Data = csrfiledata.Data;
72d00756ccSwyllys 		rawcsr.Length = csrfiledata.Length;
73d00756ccSwyllys 	}
74d00756ccSwyllys 
75d00756ccSwyllys 	rv = kmf_decode_csr(handle, &rawcsr, csrdata);
76d00756ccSwyllys 	kmf_free_data(&rawcsr);
77d00756ccSwyllys 
78d00756ccSwyllys 	return (rv);
79d00756ccSwyllys }
80d00756ccSwyllys 
81448b8615Swyllys static KMF_RETURN
find_csr_extn(KMF_X509_EXTENSIONS * extnlist,KMF_OID * extoid,KMF_X509_EXTENSION * outextn)82448b8615Swyllys find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid,
83448b8615Swyllys 	KMF_X509_EXTENSION *outextn)
84448b8615Swyllys {
85448b8615Swyllys 	int i, found = 0;
86448b8615Swyllys 	KMF_X509_EXTENSION *eptr;
87448b8615Swyllys 	KMF_RETURN rv = KMF_OK;
88448b8615Swyllys 
89448b8615Swyllys 	(void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION));
90448b8615Swyllys 	for (i = 0; !found && i < extnlist->numberOfExtensions; i++) {
91448b8615Swyllys 		eptr = &extnlist->extensions[i];
92448b8615Swyllys 		if (IsEqualOid(extoid, &eptr->extnId)) {
93448b8615Swyllys 			rv = copy_extension_data(outextn, eptr);
94448b8615Swyllys 			found++;
95448b8615Swyllys 		}
96448b8615Swyllys 	}
97448b8615Swyllys 	if (found == 0 || rv != KMF_OK)
98448b8615Swyllys 		return (1);
99448b8615Swyllys 	else
100448b8615Swyllys 		return (rv);
101448b8615Swyllys }
102448b8615Swyllys 
103d00756ccSwyllys 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)104d00756ccSwyllys build_cert_from_csr(KMF_CSR_DATA *csrdata,
105d00756ccSwyllys 	KMF_X509_CERTIFICATE *signedCert,
106d00756ccSwyllys 	KMF_BIGINT *serial,
107d00756ccSwyllys 	uint32_t ltime,
108d00756ccSwyllys 	char *issuer, char *subject,
109d00756ccSwyllys 	char *altname,
110d00756ccSwyllys 	KMF_GENERALNAMECHOICES alttype,
111d00756ccSwyllys 	int altcrit,
112d00756ccSwyllys 	uint16_t kubits,
113d00756ccSwyllys 	int kucrit,
114d00756ccSwyllys 	EKU_LIST *ekulist)
115d00756ccSwyllys {
116d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
117d00756ccSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
118d00756ccSwyllys 
119d00756ccSwyllys 	/*
120d00756ccSwyllys 	 * If the CSR is ok, now we can generate the final certificate.
121d00756ccSwyllys 	 */
122d00756ccSwyllys 	(void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE));
123d00756ccSwyllys 	(void) memset(&issuerDN, 0, sizeof (issuerDN));
124d00756ccSwyllys 	(void) memset(&subjectDN, 0, sizeof (subjectDN));
125d00756ccSwyllys 
126d00756ccSwyllys 	SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number");
127d00756ccSwyllys 
128d00756ccSwyllys 	SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number");
129d00756ccSwyllys 
130*6f2b04a2SToomas Soome 	SET_VALUE(kmf_set_cert_validity(signedCert, 0, ltime),
131d00756ccSwyllys 	    "validity time");
132d00756ccSwyllys 
133d00756ccSwyllys 	if (issuer) {
134d00756ccSwyllys 		if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) {
135d00756ccSwyllys 			cryptoerror(LOG_STDERR,
136d00756ccSwyllys 			    gettext("Issuer name cannot be parsed\n"));
137d00756ccSwyllys 			return (PK_ERR_USAGE);
138d00756ccSwyllys 		}
139d00756ccSwyllys 		SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN),
140d00756ccSwyllys 		    "Issuer Name");
141d00756ccSwyllys 	}
142d00756ccSwyllys 	if (subject) {
143d00756ccSwyllys 		if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) {
144d00756ccSwyllys 			cryptoerror(LOG_STDERR,
145d00756ccSwyllys 			    gettext("Subject name cannot be parsed\n"));
146d00756ccSwyllys 			return (PK_ERR_USAGE);
147d00756ccSwyllys 		}
148d00756ccSwyllys 		SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN),
149d00756ccSwyllys 		    "Subject Name");
150d00756ccSwyllys 	} else {
151d00756ccSwyllys 		signedCert->certificate.subject = csrdata->csr.subject;
152d00756ccSwyllys 	}
153d00756ccSwyllys 
154d00756ccSwyllys 	signedCert->certificate.subjectPublicKeyInfo =
155d00756ccSwyllys 	    csrdata->csr.subjectPublicKeyInfo;
156d00756ccSwyllys 
157d00756ccSwyllys 	signedCert->certificate.extensions = csrdata->csr.extensions;
158d00756ccSwyllys 
159d00756ccSwyllys 	signedCert->certificate.signature =
160d00756ccSwyllys 	    csrdata->signature.algorithmIdentifier;
161d00756ccSwyllys 
162d00756ccSwyllys 	if (kubits != 0) {
163448b8615Swyllys 		KMF_X509_EXTENSION extn;
164448b8615Swyllys 		uint16_t oldbits;
165448b8615Swyllys 		/*
166448b8615Swyllys 		 * If the CSR already has KU, merge them.
167448b8615Swyllys 		 */
168448b8615Swyllys 		rv = find_csr_extn(&csrdata->csr.extensions,
169448b8615Swyllys 		    (KMF_OID *)&KMFOID_KeyUsage, &extn);
170448b8615Swyllys 		if (rv == KMF_OK) {
171448b8615Swyllys 			extn.critical |= kucrit;
172448b8615Swyllys 			if (extn.value.tagAndValue->value.Length > 1) {
173448b8615Swyllys 				oldbits =
174448b8615Swyllys 				    extn.value.tagAndValue->value.Data[1] << 8;
175448b8615Swyllys 			} else {
176448b8615Swyllys 				oldbits =
177448b8615Swyllys 				    extn.value.tagAndValue->value.Data[0];
178448b8615Swyllys 			}
179448b8615Swyllys 			oldbits |= kubits;
180448b8615Swyllys 		} else {
181448b8615Swyllys 			SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
182448b8615Swyllys 			    "KeyUsage");
183448b8615Swyllys 		}
184d00756ccSwyllys 	}
185d00756ccSwyllys 	if (altname != NULL) {
186d00756ccSwyllys 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
187d00756ccSwyllys 		    altcrit, alttype, altname), "subjectAltName");
188d00756ccSwyllys 	}
189d00756ccSwyllys 	if (ekulist != NULL) {
190d00756ccSwyllys 		int i;
191d00756ccSwyllys 		for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) {
192d00756ccSwyllys 			SET_VALUE(kmf_add_cert_eku(signedCert,
193d00756ccSwyllys 			    &ekulist->ekulist[i],
194d00756ccSwyllys 			    ekulist->critlist[i]), "Extended Key Usage");
195d00756ccSwyllys 		}
196d00756ccSwyllys 	}
197d00756ccSwyllys cleanup:
198d00756ccSwyllys 	if (issuer != NULL)
199d00756ccSwyllys 		kmf_free_dn(&issuerDN);
200d00756ccSwyllys 	if (subject != NULL)
201d00756ccSwyllys 		kmf_free_dn(&subjectDN);
202d00756ccSwyllys 
203d00756ccSwyllys 	return (rv);
204d00756ccSwyllys }
205d00756ccSwyllys 
206d00756ccSwyllys static int
pk_sign_cert(KMF_HANDLE_T handle,KMF_X509_CERTIFICATE * cert,KMF_KEY_HANDLE * key,KMF_OID * sigoid,KMF_DATA * outdata)207d00756ccSwyllys pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert,
2082c9a247fSWyllys Ingersoll 	KMF_KEY_HANDLE *key, KMF_OID *sigoid, KMF_DATA *outdata)
209d00756ccSwyllys {
210d00756ccSwyllys 	KMF_RETURN rv;
211d00756ccSwyllys 	int numattr;
212d00756ccSwyllys 	KMF_ATTRIBUTE attrlist[4];
213d00756ccSwyllys 
214d00756ccSwyllys 	numattr = 0;
2152c9a247fSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEYSTORE_TYPE_ATTR,
216d00756ccSwyllys 	    &key->kstype, sizeof (KMF_KEYSTORE_TYPE));
217d00756ccSwyllys 
2182c9a247fSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr++, KMF_KEY_HANDLE_ATTR,
219d00756ccSwyllys 	    key, sizeof (KMF_KEY_HANDLE_ATTR));
220d00756ccSwyllys 
221d00756ccSwyllys 	/* cert data that is to be signed */
2222c9a247fSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr++, KMF_X509_CERTIFICATE_ATTR,
223d00756ccSwyllys 	    cert, sizeof (KMF_X509_CERTIFICATE));
224d00756ccSwyllys 
225d00756ccSwyllys 	/* output buffer for the signed cert */
2262c9a247fSWyllys Ingersoll 	kmf_set_attr_at_index(attrlist, numattr++, KMF_CERT_DATA_ATTR,
227d00756ccSwyllys 	    outdata, sizeof (KMF_DATA));
2282c9a247fSWyllys Ingersoll 
2292c9a247fSWyllys Ingersoll 	/* Set the signature OID value so KMF knows how to generate the sig */
2302c9a247fSWyllys Ingersoll 	if (sigoid) {
2312c9a247fSWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr++, KMF_OID_ATTR,
2322c9a247fSWyllys Ingersoll 		    sigoid, sizeof (KMF_OID));
2332c9a247fSWyllys Ingersoll 	}
234d00756ccSwyllys 
235d00756ccSwyllys 	if ((rv = kmf_sign_cert(handle, numattr, attrlist)) != KMF_OK) {
236d00756ccSwyllys 		cryptoerror(LOG_STDERR,
237d00756ccSwyllys 		    gettext("Failed to sign certificate.\n"));
238d00756ccSwyllys 		return (rv);
239d00756ccSwyllys 	}
240d00756ccSwyllys 
241d00756ccSwyllys 	return (rv);
242d00756ccSwyllys }
243d00756ccSwyllys 
244d00756ccSwyllys 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)245d00756ccSwyllys pk_signcsr_files(KMF_HANDLE_T handle,
246d00756ccSwyllys 	char *signkey,
247d00756ccSwyllys 	char *csrfile,
248d00756ccSwyllys 	KMF_BIGINT *serial,
249d00756ccSwyllys 	char *certfile,
250d00756ccSwyllys 	char *issuer,
251d00756ccSwyllys 	char *subject,
252d00756ccSwyllys 	char *altname,
253d00756ccSwyllys 	KMF_GENERALNAMECHOICES alttype,
254d00756ccSwyllys 	int altcrit,
255d00756ccSwyllys 	uint16_t kubits,
256d00756ccSwyllys 	int kucrit,
257d00756ccSwyllys 	EKU_LIST *ekulist,
258d00756ccSwyllys 	uint32_t ltime,
259d00756ccSwyllys 	KMF_ENCODE_FORMAT fmt)
260d00756ccSwyllys {
261d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
262d00756ccSwyllys 	KMF_CSR_DATA csrdata;
263d00756ccSwyllys 	KMF_ATTRIBUTE attrlist[16];
264d00756ccSwyllys 	KMF_X509_CERTIFICATE signedCert;
265d00756ccSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
266d00756ccSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
267d00756ccSwyllys 	KMF_KEY_HANDLE cakey;
2686b35cb3cSRichard PALO 	KMF_DATA certdata = { 0, NULL };
269d00756ccSwyllys 	int numattr, count;
270d00756ccSwyllys 
271e65e5c2dSWyllys Ingersoll 	(void) memset(&cakey, 0, sizeof (cakey));
272e65e5c2dSWyllys Ingersoll 	(void) memset(&signedCert, 0, sizeof (signedCert));
273e65e5c2dSWyllys Ingersoll 
274d00756ccSwyllys 	rv = read_csrdata(handle, csrfile, &csrdata);
275d00756ccSwyllys 	if (rv != KMF_OK) {
276d00756ccSwyllys 		cryptoerror(LOG_STDERR,
277d00756ccSwyllys 		    gettext("Error reading CSR data\n"));
278d00756ccSwyllys 		return (rv);
279d00756ccSwyllys 	}
280d00756ccSwyllys 
281d00756ccSwyllys 	/* verify the signature first */
282d00756ccSwyllys 	numattr = 0;
283d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
284d00756ccSwyllys 	    &csrdata, sizeof (csrdata));
285d00756ccSwyllys 	numattr++;
286d00756ccSwyllys 
287d00756ccSwyllys 	rv = kmf_verify_csr(handle, numattr, attrlist);
288d00756ccSwyllys 	if (rv != KMF_OK) {
289d00756ccSwyllys 		cryptoerror(LOG_STDERR, gettext("CSR signature "
290d00756ccSwyllys 		    "verification failed.\n"));
291d00756ccSwyllys 		goto cleanup;
292d00756ccSwyllys 	}
293d00756ccSwyllys 
294d00756ccSwyllys 	rv = build_cert_from_csr(&csrdata, &signedCert, serial, ltime,
295d00756ccSwyllys 	    issuer, subject, altname, alttype, altcrit, kubits,
296d00756ccSwyllys 	    kucrit, ekulist);
297d00756ccSwyllys 
298d00756ccSwyllys 	if (rv != KMF_OK)
299d00756ccSwyllys 		goto cleanup;
300d00756ccSwyllys 
301d00756ccSwyllys 	/*
302d00756ccSwyllys 	 * Find the signing key.
303d00756ccSwyllys 	 */
304d00756ccSwyllys 	(void) memset(&cakey, 0, sizeof (cakey));
305d00756ccSwyllys 
306d00756ccSwyllys 	numattr = 0;
307d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
308d00756ccSwyllys 	    &kstype, sizeof (kstype));
309d00756ccSwyllys 	numattr++;
310d00756ccSwyllys 
311d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
312d00756ccSwyllys 	    signkey, strlen(signkey));
313d00756ccSwyllys 	numattr++;
314d00756ccSwyllys 
315d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
316d00756ccSwyllys 	    &keyclass, sizeof (keyclass));
317d00756ccSwyllys 	numattr++;
318d00756ccSwyllys 
319d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
320d00756ccSwyllys 	    &cakey, sizeof (cakey));
321d00756ccSwyllys 	numattr++;
322d00756ccSwyllys 
323d00756ccSwyllys 	count = 1;
324d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
325d00756ccSwyllys 	    &count, sizeof (count));
326d00756ccSwyllys 	numattr++;
327d00756ccSwyllys 
328d00756ccSwyllys 	rv = kmf_find_key(handle, numattr, attrlist);
329d00756ccSwyllys 	if (rv != KMF_OK) {
330d00756ccSwyllys 		cryptoerror(LOG_STDERR, gettext(
331d00756ccSwyllys 		    "Error finding CA signing key\n"));
332d00756ccSwyllys 		goto cleanup;
333d00756ccSwyllys 	}
334d00756ccSwyllys 
3352c9a247fSWyllys Ingersoll 	rv = pk_sign_cert(handle, &signedCert, &cakey, NULL, &certdata);
336d00756ccSwyllys 	if (rv != KMF_OK) {
337d00756ccSwyllys 		cryptoerror(LOG_STDERR, gettext(
338d00756ccSwyllys 		    "Error signing certificate.\n"));
339d00756ccSwyllys 		goto cleanup;
340d00756ccSwyllys 	}
341d00756ccSwyllys 
342d00756ccSwyllys 	rv = kmf_create_cert_file(&certdata, fmt, certfile);
343d00756ccSwyllys 
344d00756ccSwyllys cleanup:
345d00756ccSwyllys 	kmf_free_signed_csr(&csrdata);
346d00756ccSwyllys 	kmf_free_data(&certdata);
347d00756ccSwyllys 	kmf_free_kmf_key(handle, &cakey);
348d00756ccSwyllys 	return (rv);
349d00756ccSwyllys }
350d00756ccSwyllys 
351d00756ccSwyllys 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)352d00756ccSwyllys pk_signcsr_pk11_nss(KMF_HANDLE_T handle,
353d00756ccSwyllys 	KMF_KEYSTORE_TYPE kstype,
354d00756ccSwyllys 	char *dir, char *prefix,
355d00756ccSwyllys 	char *token, KMF_CREDENTIAL *cred,
356d00756ccSwyllys 	char *signkey, char *csrfile,
357d00756ccSwyllys 	KMF_BIGINT *serial, char *certfile, char *issuer, char *subject,
358d00756ccSwyllys 	char *altname, KMF_GENERALNAMECHOICES alttype, int altcrit,
359d00756ccSwyllys 	uint16_t kubits, int kucrit,
360d00756ccSwyllys 	EKU_LIST *ekulist, uint32_t ltime,
361d00756ccSwyllys 	KMF_ENCODE_FORMAT fmt, int store, char *outlabel)
362d00756ccSwyllys {
363d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
3646b35cb3cSRichard PALO 	KMF_DATA outcert = { 0, NULL };
3656b35cb3cSRichard PALO 	KMF_CSR_DATA csrdata = { 0, NULL };
366d00756ccSwyllys 	KMF_KEY_HANDLE casignkey;
367d00756ccSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
368d00756ccSwyllys 	KMF_ATTRIBUTE attrlist[16];
369d00756ccSwyllys 	KMF_X509_CERTIFICATE signedCert;
370d00756ccSwyllys 	boolean_t token_bool = B_TRUE;
371d00756ccSwyllys 	boolean_t private_bool = B_TRUE;
3722c9a247fSWyllys Ingersoll 	int numattr = 0;
3732c9a247fSWyllys Ingersoll 	int keys = 1;
374d00756ccSwyllys 
37572ca8cc9SWyllys Ingersoll 	(void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE));
376e65e5c2dSWyllys Ingersoll 	(void) memset(&signedCert, 0, sizeof (signedCert));
37772ca8cc9SWyllys Ingersoll 
378d00756ccSwyllys 	rv = read_csrdata(handle, csrfile, &csrdata);
379d00756ccSwyllys 	if (rv != KMF_OK) {
380d00756ccSwyllys 		cryptoerror(LOG_STDERR,
381d00756ccSwyllys 		    gettext("Error reading CSR data\n"));
382d00756ccSwyllys 		return (rv);
383d00756ccSwyllys 	}
384d00756ccSwyllys 
385d00756ccSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
386d00756ccSwyllys 		rv = select_token(handle, token, FALSE);
387d00756ccSwyllys 	} else if (kstype == KMF_KEYSTORE_NSS) {
388d00756ccSwyllys 		rv = configure_nss(handle, dir, prefix);
389d00756ccSwyllys 	}
390d00756ccSwyllys 
391d00756ccSwyllys 	/* verify the signature first */
392d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CSR_DATA_ATTR,
393d00756ccSwyllys 	    &csrdata, sizeof (csrdata));
394d00756ccSwyllys 	numattr++;
395d00756ccSwyllys 
396d00756ccSwyllys 	rv = kmf_verify_csr(handle, numattr, attrlist);
397d00756ccSwyllys 	if (rv != KMF_OK) {
398d00756ccSwyllys 		cryptoerror(LOG_STDERR, gettext("CSR signature "
399d00756ccSwyllys 		    "verification failed.\n"));
400d00756ccSwyllys 		goto cleanup;
401d00756ccSwyllys 	}
402d00756ccSwyllys 
403d00756ccSwyllys 	rv = build_cert_from_csr(&csrdata,
404d00756ccSwyllys 	    &signedCert, serial, ltime,
405d00756ccSwyllys 	    issuer, subject, altname,
406d00756ccSwyllys 	    alttype, altcrit, kubits,
407d00756ccSwyllys 	    kucrit, ekulist);
408d00756ccSwyllys 
409d00756ccSwyllys 	if (rv != KMF_OK)
410d00756ccSwyllys 		goto cleanup;
411d00756ccSwyllys 
412d00756ccSwyllys 	/*
413d00756ccSwyllys 	 * Find the signing key.
414d00756ccSwyllys 	 */
415d00756ccSwyllys 	numattr = 0;
416d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
417d00756ccSwyllys 	    &kstype, sizeof (kstype));
418d00756ccSwyllys 	numattr++;
419d00756ccSwyllys 	if (kstype == KMF_KEYSTORE_NSS) {
420d00756ccSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
421d00756ccSwyllys 		    token, strlen(token));
422d00756ccSwyllys 		numattr++;
423d00756ccSwyllys 	}
424d00756ccSwyllys 
425d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, signkey,
426d00756ccSwyllys 	    strlen(signkey));
427d00756ccSwyllys 	numattr++;
428d00756ccSwyllys 
429d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
430d00756ccSwyllys 	    &private_bool, sizeof (private_bool));
431d00756ccSwyllys 	numattr++;
432d00756ccSwyllys 
433d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
434d00756ccSwyllys 	    &token_bool, sizeof (token_bool));
435d00756ccSwyllys 	numattr++;
436d00756ccSwyllys 
437d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
438d00756ccSwyllys 	    &keyclass, sizeof (keyclass));
439d00756ccSwyllys 	numattr++;
440d00756ccSwyllys 
441d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
442d00756ccSwyllys 	    cred, sizeof (KMF_CREDENTIAL_ATTR));
443d00756ccSwyllys 	numattr++;
444d00756ccSwyllys 
445d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
446d00756ccSwyllys 	    &keys, sizeof (keys));
447d00756ccSwyllys 	numattr++;
448d00756ccSwyllys 
449d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
450d00756ccSwyllys 	    &casignkey, sizeof (casignkey));
451d00756ccSwyllys 	numattr++;
452d00756ccSwyllys 
453d00756ccSwyllys 	rv = kmf_find_key(handle, numattr, attrlist);
454d00756ccSwyllys 	if (rv != KMF_OK) {
455d00756ccSwyllys 		cryptoerror(LOG_STDERR,
456d00756ccSwyllys 		    gettext("Failed to find signing key\n"));
457d00756ccSwyllys 		goto cleanup;
458d00756ccSwyllys 	}
459d00756ccSwyllys 	/*
460d00756ccSwyllys 	 * If we found the key, now we can sign the cert.
461d00756ccSwyllys 	 */
4622c9a247fSWyllys Ingersoll 	rv = pk_sign_cert(handle, &signedCert, &casignkey, NULL,
4632c9a247fSWyllys Ingersoll 	    &outcert);
464d00756ccSwyllys 	if (rv != KMF_OK) {
465d00756ccSwyllys 		cryptoerror(LOG_STDERR, gettext(
466d00756ccSwyllys 		    "Error signing certificate.\n"));
467d00756ccSwyllys 		goto cleanup;
468d00756ccSwyllys 	}
469d00756ccSwyllys 
470d00756ccSwyllys 	/*
471d00756ccSwyllys 	 * Store it on the token if the user asked for it.
472d00756ccSwyllys 	 */
473d00756ccSwyllys 	if (store) {
474d00756ccSwyllys 		numattr = 0;
475d00756ccSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
476d00756ccSwyllys 		    &kstype, sizeof (kstype));
477d00756ccSwyllys 		numattr++;
478d00756ccSwyllys 
479d00756ccSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
480d00756ccSwyllys 		    &outcert, sizeof (KMF_DATA));
481d00756ccSwyllys 		numattr++;
482d00756ccSwyllys 
483d00756ccSwyllys 		if (outlabel != NULL) {
484d00756ccSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
485d00756ccSwyllys 			    KMF_CERT_LABEL_ATTR,
486d00756ccSwyllys 			    outlabel, strlen(outlabel));
487d00756ccSwyllys 			numattr++;
488d00756ccSwyllys 		}
489d00756ccSwyllys 
490d00756ccSwyllys 		if (kstype == KMF_KEYSTORE_NSS) {
491d00756ccSwyllys 			if (token != NULL)
492d00756ccSwyllys 				kmf_set_attr_at_index(attrlist, numattr,
493d00756ccSwyllys 				    KMF_TOKEN_LABEL_ATTR,
494d00756ccSwyllys 				    token, strlen(token));
495d00756ccSwyllys 			numattr++;
496d00756ccSwyllys 		}
497d00756ccSwyllys 
498d00756ccSwyllys 		rv = kmf_store_cert(handle, numattr, attrlist);
499d00756ccSwyllys 		if (rv != KMF_OK) {
500d00756ccSwyllys 			display_error(handle, rv,
501d00756ccSwyllys 			    gettext("Failed to store cert "
502d00756ccSwyllys 			    "on PKCS#11 token.\n"));
503d00756ccSwyllys 			rv = KMF_OK;
504d00756ccSwyllys 			/* Not fatal, we can still write it to a file. */
505d00756ccSwyllys 		}
506d00756ccSwyllys 	}
507d00756ccSwyllys 	rv = kmf_create_cert_file(&outcert, fmt, certfile);
508d00756ccSwyllys 
509d00756ccSwyllys cleanup:
510d00756ccSwyllys 	kmf_free_signed_csr(&csrdata);
511d00756ccSwyllys 	kmf_free_data(&outcert);
512d00756ccSwyllys 	kmf_free_kmf_key(handle, &casignkey);
513d00756ccSwyllys 
514d00756ccSwyllys 	return (rv);
515d00756ccSwyllys }
516d00756ccSwyllys 
517d00756ccSwyllys /*
518d00756ccSwyllys  * sign a CSR and generate an x509v3 certificate file.
519d00756ccSwyllys  */
520d00756ccSwyllys int
pk_signcsr(int argc,char * argv[])521d00756ccSwyllys pk_signcsr(int argc, char *argv[])
522d00756ccSwyllys {
523d00756ccSwyllys 	int			opt;
524d00756ccSwyllys 	extern int		optind_av;
525d00756ccSwyllys 	extern char		*optarg_av;
526d00756ccSwyllys 	char			*token_spec = NULL;
527d00756ccSwyllys 	char			*subject = NULL;
528d00756ccSwyllys 	char			*issuer = NULL;
529d00756ccSwyllys 	char			*dir = NULL;
530d00756ccSwyllys 	char			*prefix = NULL;
531d00756ccSwyllys 	char			*csrfile = NULL;
532d00756ccSwyllys 	char			*serstr = NULL;
533d00756ccSwyllys 	char			*ekustr = NULL;
534d00756ccSwyllys 	char			*kustr = NULL;
535d00756ccSwyllys 	char			*format = NULL;
536d00756ccSwyllys 	char			*storestr = NULL;
537d00756ccSwyllys 	char			*altname = NULL;
538d00756ccSwyllys 	char			*certfile = NULL;
539d00756ccSwyllys 	char			*lifetime = NULL;
540d00756ccSwyllys 	char			*signkey = NULL;
541d00756ccSwyllys 	char			*outlabel = NULL;
542d00756ccSwyllys 	uint32_t		ltime = 365 * 24 * 60 * 60; /* 1 Year */
543d00756ccSwyllys 	int			store = 0;
544d00756ccSwyllys 	uint16_t		kubits = 0;
545d00756ccSwyllys 	int			altcrit = 0, kucrit = 0;
546d00756ccSwyllys 	KMF_BIGINT		serial = { NULL, 0 };
547d00756ccSwyllys 	EKU_LIST		*ekulist = NULL;
548d00756ccSwyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
549d00756ccSwyllys 	KMF_RETURN		rv = KMF_OK;
550d00756ccSwyllys 	KMF_HANDLE_T		kmfhandle = NULL;
5516b35cb3cSRichard PALO 	KMF_CREDENTIAL		tokencred = { NULL, 0 };
552d00756ccSwyllys 	KMF_GENERALNAMECHOICES	alttype = 0;
553d00756ccSwyllys 	KMF_ENCODE_FORMAT	fmt = KMF_FORMAT_PEM;
554d00756ccSwyllys 
555d00756ccSwyllys 	/* Parse command line options.  Do NOT i18n/l10n. */
556d00756ccSwyllys 	while ((opt = getopt_av(argc, argv,
557d00756ccSwyllys 	    "k:(keystore)c:(csr)T:(token)d:(dir)"
558d00756ccSwyllys 	    "p:(prefix)S:(serial)s:(subject)a:(altname)"
559d00756ccSwyllys 	    "t:(store)F:(format)K:(keyusage)l:(signkey)"
560d00756ccSwyllys 	    "L:(lifetime)e:(eku)i:(issuer)"
561d00756ccSwyllys 	    "n:(outlabel)o:(outcert)")) != EOF) {
562d00756ccSwyllys 		if (EMPTYSTRING(optarg_av))
563d00756ccSwyllys 			return (PK_ERR_USAGE);
564d00756ccSwyllys 		switch (opt) {
565d00756ccSwyllys 			case 'k':
566d00756ccSwyllys 				if (kstype != 0)
567d00756ccSwyllys 					return (PK_ERR_USAGE);
568d00756ccSwyllys 				kstype = KS2Int(optarg_av);
569d00756ccSwyllys 				if (kstype == 0)
570d00756ccSwyllys 					return (PK_ERR_USAGE);
571d00756ccSwyllys 				break;
572d00756ccSwyllys 			case 't':
573d00756ccSwyllys 				if (storestr != NULL)
574d00756ccSwyllys 					return (PK_ERR_USAGE);
575d00756ccSwyllys 				storestr = optarg_av;
576d00756ccSwyllys 				store = yn_to_int(optarg_av);
577d00756ccSwyllys 				if (store == -1)
578d00756ccSwyllys 					return (PK_ERR_USAGE);
579d00756ccSwyllys 				break;
580d00756ccSwyllys 			case 'a':
581d00756ccSwyllys 				if (altname)
582d00756ccSwyllys 					return (PK_ERR_USAGE);
583d00756ccSwyllys 				altname = optarg_av;
584d00756ccSwyllys 				break;
585d00756ccSwyllys 			case 's':
586d00756ccSwyllys 				if (subject)
587d00756ccSwyllys 					return (PK_ERR_USAGE);
588d00756ccSwyllys 				subject = optarg_av;
589d00756ccSwyllys 				break;
590d00756ccSwyllys 			case 'i':
591d00756ccSwyllys 				if (issuer)
592d00756ccSwyllys 					return (PK_ERR_USAGE);
593d00756ccSwyllys 				issuer = optarg_av;
594d00756ccSwyllys 				break;
595d00756ccSwyllys 			case 'd':
596d00756ccSwyllys 				if (dir)
597d00756ccSwyllys 					return (PK_ERR_USAGE);
598d00756ccSwyllys 				dir = optarg_av;
599d00756ccSwyllys 				break;
600d00756ccSwyllys 			case 'p':
601d00756ccSwyllys 				if (prefix)
602d00756ccSwyllys 					return (PK_ERR_USAGE);
603d00756ccSwyllys 				prefix = optarg_av;
604d00756ccSwyllys 				break;
605d00756ccSwyllys 			case 'S':
606d00756ccSwyllys 				if (serstr != NULL)
607d00756ccSwyllys 					return (PK_ERR_USAGE);
608d00756ccSwyllys 				serstr = optarg_av;
609d00756ccSwyllys 				break;
610d00756ccSwyllys 			case 'c':
611d00756ccSwyllys 				if (csrfile)
612d00756ccSwyllys 					return (PK_ERR_USAGE);
613d00756ccSwyllys 				csrfile = optarg_av;
614d00756ccSwyllys 				break;
615d00756ccSwyllys 			case 'T':	/* token specifier */
616d00756ccSwyllys 				if (token_spec)
617d00756ccSwyllys 					return (PK_ERR_USAGE);
618d00756ccSwyllys 				token_spec = optarg_av;
619d00756ccSwyllys 				break;
620d00756ccSwyllys 			case 'l':	/* object with specific label */
621d00756ccSwyllys 				if (signkey)
622d00756ccSwyllys 					return (PK_ERR_USAGE);
623d00756ccSwyllys 				signkey = optarg_av;
624d00756ccSwyllys 				break;
625d00756ccSwyllys 			case 'e':
626d00756ccSwyllys 				if (ekustr != NULL)
627d00756ccSwyllys 					return (PK_ERR_USAGE);
628d00756ccSwyllys 				ekustr = optarg_av;
629d00756ccSwyllys 				break;
630d00756ccSwyllys 			case 'K':
631d00756ccSwyllys 				if (kustr != NULL)
632d00756ccSwyllys 					return (PK_ERR_USAGE);
633d00756ccSwyllys 				kustr = optarg_av;
634d00756ccSwyllys 				break;
635d00756ccSwyllys 			case 'F':
636d00756ccSwyllys 				if (format != NULL)
637d00756ccSwyllys 					return (PK_ERR_USAGE);
638d00756ccSwyllys 				format = optarg_av;
639d00756ccSwyllys 				break;
640d00756ccSwyllys 			case 'o':
641d00756ccSwyllys 				if (certfile != NULL)
642d00756ccSwyllys 					return (PK_ERR_USAGE);
643d00756ccSwyllys 				certfile = optarg_av;
644d00756ccSwyllys 				break;
645d00756ccSwyllys 			case 'L':
646d00756ccSwyllys 				if (lifetime != NULL)
647d00756ccSwyllys 					return (PK_ERR_USAGE);
648d00756ccSwyllys 				lifetime = optarg_av;
649d00756ccSwyllys 				break;
650d00756ccSwyllys 			case 'n':
651d00756ccSwyllys 				if (outlabel != NULL)
652d00756ccSwyllys 					return (PK_ERR_USAGE);
653d00756ccSwyllys 				outlabel = optarg_av;
654d00756ccSwyllys 				break;
655d00756ccSwyllys 			default:
656d00756ccSwyllys 				return (PK_ERR_USAGE);
657d00756ccSwyllys 		}
658d00756ccSwyllys 	}
659d00756ccSwyllys 	/* No additional args allowed. */
660d00756ccSwyllys 	argc -= optind_av;
661d00756ccSwyllys 	argv += optind_av;
662d00756ccSwyllys 	if (argc)
663d00756ccSwyllys 		return (PK_ERR_USAGE);
664d00756ccSwyllys 
665d00756ccSwyllys 
666d00756ccSwyllys 	/* Assume keystore = PKCS#11 if not specified. */
667d00756ccSwyllys 	if (kstype == 0)
668d00756ccSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
669d00756ccSwyllys 
670577f4726Swyllys 	DIR_OPTION_CHECK(kstype, dir);
671577f4726Swyllys 
672d00756ccSwyllys 	if (signkey == NULL) {
673d00756ccSwyllys 		(void) fprintf(stderr, gettext("The signing key label "
674d00756ccSwyllys 		    "or filename was not specified\n"));
675d00756ccSwyllys 		return (PK_ERR_USAGE);
676d00756ccSwyllys 	}
677d00756ccSwyllys 	if (csrfile == NULL) {
678d00756ccSwyllys 		(void) fprintf(stderr, gettext("The CSR filename was not"
679d00756ccSwyllys 		    " specified\n"));
680d00756ccSwyllys 		return (PK_ERR_USAGE);
681d00756ccSwyllys 	}
682d00756ccSwyllys 	if (certfile == NULL) {
683d00756ccSwyllys 		(void) fprintf(stderr, gettext("The output certificate file "
684d00756ccSwyllys 		    "was not specified\n"));
685d00756ccSwyllys 		return (PK_ERR_USAGE);
686d00756ccSwyllys 	}
687d00756ccSwyllys 	if (issuer == NULL) {
688d00756ccSwyllys 		(void) fprintf(stderr, gettext("The issuer DN "
689d00756ccSwyllys 		    "was not specified\n"));
690d00756ccSwyllys 		return (PK_ERR_USAGE);
691d00756ccSwyllys 	}
692d00756ccSwyllys 	if (lifetime != NULL) {
693d00756ccSwyllys 		if (Str2Lifetime(lifetime, &ltime) != 0) {
694d00756ccSwyllys 			cryptoerror(LOG_STDERR,
695d00756ccSwyllys 			    gettext("Error parsing lifetime string\n"));
696d00756ccSwyllys 			return (PK_ERR_USAGE);
697d00756ccSwyllys 		}
698d00756ccSwyllys 	}
699d00756ccSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) {
700d00756ccSwyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
701d00756ccSwyllys 	} else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) {
702d00756ccSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
703d00756ccSwyllys 	}
704d00756ccSwyllys 
705d00756ccSwyllys 	if (serstr != NULL) {
706d00756ccSwyllys 		uchar_t *bytes = NULL;
707d00756ccSwyllys 		size_t bytelen;
708d00756ccSwyllys 
709d00756ccSwyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
710d00756ccSwyllys 		if (rv != KMF_OK || bytes == NULL) {
711d00756ccSwyllys 			(void) fprintf(stderr, gettext("Serial number "
712d00756ccSwyllys 			    "must be specified as a hex number "
713d00756ccSwyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
714d00756ccSwyllys 			return (PK_ERR_USAGE);
715d00756ccSwyllys 		}
716d00756ccSwyllys 		serial.val = bytes;
717d00756ccSwyllys 		serial.len = bytelen;
718d00756ccSwyllys 	} else {
719d00756ccSwyllys 		(void) fprintf(stderr, gettext("The serial number was not"
720d00756ccSwyllys 		    " specified\n"));
721d00756ccSwyllys 		return (PK_ERR_USAGE);
722d00756ccSwyllys 	}
723d00756ccSwyllys 
724d00756ccSwyllys 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
725d00756ccSwyllys 	    kstype == KMF_KEYSTORE_NSS)) {
726d00756ccSwyllys 		/* Need to get password for private key access */
727d00756ccSwyllys 		(void) get_token_password(kstype, token_spec,
728d00756ccSwyllys 		    &tokencred);
729d00756ccSwyllys 	}
730448b8615Swyllys 	if (kustr != NULL) {
731448b8615Swyllys 		rv = verify_keyusage(kustr, &kubits, &kucrit);
732448b8615Swyllys 		if (rv != KMF_OK) {
733448b8615Swyllys 			(void) fprintf(stderr, gettext("KeyUsage "
734448b8615Swyllys 			    "must be specified as a comma-separated list. "
735448b8615Swyllys 			    "See the man page for details.\n"));
736448b8615Swyllys 			rv = PK_ERR_USAGE;
737448b8615Swyllys 			goto end;
738448b8615Swyllys 		}
739448b8615Swyllys 	}
740d00756ccSwyllys 	if (ekustr != NULL) {
741d00756ccSwyllys 		rv = verify_ekunames(ekustr, &ekulist);
742d00756ccSwyllys 		if (rv != KMF_OK) {
743d00756ccSwyllys 			(void) fprintf(stderr, gettext("EKUs must "
744d00756ccSwyllys 			    "be specified as a comma-separated list. "
745d00756ccSwyllys 			    "See the man page for details.\n"));
746d00756ccSwyllys 			rv = PK_ERR_USAGE;
747d00756ccSwyllys 			goto end;
748d00756ccSwyllys 		}
749d00756ccSwyllys 	}
750d00756ccSwyllys 	if (altname != NULL) {
751d00756ccSwyllys 		char *p;
752d00756ccSwyllys 		rv = verify_altname(altname, &alttype, &altcrit);
753d00756ccSwyllys 		if (rv != KMF_OK) {
754d00756ccSwyllys 			(void) fprintf(stderr, gettext("Subject AltName "
755d00756ccSwyllys 			    "must be specified as a name=value pair. "
756d00756ccSwyllys 			    "See the man page for details.\n"));
757d00756ccSwyllys 			rv = PK_ERR_USAGE;
758d00756ccSwyllys 			goto end;
759d00756ccSwyllys 		}
760d00756ccSwyllys 		/* advance the altname past the '=' sign */
761d00756ccSwyllys 		p = strchr(altname, '=');
762d00756ccSwyllys 		if (p != NULL)
763d00756ccSwyllys 			altname = p + 1;
764d00756ccSwyllys 	}
765d00756ccSwyllys 	if (format && (fmt = Str2Format(format)) == KMF_FORMAT_UNDEF) {
766d00756ccSwyllys 		cryptoerror(LOG_STDERR,
767d00756ccSwyllys 		    gettext("Error parsing format string (%s).\n"),
768d00756ccSwyllys 		    format);
769d00756ccSwyllys 		return (PK_ERR_USAGE);
770d00756ccSwyllys 	}
771d00756ccSwyllys 
772577f4726Swyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
773577f4726Swyllys 		return (rv);
774577f4726Swyllys 	}
775577f4726Swyllys 
776d00756ccSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN) {
777d00756ccSwyllys 		rv = pk_signcsr_pk11_nss(kmfhandle,
778d00756ccSwyllys 		    kstype, dir, prefix, token_spec, &tokencred,
779d00756ccSwyllys 		    signkey, csrfile, &serial, certfile, issuer, subject,
780d00756ccSwyllys 		    altname, alttype, altcrit, kubits, kucrit,
781d00756ccSwyllys 		    ekulist, ltime, fmt, store, outlabel);
782d00756ccSwyllys 
783d00756ccSwyllys 	} else if (kstype == KMF_KEYSTORE_NSS) {
784d00756ccSwyllys 		if (dir == NULL)
785d00756ccSwyllys 			dir = PK_DEFAULT_DIRECTORY;
786d00756ccSwyllys 
787d00756ccSwyllys 		rv = pk_signcsr_pk11_nss(kmfhandle,
788d00756ccSwyllys 		    kstype, dir, prefix, token_spec, &tokencred,
789d00756ccSwyllys 		    signkey, csrfile, &serial, certfile, issuer, subject,
790d00756ccSwyllys 		    altname, alttype, altcrit, kubits, kucrit,
791d00756ccSwyllys 		    ekulist, ltime, fmt, store, outlabel);
792d00756ccSwyllys 
793d00756ccSwyllys 	} else if (kstype == KMF_KEYSTORE_OPENSSL) {
794d00756ccSwyllys 		rv = pk_signcsr_files(kmfhandle,
795d00756ccSwyllys 		    signkey, csrfile, &serial, certfile, issuer, subject,
796d00756ccSwyllys 		    altname, alttype, altcrit, kubits, kucrit,
797d00756ccSwyllys 		    ekulist, ltime, fmt);
798d00756ccSwyllys 	}
799d00756ccSwyllys 
800d00756ccSwyllys end:
801d00756ccSwyllys 	if (rv != KMF_OK) {
802d00756ccSwyllys 		display_error(kmfhandle, rv,
803d00756ccSwyllys 		    gettext("Error listing objects"));
804d00756ccSwyllys 	}
805d00756ccSwyllys 
806d00756ccSwyllys 	if (serial.val != NULL)
807d00756ccSwyllys 		free(serial.val);
808d00756ccSwyllys 
809d00756ccSwyllys 	if (tokencred.cred != NULL)
810d00756ccSwyllys 		free(tokencred.cred);
811d00756ccSwyllys 
812d00756ccSwyllys 	free_eku_list(ekulist);
813d00756ccSwyllys 
814d00756ccSwyllys 	(void) kmf_finalize(kmfhandle);
815d00756ccSwyllys 	return (rv);
816d00756ccSwyllys }
817