xref: /titanic_52/usr/src/cmd/cmd-crypto/pktool/signcsr.c (revision e65e5c2d2f32a99e8c5f740cabae9075dab03ce7)
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  *
2172ca8cc9SWyllys Ingersoll  *
22*e65e5c2dSWyllys Ingersoll  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23d00756ccSwyllys  * Use is subject to license terms.
24d00756ccSwyllys  */
25d00756ccSwyllys 
26d00756ccSwyllys /*
27d00756ccSwyllys  * This file implements the sign CSR operation for this tool.
28d00756ccSwyllys  */
29d00756ccSwyllys 
30d00756ccSwyllys #include <stdio.h>
31d00756ccSwyllys #include <errno.h>
32d00756ccSwyllys #include <string.h>
33d00756ccSwyllys #include <cryptoutil.h>
34d00756ccSwyllys #include <security/cryptoki.h>
35d00756ccSwyllys #include "common.h"
36d00756ccSwyllys 
37d00756ccSwyllys #include <kmfapi.h>
38448b8615Swyllys #include <kmfapiP.h>
39448b8615Swyllys 
40d00756ccSwyllys #define	SET_VALUE(f, s) \
41d00756ccSwyllys 	rv = f; \
42d00756ccSwyllys 	if (rv != KMF_OK) { \
43d00756ccSwyllys 		cryptoerror(LOG_STDERR, \
44d00756ccSwyllys 		    gettext("Failed to set %s: 0x%02x\n"), s, rv); \
45d00756ccSwyllys 		goto cleanup; \
46d00756ccSwyllys 	}
47d00756ccSwyllys 
48d00756ccSwyllys 
49d00756ccSwyllys static int
50d00756ccSwyllys read_csrdata(KMF_HANDLE_T handle, char *csrfile, KMF_CSR_DATA *csrdata)
51d00756ccSwyllys {
52d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
53d00756ccSwyllys 	KMF_ENCODE_FORMAT csrfmt;
54d00756ccSwyllys 	KMF_DATA csrfiledata = {NULL, 0};
55d00756ccSwyllys 	KMF_DATA rawcsr = {NULL, 0};
56d00756ccSwyllys 
57d00756ccSwyllys 	rv = kmf_get_file_format(csrfile, &csrfmt);
58d00756ccSwyllys 	if (rv != KMF_OK)
59d00756ccSwyllys 		return (rv);
60d00756ccSwyllys 
61d00756ccSwyllys 	rv = kmf_read_input_file(handle, csrfile, &csrfiledata);
62d00756ccSwyllys 	if (rv != KMF_OK)
63d00756ccSwyllys 		return (rv);
64d00756ccSwyllys 
65d00756ccSwyllys 	if (csrfmt == KMF_FORMAT_PEM) {
66d00756ccSwyllys 		rv = kmf_pem_to_der(csrfiledata.Data, csrfiledata.Length,
67d00756ccSwyllys 		    &rawcsr.Data, (int *)&rawcsr.Length);
68d00756ccSwyllys 		if (rv != KMF_OK)
69d00756ccSwyllys 			return (rv);
70d00756ccSwyllys 
71d00756ccSwyllys 		kmf_free_data(&csrfiledata);
72d00756ccSwyllys 	} else {
73d00756ccSwyllys 		rawcsr.Data = csrfiledata.Data;
74d00756ccSwyllys 		rawcsr.Length = csrfiledata.Length;
75d00756ccSwyllys 	}
76d00756ccSwyllys 
77d00756ccSwyllys 	rv = kmf_decode_csr(handle, &rawcsr, csrdata);
78d00756ccSwyllys 	kmf_free_data(&rawcsr);
79d00756ccSwyllys 
80d00756ccSwyllys 	return (rv);
81d00756ccSwyllys }
82d00756ccSwyllys 
83448b8615Swyllys static KMF_RETURN
84448b8615Swyllys find_csr_extn(KMF_X509_EXTENSIONS *extnlist, KMF_OID *extoid,
85448b8615Swyllys 	KMF_X509_EXTENSION *outextn)
86448b8615Swyllys {
87448b8615Swyllys 	int i, found = 0;
88448b8615Swyllys 	KMF_X509_EXTENSION *eptr;
89448b8615Swyllys 	KMF_RETURN rv = KMF_OK;
90448b8615Swyllys 
91448b8615Swyllys 	(void) memset(outextn, 0, sizeof (KMF_X509_EXTENSION));
92448b8615Swyllys 	for (i = 0; !found && i < extnlist->numberOfExtensions; i++) {
93448b8615Swyllys 		eptr = &extnlist->extensions[i];
94448b8615Swyllys 		if (IsEqualOid(extoid, &eptr->extnId)) {
95448b8615Swyllys 			rv = copy_extension_data(outextn, eptr);
96448b8615Swyllys 			found++;
97448b8615Swyllys 		}
98448b8615Swyllys 	}
99448b8615Swyllys 	if (found == 0 || rv != KMF_OK)
100448b8615Swyllys 		return (1);
101448b8615Swyllys 	else
102448b8615Swyllys 		return (rv);
103448b8615Swyllys }
104448b8615Swyllys 
105d00756ccSwyllys static int
106d00756ccSwyllys build_cert_from_csr(KMF_CSR_DATA *csrdata,
107d00756ccSwyllys 	KMF_X509_CERTIFICATE *signedCert,
108d00756ccSwyllys 	KMF_BIGINT *serial,
109d00756ccSwyllys 	uint32_t ltime,
110d00756ccSwyllys 	char *issuer, char *subject,
111d00756ccSwyllys 	char *altname,
112d00756ccSwyllys 	KMF_GENERALNAMECHOICES alttype,
113d00756ccSwyllys 	int altcrit,
114d00756ccSwyllys 	uint16_t kubits,
115d00756ccSwyllys 	int kucrit,
116d00756ccSwyllys 	EKU_LIST *ekulist)
117d00756ccSwyllys {
118d00756ccSwyllys 	KMF_RETURN rv = KMF_OK;
119d00756ccSwyllys 	KMF_X509_NAME issuerDN, subjectDN;
120d00756ccSwyllys 
121d00756ccSwyllys 	/*
122d00756ccSwyllys 	 * If the CSR is ok, now we can generate the final certificate.
123d00756ccSwyllys 	 */
124d00756ccSwyllys 	(void) memset(signedCert, 0, sizeof (KMF_X509_CERTIFICATE));
125d00756ccSwyllys 	(void) memset(&issuerDN, 0, sizeof (issuerDN));
126d00756ccSwyllys 	(void) memset(&subjectDN, 0, sizeof (subjectDN));
127d00756ccSwyllys 
128d00756ccSwyllys 	SET_VALUE(kmf_set_cert_version(signedCert, 2), "version number");
129d00756ccSwyllys 
130d00756ccSwyllys 	SET_VALUE(kmf_set_cert_serial(signedCert, serial), "serial number");
131d00756ccSwyllys 
132d00756ccSwyllys 	SET_VALUE(kmf_set_cert_validity(signedCert, NULL, ltime),
133d00756ccSwyllys 	    "validity time");
134d00756ccSwyllys 
135d00756ccSwyllys 	if (issuer) {
136d00756ccSwyllys 		if (kmf_dn_parser(issuer, &issuerDN) != KMF_OK) {
137d00756ccSwyllys 			cryptoerror(LOG_STDERR,
138d00756ccSwyllys 			    gettext("Issuer name cannot be parsed\n"));
139d00756ccSwyllys 			return (PK_ERR_USAGE);
140d00756ccSwyllys 		}
141d00756ccSwyllys 		SET_VALUE(kmf_set_cert_issuer(signedCert, &issuerDN),
142d00756ccSwyllys 		    "Issuer Name");
143d00756ccSwyllys 	}
144d00756ccSwyllys 	if (subject) {
145d00756ccSwyllys 		if (kmf_dn_parser(subject, &subjectDN) != KMF_OK) {
146d00756ccSwyllys 			cryptoerror(LOG_STDERR,
147d00756ccSwyllys 			    gettext("Subject name cannot be parsed\n"));
148d00756ccSwyllys 			return (PK_ERR_USAGE);
149d00756ccSwyllys 		}
150d00756ccSwyllys 		SET_VALUE(kmf_set_cert_subject(signedCert, &subjectDN),
151d00756ccSwyllys 		    "Subject Name");
152d00756ccSwyllys 	} else {
153d00756ccSwyllys 		signedCert->certificate.subject = csrdata->csr.subject;
154d00756ccSwyllys 	}
155d00756ccSwyllys 
156d00756ccSwyllys 	signedCert->certificate.subjectPublicKeyInfo =
157d00756ccSwyllys 	    csrdata->csr.subjectPublicKeyInfo;
158d00756ccSwyllys 
159d00756ccSwyllys 	signedCert->certificate.extensions = csrdata->csr.extensions;
160d00756ccSwyllys 
161d00756ccSwyllys 	signedCert->certificate.signature =
162d00756ccSwyllys 	    csrdata->signature.algorithmIdentifier;
163d00756ccSwyllys 
164d00756ccSwyllys 	if (kubits != 0) {
165448b8615Swyllys 		KMF_X509_EXTENSION extn;
166448b8615Swyllys 		uint16_t oldbits;
167448b8615Swyllys 		/*
168448b8615Swyllys 		 * If the CSR already has KU, merge them.
169448b8615Swyllys 		 */
170448b8615Swyllys 		rv = find_csr_extn(&csrdata->csr.extensions,
171448b8615Swyllys 		    (KMF_OID *)&KMFOID_KeyUsage, &extn);
172448b8615Swyllys 		if (rv == KMF_OK) {
173448b8615Swyllys 			extn.critical |= kucrit;
174448b8615Swyllys 			if (extn.value.tagAndValue->value.Length > 1) {
175448b8615Swyllys 				oldbits =
176448b8615Swyllys 				    extn.value.tagAndValue->value.Data[1] << 8;
177448b8615Swyllys 			} else {
178448b8615Swyllys 				oldbits =
179448b8615Swyllys 				    extn.value.tagAndValue->value.Data[0];
180448b8615Swyllys 			}
181448b8615Swyllys 			oldbits |= kubits;
182448b8615Swyllys 		} else {
183d00756ccSwyllys 			SET_VALUE(kmf_set_cert_ku(signedCert, kucrit, kubits),
184d00756ccSwyllys 			    "KeyUsage");
185d00756ccSwyllys 		}
186448b8615Swyllys 	}
187d00756ccSwyllys 	if (altname != NULL) {
188d00756ccSwyllys 		SET_VALUE(kmf_set_cert_subject_altname(signedCert,
189d00756ccSwyllys 		    altcrit, alttype, altname), "subjectAltName");
190d00756ccSwyllys 	}
191d00756ccSwyllys 	if (ekulist != NULL) {
192d00756ccSwyllys 		int i;
193d00756ccSwyllys 		for (i = 0; rv == KMF_OK && i < ekulist->eku_count; i++) {
194d00756ccSwyllys 			SET_VALUE(kmf_add_cert_eku(signedCert,
195d00756ccSwyllys 			    &ekulist->ekulist[i],
196d00756ccSwyllys 			    ekulist->critlist[i]), "Extended Key Usage");
197d00756ccSwyllys 		}
198d00756ccSwyllys 	}
199d00756ccSwyllys cleanup:
200d00756ccSwyllys 	if (issuer != NULL)
201d00756ccSwyllys 		kmf_free_dn(&issuerDN);
202d00756ccSwyllys 	if (subject != NULL)
203d00756ccSwyllys 		kmf_free_dn(&subjectDN);
204d00756ccSwyllys 
205d00756ccSwyllys 	return (rv);
206d00756ccSwyllys }
207d00756ccSwyllys 
208d00756ccSwyllys static int
209d00756ccSwyllys pk_sign_cert(KMF_HANDLE_T handle, KMF_X509_CERTIFICATE *cert,
210d00756ccSwyllys 	KMF_KEY_HANDLE *key, KMF_DATA *outdata)
211d00756ccSwyllys {
212d00756ccSwyllys 	KMF_RETURN rv;
213d00756ccSwyllys 	int numattr;
214d00756ccSwyllys 	KMF_ATTRIBUTE attrlist[4];
215d00756ccSwyllys 
216d00756ccSwyllys 	numattr = 0;
217d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
218d00756ccSwyllys 	    &key->kstype, sizeof (KMF_KEYSTORE_TYPE));
219d00756ccSwyllys 	numattr++;
220d00756ccSwyllys 
221d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
222d00756ccSwyllys 	    key, sizeof (KMF_KEY_HANDLE_ATTR));
223d00756ccSwyllys 	numattr++;
224d00756ccSwyllys 
225d00756ccSwyllys 	/* cert data that is to be signed */
226d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_CERTIFICATE_ATTR,
227d00756ccSwyllys 	    cert, sizeof (KMF_X509_CERTIFICATE));
228d00756ccSwyllys 	numattr++;
229d00756ccSwyllys 
230d00756ccSwyllys 	/* output buffer for the signed cert */
231d00756ccSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_DATA_ATTR,
232d00756ccSwyllys 	    outdata, sizeof (KMF_DATA));
233d00756ccSwyllys 	numattr++;
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
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;
268d00756ccSwyllys 	KMF_DATA certdata = {NULL, 0};
269d00756ccSwyllys 	int numattr, count;
270d00756ccSwyllys 
271*e65e5c2dSWyllys Ingersoll 	(void) memset(&cakey, 0, sizeof (cakey));
272*e65e5c2dSWyllys Ingersoll 	(void) memset(&signedCert, 0, sizeof (signedCert));
273*e65e5c2dSWyllys 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 
335d00756ccSwyllys 	rv = pk_sign_cert(handle, &signedCert, &cakey, &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
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;
364d00756ccSwyllys 	KMF_DATA outcert = {NULL, 0};
365d00756ccSwyllys 	KMF_CSR_DATA csrdata;
366d00756ccSwyllys 	KMF_KEY_HANDLE casignkey;
367d00756ccSwyllys 	KMF_KEY_CLASS keyclass = KMF_ASYM_PRI;
368d00756ccSwyllys 	int numattr = 0;
369d00756ccSwyllys 	int keys = 1;
370d00756ccSwyllys 	KMF_ATTRIBUTE attrlist[16];
371d00756ccSwyllys 	KMF_X509_CERTIFICATE signedCert;
372d00756ccSwyllys 	boolean_t token_bool = B_TRUE;
373d00756ccSwyllys 	boolean_t private_bool = B_TRUE;
374d00756ccSwyllys 
37572ca8cc9SWyllys Ingersoll 	(void) memset(&casignkey, 0, sizeof (KMF_KEY_HANDLE));
376*e65e5c2dSWyllys 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 	/*
461d00756ccSwyllys 	 * If we found the key, now we can sign the cert.
462d00756ccSwyllys 	 */
463d00756ccSwyllys 	rv = pk_sign_cert(handle, &signedCert, &casignkey, &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
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;
551d00756ccSwyllys 	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