17711facfSdinak /*
27711facfSdinak  * CDDL HEADER START
37711facfSdinak  *
47711facfSdinak  * The contents of this file are subject to the terms of the
59e860378Sdinak  * Common Development and Distribution License (the "License").
69e860378Sdinak  * You may not use this file except in compliance with the License.
77711facfSdinak  *
87711facfSdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97711facfSdinak  * or http://www.opensolaris.org/os/licensing.
107711facfSdinak  * See the License for the specific language governing permissions
117711facfSdinak  * and limitations under the License.
127711facfSdinak  *
137711facfSdinak  * When distributing Covered Code, include this CDDL HEADER in each
147711facfSdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157711facfSdinak  * If applicable, add the following below this CDDL HEADER, with the
167711facfSdinak  * fields enclosed by brackets "[]" replaced with your own identifying
177711facfSdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
187711facfSdinak  *
197711facfSdinak  * CDDL HEADER END
20*99ebb4caSwyllys  *
21*99ebb4caSwyllys  *
229e860378Sdinak  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
237711facfSdinak  * Use is subject to license terms.
247711facfSdinak  */
257711facfSdinak 
267711facfSdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
277711facfSdinak 
287711facfSdinak /*
297711facfSdinak  * This file implements the export operation for this tool.
307711facfSdinak  * The basic flow of the process is to find the soft token,
317711facfSdinak  * log into it, find the PKCS#11 objects in the soft token
327711facfSdinak  * to be exported matching keys with their certificates, export
337711facfSdinak  * them to the PKCS#12 file encrypting them with a file password
347711facfSdinak  * if desired, and log out.
357711facfSdinak  */
367711facfSdinak 
377711facfSdinak #include <stdio.h>
387711facfSdinak #include <stdlib.h>
397711facfSdinak #include <string.h>
407711facfSdinak #include <errno.h>
41*99ebb4caSwyllys #include <fcntl.h>
427711facfSdinak #include "common.h"
437711facfSdinak 
44*99ebb4caSwyllys #include <kmfapi.h>
457711facfSdinak 
46*99ebb4caSwyllys static KMF_RETURN
47*99ebb4caSwyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *parms,
48*99ebb4caSwyllys 	KMF_X509_DER_CERT *cert)
497711facfSdinak {
50*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
51*99ebb4caSwyllys 	uint32_t numcerts = 0;
527711facfSdinak 
53*99ebb4caSwyllys 	numcerts = 0;
54*99ebb4caSwyllys 	(void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
55*99ebb4caSwyllys 	rv = KMF_FindCert(kmfhandle, parms, NULL, &numcerts);
56*99ebb4caSwyllys 	if (rv != KMF_OK) {
577711facfSdinak 		return (rv);
587711facfSdinak 	}
59*99ebb4caSwyllys 	if (numcerts == 0) {
60*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
61*99ebb4caSwyllys 			gettext("No matching certificates found."));
62*99ebb4caSwyllys 		return (KMF_ERR_CERT_NOT_FOUND);
637711facfSdinak 
64*99ebb4caSwyllys 	} else if (numcerts == 1) {
65*99ebb4caSwyllys 		rv = KMF_FindCert(kmfhandle, parms, cert, &numcerts);
667711facfSdinak 
67*99ebb4caSwyllys 	} else if (numcerts > 1) {
68*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
69*99ebb4caSwyllys 			gettext("%d certificates found, refine the "
70*99ebb4caSwyllys 			"search parameters to eliminate ambiguity\n"),
71*99ebb4caSwyllys 			numcerts);
72*99ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
737711facfSdinak 	}
74*99ebb4caSwyllys 	return (rv);
757711facfSdinak }
767711facfSdinak 
77*99ebb4caSwyllys static KMF_RETURN
78*99ebb4caSwyllys pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
79*99ebb4caSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
80*99ebb4caSwyllys 	KMF_ENCODE_FORMAT ofmt,
81*99ebb4caSwyllys 	char *dir, char *infile, char *filename)
827711facfSdinak {
83*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
84*99ebb4caSwyllys 	KMF_STORECERT_PARAMS scparms;
85*99ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
86*99ebb4caSwyllys 
87*99ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
88*99ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
89*99ebb4caSwyllys 		KMF_FINDCERT_PARAMS fcargs;
90*99ebb4caSwyllys 
91*99ebb4caSwyllys 		(void) memset(&fcargs, 0, sizeof (fcargs));
92*99ebb4caSwyllys 		fcargs.kstype = KMF_KEYSTORE_OPENSSL;
93*99ebb4caSwyllys 		fcargs.certLabel = NULL;
94*99ebb4caSwyllys 		fcargs.issuer = issuer;
95*99ebb4caSwyllys 		fcargs.subject = subject;
96*99ebb4caSwyllys 		fcargs.serial = serial;
97*99ebb4caSwyllys 		fcargs.sslparms.dirpath = dir;
98*99ebb4caSwyllys 		fcargs.sslparms.certfile = infile;
99*99ebb4caSwyllys 		fcargs.sslparms.format = ofmt;
100*99ebb4caSwyllys 
101*99ebb4caSwyllys 		rv = pk_find_export_cert(kmfhandle, &fcargs, &kmfcert);
102*99ebb4caSwyllys 		if (rv == KMF_OK) {
103*99ebb4caSwyllys 			(void) memset(&scparms, 0, sizeof (scparms));
104*99ebb4caSwyllys 			scparms.kstype = KMF_KEYSTORE_OPENSSL;
105*99ebb4caSwyllys 			scparms.sslparms.certfile = filename;
106*99ebb4caSwyllys 			rv = KMF_StoreCert(kmfhandle, &scparms,
107*99ebb4caSwyllys 				&kmfcert.certificate);
108*99ebb4caSwyllys 
109*99ebb4caSwyllys 			KMF_FreeKMFCert(kmfhandle, &kmfcert);
110*99ebb4caSwyllys 		}
111*99ebb4caSwyllys 	}
112*99ebb4caSwyllys 	return (rv);
1137711facfSdinak }
1147711facfSdinak 
115*99ebb4caSwyllys static KMF_RETURN
116*99ebb4caSwyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
117*99ebb4caSwyllys 	char *token_spec, char *dir, char *prefix,
118*99ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
119*99ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
120*99ebb4caSwyllys 	char *filename)
1217711facfSdinak {
122*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
123*99ebb4caSwyllys 	KMF_EXPORTP12_PARAMS p12parms;
1247711facfSdinak 
125*99ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
126*99ebb4caSwyllys 	if (rv != KMF_OK)
1277711facfSdinak 		return (rv);
1287711facfSdinak 
129*99ebb4caSwyllys 	(void) memset(&p12parms, 0, sizeof (p12parms));
130*99ebb4caSwyllys 	if (token_spec == NULL)
131*99ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
1327711facfSdinak 
133*99ebb4caSwyllys 	p12parms.kstype = KMF_KEYSTORE_NSS;
134*99ebb4caSwyllys 	p12parms.certLabel = certlabel;
135*99ebb4caSwyllys 	p12parms.issuer = issuer;
136*99ebb4caSwyllys 	p12parms.subject = subject;
137*99ebb4caSwyllys 	p12parms.serial = serial;
138*99ebb4caSwyllys 	p12parms.idstr = NULL;
139*99ebb4caSwyllys 	if (tokencred != NULL)
140*99ebb4caSwyllys 		p12parms.cred = *tokencred;
141*99ebb4caSwyllys 	p12parms.nssparms.slotlabel = token_spec;
1427711facfSdinak 
143*99ebb4caSwyllys 	(void) get_pk12_password(&p12parms.p12cred);
1447711facfSdinak 
145*99ebb4caSwyllys 	rv = KMF_ExportPK12(kmfhandle, &p12parms, filename);
146*99ebb4caSwyllys 	if (p12parms.p12cred.cred)
147*99ebb4caSwyllys 		free(p12parms.p12cred.cred);
1487711facfSdinak 
149*99ebb4caSwyllys 	return (rv);
1507711facfSdinak }
1517711facfSdinak 
152*99ebb4caSwyllys static KMF_RETURN
153*99ebb4caSwyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
154*99ebb4caSwyllys 	char *certfile, char *keyfile, char *dir,
155*99ebb4caSwyllys 	char *outfile)
1567711facfSdinak {
157*99ebb4caSwyllys 	KMF_RETURN rv;
158*99ebb4caSwyllys 	KMF_EXPORTP12_PARAMS p12parms;
1597711facfSdinak 
160*99ebb4caSwyllys 	(void) memset(&p12parms, 0, sizeof (p12parms));
1617711facfSdinak 
162*99ebb4caSwyllys 	p12parms.kstype = KMF_KEYSTORE_OPENSSL;
163*99ebb4caSwyllys 	p12parms.certLabel = NULL;
164*99ebb4caSwyllys 	p12parms.issuer = NULL;
165*99ebb4caSwyllys 	p12parms.subject = NULL;
166*99ebb4caSwyllys 	p12parms.serial = 0;
167*99ebb4caSwyllys 	p12parms.idstr = NULL;
168*99ebb4caSwyllys 	p12parms.sslparms.dirpath = dir;
169*99ebb4caSwyllys 	p12parms.sslparms.certfile = certfile;
170*99ebb4caSwyllys 	p12parms.sslparms.keyfile = keyfile;
1717711facfSdinak 
172*99ebb4caSwyllys 	(void) get_pk12_password(&p12parms.p12cred);
1737711facfSdinak 
174*99ebb4caSwyllys 	rv = KMF_ExportPK12(kmfhandle, &p12parms, outfile);
1757711facfSdinak 
176*99ebb4caSwyllys 	if (p12parms.p12cred.cred)
177*99ebb4caSwyllys 		free(p12parms.p12cred.cred);
1787711facfSdinak 
179*99ebb4caSwyllys 	return (rv);
1807711facfSdinak }
1817711facfSdinak 
182*99ebb4caSwyllys static KMF_RETURN
183*99ebb4caSwyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
184*99ebb4caSwyllys 	int oclass, char *certlabel, char *issuer, char *subject,
185*99ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
186*99ebb4caSwyllys 	char *prefix, char *filename)
1877711facfSdinak {
188*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
189*99ebb4caSwyllys 	KMF_STORECERT_PARAMS scparms;
190*99ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
1917711facfSdinak 
192*99ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
193*99ebb4caSwyllys 	if (rv != KMF_OK)
1947711facfSdinak 		return (rv);
1957711facfSdinak 
196*99ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
197*99ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
198*99ebb4caSwyllys 		KMF_FINDCERT_PARAMS fcargs;
199*99ebb4caSwyllys 
200*99ebb4caSwyllys 		(void) memset(&fcargs, 0, sizeof (fcargs));
201*99ebb4caSwyllys 		fcargs.kstype = KMF_KEYSTORE_NSS;
202*99ebb4caSwyllys 		fcargs.certLabel = certlabel;
203*99ebb4caSwyllys 		fcargs.issuer = issuer;
204*99ebb4caSwyllys 		fcargs.subject = subject;
205*99ebb4caSwyllys 		fcargs.serial = serial;
206*99ebb4caSwyllys 		fcargs.nssparms.slotlabel = token_spec;
207*99ebb4caSwyllys 
208*99ebb4caSwyllys 		rv = pk_find_export_cert(kmfhandle, &fcargs, &kmfcert);
209*99ebb4caSwyllys 		if (rv == KMF_OK) {
210*99ebb4caSwyllys 			(void) memset(&scparms, 0, sizeof (scparms));
211*99ebb4caSwyllys 			scparms.kstype = KMF_KEYSTORE_OPENSSL;
212*99ebb4caSwyllys 			scparms.sslparms.certfile = filename;
213*99ebb4caSwyllys 			scparms.sslparms.format = kfmt;
214*99ebb4caSwyllys 
215*99ebb4caSwyllys 			rv = KMF_StoreCert(kmfhandle, &scparms,
216*99ebb4caSwyllys 				&kmfcert.certificate);
217*99ebb4caSwyllys 
218*99ebb4caSwyllys 			KMF_FreeKMFCert(kmfhandle, &kmfcert);
2197711facfSdinak 		}
2207711facfSdinak 	}
221*99ebb4caSwyllys 	return (rv);
222*99ebb4caSwyllys }
2237711facfSdinak 
224*99ebb4caSwyllys static KMF_RETURN
225*99ebb4caSwyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
226*99ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
227*99ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
228*99ebb4caSwyllys {
229*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
230*99ebb4caSwyllys 	KMF_EXPORTP12_PARAMS p12parms;
2317711facfSdinak 
232*99ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
233*99ebb4caSwyllys 	if (rv != KMF_OK) {
234*99ebb4caSwyllys 		return (rv);
2357711facfSdinak 	}
2367711facfSdinak 
237*99ebb4caSwyllys 	(void) memset(&p12parms, 0, sizeof (p12parms));
2387711facfSdinak 
239*99ebb4caSwyllys 	p12parms.kstype = KMF_KEYSTORE_PK11TOKEN;
240*99ebb4caSwyllys 	p12parms.certLabel = certlabel;
241*99ebb4caSwyllys 	p12parms.issuer = issuer;
242*99ebb4caSwyllys 	p12parms.subject = subject;
243*99ebb4caSwyllys 	p12parms.serial = serial;
244*99ebb4caSwyllys 	p12parms.idstr = NULL;
245*99ebb4caSwyllys 	if (tokencred != NULL)
246*99ebb4caSwyllys 		p12parms.cred = *tokencred;
247*99ebb4caSwyllys 	(void) get_pk12_password(&p12parms.p12cred);
2487711facfSdinak 
249*99ebb4caSwyllys 	rv = KMF_ExportPK12(kmfhandle, &p12parms, filename);
2507711facfSdinak 
251*99ebb4caSwyllys 	if (p12parms.p12cred.cred)
252*99ebb4caSwyllys 		free(p12parms.p12cred.cred);
2537711facfSdinak 
254*99ebb4caSwyllys 	return (rv);
2557711facfSdinak }
2567711facfSdinak 
257*99ebb4caSwyllys static KMF_RETURN
258*99ebb4caSwyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
259*99ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
260*99ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
261*99ebb4caSwyllys 	char *filename)
2627711facfSdinak {
263*99ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
264*99ebb4caSwyllys 	KMF_FINDCERT_PARAMS fcparms;
265*99ebb4caSwyllys 	KMF_STORECERT_PARAMS scparms;
266*99ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
2677711facfSdinak 
268*99ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
2697711facfSdinak 
270*99ebb4caSwyllys 	if (rv != KMF_OK) {
2717711facfSdinak 		return (rv);
2727711facfSdinak 	}
2737711facfSdinak 
274*99ebb4caSwyllys 	(void) memset(&fcparms, 0, sizeof (fcparms));
275*99ebb4caSwyllys 	fcparms.kstype = KMF_KEYSTORE_PK11TOKEN;
276*99ebb4caSwyllys 	fcparms.certLabel = certlabel;
277*99ebb4caSwyllys 	fcparms.issuer = issuer;
278*99ebb4caSwyllys 	fcparms.subject = subject;
279*99ebb4caSwyllys 	fcparms.serial = serial;
2807711facfSdinak 
281*99ebb4caSwyllys 	rv = pk_find_export_cert(kmfhandle, &fcparms, &kmfcert);
2827711facfSdinak 
283*99ebb4caSwyllys 	if (rv == KMF_OK) {
284*99ebb4caSwyllys 		(void) memset(&scparms, 0, sizeof (scparms));
285*99ebb4caSwyllys 		scparms.kstype = KMF_KEYSTORE_OPENSSL;
286*99ebb4caSwyllys 		scparms.sslparms.certfile = filename;
287*99ebb4caSwyllys 		scparms.sslparms.format = kfmt;
2887711facfSdinak 
289*99ebb4caSwyllys 		rv = KMF_StoreCert(kmfhandle, &scparms,
290*99ebb4caSwyllys 			&kmfcert.certificate);
2917711facfSdinak 
292*99ebb4caSwyllys 		KMF_FreeKMFCert(kmfhandle, &kmfcert);
2937711facfSdinak 	}
294*99ebb4caSwyllys 	return (rv);
2957711facfSdinak }
2967711facfSdinak 
2977711facfSdinak /*
298*99ebb4caSwyllys  * Export objects from one keystore to a file.
2997711facfSdinak  */
3007711facfSdinak int
3017711facfSdinak pk_export(int argc, char *argv[])
3027711facfSdinak {
30349e21299Sdinak 	int		opt;
30449e21299Sdinak 	extern int	optind_av;
30549e21299Sdinak 	extern char	*optarg_av;
30649e21299Sdinak 	char		*token_spec = NULL;
3077711facfSdinak 	char		*filename = NULL;
308*99ebb4caSwyllys 	char		*dir = NULL;
309*99ebb4caSwyllys 	char		*prefix = NULL;
310*99ebb4caSwyllys 	char		*certlabel = NULL;
311*99ebb4caSwyllys 	char		*subject = NULL;
312*99ebb4caSwyllys 	char		*issuer = NULL;
313*99ebb4caSwyllys 	char		*infile = NULL;
314*99ebb4caSwyllys 	char		*keyfile = NULL;
315*99ebb4caSwyllys 	char		*certfile = NULL;
316*99ebb4caSwyllys 	char		*serstr = NULL;
317*99ebb4caSwyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
318*99ebb4caSwyllys 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
319*99ebb4caSwyllys 	KMF_RETURN		rv = KMF_OK;
320*99ebb4caSwyllys 	int		oclass = PK_CERT_OBJ;
321*99ebb4caSwyllys 	KMF_BIGINT	serial = { NULL, 0 };
322*99ebb4caSwyllys 	KMF_HANDLE_T	kmfhandle = NULL;
323*99ebb4caSwyllys 	KMF_CREDENTIAL	tokencred = {NULL, 0};
3247711facfSdinak 
32549e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
326*99ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
327*99ebb4caSwyllys 		"k:(keystore)y:(objtype)T:(token)"
328*99ebb4caSwyllys 		"d:(dir)p:(prefix)"
329*99ebb4caSwyllys 		"l:(label)n:(nickname)s:(subject)"
330*99ebb4caSwyllys 		"i:(issuer)S:(serial)"
331*99ebb4caSwyllys 		"K:(keyfile)c:(certfile)"
332*99ebb4caSwyllys 		"F:(outformat)"
333*99ebb4caSwyllys 		"I:(infile)o:(outfile)")) != EOF) {
334*99ebb4caSwyllys 		if (EMPTYSTRING(optarg_av))
335*99ebb4caSwyllys 			return (PK_ERR_USAGE);
33649e21299Sdinak 		switch (opt) {
337*99ebb4caSwyllys 		case 'k':
338*99ebb4caSwyllys 			kstype = KS2Int(optarg_av);
339*99ebb4caSwyllys 			if (kstype == 0)
340*99ebb4caSwyllys 				return (PK_ERR_USAGE);
341*99ebb4caSwyllys 			break;
342*99ebb4caSwyllys 		case 'y':
343*99ebb4caSwyllys 			oclass = OT2Int(optarg_av);
344*99ebb4caSwyllys 			if (oclass == -1)
345*99ebb4caSwyllys 				return (PK_ERR_USAGE);
346*99ebb4caSwyllys 			break;
34749e21299Sdinak 		case 'T':	/* token specifier */
34849e21299Sdinak 			if (token_spec)
34949e21299Sdinak 				return (PK_ERR_USAGE);
35049e21299Sdinak 			token_spec = optarg_av;
35149e21299Sdinak 			break;
352*99ebb4caSwyllys 		case 'd':
353*99ebb4caSwyllys 			if (dir)
354*99ebb4caSwyllys 				return (PK_ERR_USAGE);
355*99ebb4caSwyllys 			dir = optarg_av;
356*99ebb4caSwyllys 			break;
357*99ebb4caSwyllys 		case 'p':
358*99ebb4caSwyllys 			if (prefix)
359*99ebb4caSwyllys 				return (PK_ERR_USAGE);
360*99ebb4caSwyllys 			prefix = optarg_av;
361*99ebb4caSwyllys 			break;
362*99ebb4caSwyllys 		case 'n':
363*99ebb4caSwyllys 		case 'l':
364*99ebb4caSwyllys 			if (certlabel)
365*99ebb4caSwyllys 				return (PK_ERR_USAGE);
366*99ebb4caSwyllys 			certlabel = optarg_av;
367*99ebb4caSwyllys 			break;
368*99ebb4caSwyllys 		case 's':
369*99ebb4caSwyllys 			if (subject)
370*99ebb4caSwyllys 				return (PK_ERR_USAGE);
371*99ebb4caSwyllys 			subject = optarg_av;
372*99ebb4caSwyllys 			break;
373*99ebb4caSwyllys 		case 'i':
374*99ebb4caSwyllys 			if (issuer)
375*99ebb4caSwyllys 				return (PK_ERR_USAGE);
376*99ebb4caSwyllys 			issuer = optarg_av;
377*99ebb4caSwyllys 			break;
378*99ebb4caSwyllys 		case 'S':
379*99ebb4caSwyllys 			serstr = optarg_av;
380*99ebb4caSwyllys 			break;
381*99ebb4caSwyllys 		case 'F':
382*99ebb4caSwyllys 			kfmt = Str2Format(optarg_av);
383*99ebb4caSwyllys 			if (kfmt == KMF_FORMAT_UNDEF)
384*99ebb4caSwyllys 				return (PK_ERR_USAGE);
385*99ebb4caSwyllys 			break;
386*99ebb4caSwyllys 		case 'I':	/* output file name */
387*99ebb4caSwyllys 			if (infile)
388*99ebb4caSwyllys 				return (PK_ERR_USAGE);
389*99ebb4caSwyllys 			infile = optarg_av;
390*99ebb4caSwyllys 			break;
39149e21299Sdinak 		case 'o':	/* output file name */
39249e21299Sdinak 			if (filename)
39349e21299Sdinak 				return (PK_ERR_USAGE);
39449e21299Sdinak 			filename = optarg_av;
39549e21299Sdinak 			break;
396*99ebb4caSwyllys 		case 'c':	/* input cert file name */
397*99ebb4caSwyllys 			if (certfile)
398*99ebb4caSwyllys 				return (PK_ERR_USAGE);
399*99ebb4caSwyllys 			certfile = optarg_av;
400*99ebb4caSwyllys 			break;
401*99ebb4caSwyllys 		case 'K':	/* input key file name */
402*99ebb4caSwyllys 			if (keyfile)
403*99ebb4caSwyllys 				return (PK_ERR_USAGE);
404*99ebb4caSwyllys 			keyfile = optarg_av;
405*99ebb4caSwyllys 			break;
40649e21299Sdinak 		default:
40749e21299Sdinak 			return (PK_ERR_USAGE);
40849e21299Sdinak 			break;
40949e21299Sdinak 		}
41049e21299Sdinak 	}
4117711facfSdinak 
412*99ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified */
413*99ebb4caSwyllys 	if (kstype == 0)
414*99ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
41549e21299Sdinak 
41649e21299Sdinak 	/* Filename arg is required. */
417*99ebb4caSwyllys 	if (EMPTYSTRING(filename)) {
418*99ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("You must specify "
419*99ebb4caSwyllys 			"an 'outfile' parameter when exporting.\n"));
4207711facfSdinak 		return (PK_ERR_USAGE);
421*99ebb4caSwyllys 	}
4227711facfSdinak 
42349e21299Sdinak 	/* No additional args allowed. */
42449e21299Sdinak 	argc -= optind_av;
42549e21299Sdinak 	argv += optind_av;
42649e21299Sdinak 	if (argc)
42749e21299Sdinak 		return (PK_ERR_USAGE);
428*99ebb4caSwyllys 
429*99ebb4caSwyllys 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
430*99ebb4caSwyllys 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
431*99ebb4caSwyllys 		kstype != KMF_KEYSTORE_PK11TOKEN) {
432*99ebb4caSwyllys 
433*99ebb4caSwyllys 		(void) fprintf(stderr, gettext("The objtype parameter "
434*99ebb4caSwyllys 			"is only relevant if keystore=pkcs11\n"));
435*99ebb4caSwyllys 		return (PK_ERR_USAGE);
436*99ebb4caSwyllys 	}
437*99ebb4caSwyllys 
438*99ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
439*99ebb4caSwyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
440*99ebb4caSwyllys 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
441*99ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
442*99ebb4caSwyllys 
443*99ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_OPENSSL) {
444*99ebb4caSwyllys 		if (kfmt != KMF_FORMAT_PKCS12) {
445*99ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
446*99ebb4caSwyllys 				"is the only export format "
447*99ebb4caSwyllys 				"supported for the 'file' "
448*99ebb4caSwyllys 				"keystore.\n"));
449*99ebb4caSwyllys 			return (PK_ERR_USAGE);
450*99ebb4caSwyllys 		}
451*99ebb4caSwyllys 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
452*99ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A cert file"
453*99ebb4caSwyllys 				"and a key file must be specified "
454*99ebb4caSwyllys 				"when exporting to PKCS12 from the "
455*99ebb4caSwyllys 				"'file' keystore.\n"));
456*99ebb4caSwyllys 			return (PK_ERR_USAGE);
457*99ebb4caSwyllys 		}
458*99ebb4caSwyllys 	}
4597711facfSdinak 
4607711facfSdinak 	/* Check if the file exists and might be overwritten. */
4617711facfSdinak 	if (access(filename, F_OK) == 0) {
462*99ebb4caSwyllys 		cryptoerror(LOG_STDERR,
463*99ebb4caSwyllys 			gettext("Warning: file \"%s\" exists, "
464*99ebb4caSwyllys 				"will be overwritten."), filename);
4657711facfSdinak 		if (yesno(gettext("Continue with export? "),
4667711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
4677711facfSdinak 			return (0);
4687711facfSdinak 		}
469*99ebb4caSwyllys 	} else {
470*99ebb4caSwyllys 		rv = verify_file(filename);
471*99ebb4caSwyllys 		if (rv != KMF_OK) {
472*99ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("The file (%s) "
473*99ebb4caSwyllys 				"cannot be created.\n"), filename);
474*99ebb4caSwyllys 			return (PK_ERR_USAGE);
475*99ebb4caSwyllys 		}
4767711facfSdinak 	}
4777711facfSdinak 
478*99ebb4caSwyllys 	if (serstr != NULL) {
479*99ebb4caSwyllys 		uchar_t *bytes = NULL;
480*99ebb4caSwyllys 		size_t bytelen;
4817711facfSdinak 
482*99ebb4caSwyllys 		rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen);
483*99ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
484*99ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
485*99ebb4caSwyllys 				"must be specified as a hex number "
486*99ebb4caSwyllys 				"(ex: 0x0102030405ffeeddee)\n"));
487*99ebb4caSwyllys 			return (PK_ERR_USAGE);
488*99ebb4caSwyllys 		}
489*99ebb4caSwyllys 		serial.val = bytes;
490*99ebb4caSwyllys 		serial.len = bytelen;
4917711facfSdinak 	}
4927711facfSdinak 
493*99ebb4caSwyllys 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
494*99ebb4caSwyllys 		kstype == KMF_KEYSTORE_NSS) &&
495*99ebb4caSwyllys 		(oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) ||
496*99ebb4caSwyllys 		kfmt == KMF_FORMAT_PKCS12)) {
497*99ebb4caSwyllys 			(void) get_token_password(kstype, token_spec,
498*99ebb4caSwyllys 				&tokencred);
4997711facfSdinak 	}
5007711facfSdinak 
501*99ebb4caSwyllys 	if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
502*99ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing "
503*99ebb4caSwyllys 				"KMF: 0x%02x\n"), rv);
504*99ebb4caSwyllys 		return (rv);
5057711facfSdinak 	}
5067711facfSdinak 
507*99ebb4caSwyllys 	switch (kstype) {
508*99ebb4caSwyllys 		case KMF_KEYSTORE_PK11TOKEN:
509*99ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
510*99ebb4caSwyllys 				rv = pk_export_pk12_pk11(
511*99ebb4caSwyllys 					kmfhandle,
512*99ebb4caSwyllys 					token_spec,
513*99ebb4caSwyllys 					certlabel,
514*99ebb4caSwyllys 					issuer, subject,
515*99ebb4caSwyllys 					&serial, &tokencred,
516*99ebb4caSwyllys 					filename);
517*99ebb4caSwyllys 			else
518*99ebb4caSwyllys 				rv = pk_export_pk11_objects(kmfhandle,
519*99ebb4caSwyllys 					token_spec,
520*99ebb4caSwyllys 					certlabel,
521*99ebb4caSwyllys 					issuer, subject,
522*99ebb4caSwyllys 					&serial, kfmt,
523*99ebb4caSwyllys 					filename);
524*99ebb4caSwyllys 			break;
525*99ebb4caSwyllys 		case KMF_KEYSTORE_NSS:
526*99ebb4caSwyllys 			if (dir == NULL)
527*99ebb4caSwyllys 				dir = PK_DEFAULT_DIRECTORY;
528*99ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
529*99ebb4caSwyllys 				rv = pk_export_pk12_nss(kmfhandle,
530*99ebb4caSwyllys 					token_spec, dir, prefix,
531*99ebb4caSwyllys 					certlabel, issuer,
532*99ebb4caSwyllys 					subject, &serial,
533*99ebb4caSwyllys 					&tokencred, filename);
534*99ebb4caSwyllys 			else
535*99ebb4caSwyllys 				rv = pk_export_nss_objects(kmfhandle,
536*99ebb4caSwyllys 					token_spec,
537*99ebb4caSwyllys 					oclass, certlabel, issuer, subject,
538*99ebb4caSwyllys 					&serial, kfmt, dir, prefix, filename);
539*99ebb4caSwyllys 			break;
540*99ebb4caSwyllys 		case KMF_KEYSTORE_OPENSSL:
541*99ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
542*99ebb4caSwyllys 				rv = pk_export_pk12_files(kmfhandle,
543*99ebb4caSwyllys 					certfile, keyfile, dir,
544*99ebb4caSwyllys 					filename);
545*99ebb4caSwyllys 			else
546*99ebb4caSwyllys 				rv = pk_export_file_objects(kmfhandle, oclass,
547*99ebb4caSwyllys 					issuer, subject, &serial, kfmt,
548*99ebb4caSwyllys 					dir, infile, filename);
549*99ebb4caSwyllys 			break;
550*99ebb4caSwyllys 		default:
551*99ebb4caSwyllys 			rv = PK_ERR_USAGE;
552*99ebb4caSwyllys 			break;
5537711facfSdinak 	}
5547711facfSdinak 
555*99ebb4caSwyllys 	if (rv != KMF_OK) {
556*99ebb4caSwyllys 		display_error(kmfhandle, rv,
557*99ebb4caSwyllys 			gettext("Error exporting objects"));
5587711facfSdinak 	}
5597711facfSdinak 
560*99ebb4caSwyllys 	if (serial.val != NULL)
561*99ebb4caSwyllys 		free(serial.val);
5627711facfSdinak 
563*99ebb4caSwyllys 	(void) KMF_Finalize(kmfhandle);
5647711facfSdinak 
565*99ebb4caSwyllys 	return (rv);
5667711facfSdinak }
567