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
2099ebb4caSwyllys  *
2199ebb4caSwyllys  *
22*30a5e8faSwyllys  * Copyright 2007 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>
4199ebb4caSwyllys #include <fcntl.h>
427711facfSdinak #include "common.h"
437711facfSdinak 
4499ebb4caSwyllys #include <kmfapi.h>
457711facfSdinak 
4699ebb4caSwyllys static KMF_RETURN
47*30a5e8faSwyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist,
48*30a5e8faSwyllys 	int numattr, KMF_X509_DER_CERT *cert)
497711facfSdinak {
5099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
5199ebb4caSwyllys 	uint32_t numcerts = 0;
527711facfSdinak 
5399ebb4caSwyllys 	numcerts = 0;
5499ebb4caSwyllys 	(void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
55*30a5e8faSwyllys 
56*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
57*30a5e8faSwyllys 	    &numcerts, sizeof (uint32_t));
58*30a5e8faSwyllys 	numattr++;
59*30a5e8faSwyllys 
60*30a5e8faSwyllys 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
6199ebb4caSwyllys 	if (rv != KMF_OK) {
627711facfSdinak 		return (rv);
637711facfSdinak 	}
6499ebb4caSwyllys 	if (numcerts == 0) {
6599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
66*30a5e8faSwyllys 		    gettext("No matching certificates found."));
6799ebb4caSwyllys 		return (KMF_ERR_CERT_NOT_FOUND);
687711facfSdinak 
6999ebb4caSwyllys 	} else if (numcerts == 1) {
70*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
71*30a5e8faSwyllys 		    KMF_X509_DER_CERT_ATTR, cert,
72*30a5e8faSwyllys 		    sizeof (KMF_X509_DER_CERT));
73*30a5e8faSwyllys 		numattr++;
74*30a5e8faSwyllys 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
757711facfSdinak 
7699ebb4caSwyllys 	} else if (numcerts > 1) {
7799ebb4caSwyllys 		cryptoerror(LOG_STDERR,
78*30a5e8faSwyllys 		    gettext("%d certificates found, refine the "
79*30a5e8faSwyllys 		    "search parameters to eliminate ambiguity\n"),
80*30a5e8faSwyllys 		    numcerts);
8199ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
827711facfSdinak 	}
8399ebb4caSwyllys 	return (rv);
847711facfSdinak }
857711facfSdinak 
8699ebb4caSwyllys static KMF_RETURN
8799ebb4caSwyllys pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
8899ebb4caSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
8999ebb4caSwyllys 	char *dir, char *infile, char *filename)
907711facfSdinak {
9199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
9299ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
93*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
94*30a5e8faSwyllys 	int numattr = 0;
95*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
9699ebb4caSwyllys 
9799ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
9899ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
99*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
100*30a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
101*30a5e8faSwyllys 		    sizeof (kstype));
102*30a5e8faSwyllys 		numattr++;
103*30a5e8faSwyllys 
104*30a5e8faSwyllys 		if (issuer != NULL) {
105*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
106*30a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
107*30a5e8faSwyllys 			    strlen(issuer));
108*30a5e8faSwyllys 			numattr++;
109*30a5e8faSwyllys 		}
110*30a5e8faSwyllys 
111*30a5e8faSwyllys 		if (subject != NULL) {
112*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
113*30a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
114*30a5e8faSwyllys 			    strlen(subject));
115*30a5e8faSwyllys 			numattr++;
116*30a5e8faSwyllys 		}
117*30a5e8faSwyllys 
118*30a5e8faSwyllys 		if (serial != NULL) {
119*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
120*30a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
121*30a5e8faSwyllys 			    sizeof (KMF_BIGINT));
122*30a5e8faSwyllys 			numattr++;
123*30a5e8faSwyllys 		}
124*30a5e8faSwyllys 
125*30a5e8faSwyllys 		if (dir != NULL) {
126*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
127*30a5e8faSwyllys 			    KMF_DIRPATH_ATTR, dir,
128*30a5e8faSwyllys 			    strlen(dir));
129*30a5e8faSwyllys 			numattr++;
130*30a5e8faSwyllys 		}
131*30a5e8faSwyllys 
132*30a5e8faSwyllys 		if (infile != NULL) {
133*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
134*30a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, infile,
135*30a5e8faSwyllys 			    strlen(infile));
136*30a5e8faSwyllys 			numattr++;
137*30a5e8faSwyllys 		}
138*30a5e8faSwyllys 
139*30a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
140*30a5e8faSwyllys 		    &kmfcert);
14199ebb4caSwyllys 		if (rv == KMF_OK) {
142*30a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
143*30a5e8faSwyllys 			numattr = 0;
14499ebb4caSwyllys 
145*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
146*30a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
147*30a5e8faSwyllys 			numattr++;
148*30a5e8faSwyllys 
149*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
150*30a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
151*30a5e8faSwyllys 			    sizeof (KMF_DATA));
152*30a5e8faSwyllys 			numattr++;
153*30a5e8faSwyllys 
154*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
155*30a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
156*30a5e8faSwyllys 			    strlen(filename));
157*30a5e8faSwyllys 			numattr++;
158*30a5e8faSwyllys 
159*30a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr,
160*30a5e8faSwyllys 			    attrlist);
161*30a5e8faSwyllys 
162*30a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
16399ebb4caSwyllys 		}
16499ebb4caSwyllys 	}
16599ebb4caSwyllys 	return (rv);
1667711facfSdinak }
1677711facfSdinak 
16899ebb4caSwyllys static KMF_RETURN
16999ebb4caSwyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
17099ebb4caSwyllys 	char *token_spec, char *dir, char *prefix,
17199ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
17299ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
17399ebb4caSwyllys 	char *filename)
1747711facfSdinak {
17599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
176*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
177*30a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
178*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
179*30a5e8faSwyllys 	int numattr = 0;
1807711facfSdinak 
18199ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
18299ebb4caSwyllys 	if (rv != KMF_OK)
1837711facfSdinak 		return (rv);
1847711facfSdinak 
18599ebb4caSwyllys 	if (token_spec == NULL)
18699ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
1877711facfSdinak 
188*30a5e8faSwyllys 	kstype = KMF_KEYSTORE_NSS;
189*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
190*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
191*30a5e8faSwyllys 	numattr++;
192*30a5e8faSwyllys 
193*30a5e8faSwyllys 	if (certlabel != NULL) {
194*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
195*30a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
196*30a5e8faSwyllys 		numattr++;
197*30a5e8faSwyllys 	}
198*30a5e8faSwyllys 
199*30a5e8faSwyllys 	if (issuer != NULL) {
200*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
201*30a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
202*30a5e8faSwyllys 		numattr++;
203*30a5e8faSwyllys 	}
204*30a5e8faSwyllys 
205*30a5e8faSwyllys 	if (subject != NULL) {
206*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
207*30a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
208*30a5e8faSwyllys 		numattr++;
209*30a5e8faSwyllys 	}
2107711facfSdinak 
211*30a5e8faSwyllys 	if (serial != NULL) {
212*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
213*30a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
214*30a5e8faSwyllys 		numattr++;
215*30a5e8faSwyllys 	}
2167711facfSdinak 
217*30a5e8faSwyllys 	if (tokencred != NULL) {
218*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
219*30a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
220*30a5e8faSwyllys 		numattr++;
221*30a5e8faSwyllys 	}
222*30a5e8faSwyllys 
223*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
224*30a5e8faSwyllys 	    token_spec, strlen(token_spec));
225*30a5e8faSwyllys 	numattr++;
226*30a5e8faSwyllys 
227*30a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
228*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
229*30a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
230*30a5e8faSwyllys 	numattr++;
231*30a5e8faSwyllys 
232*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
233*30a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
234*30a5e8faSwyllys 	numattr++;
235*30a5e8faSwyllys 
236*30a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
237*30a5e8faSwyllys 
238*30a5e8faSwyllys 	if (p12cred.cred)
239*30a5e8faSwyllys 		free(p12cred.cred);
2407711facfSdinak 
24199ebb4caSwyllys 	return (rv);
2427711facfSdinak }
2437711facfSdinak 
24499ebb4caSwyllys static KMF_RETURN
24599ebb4caSwyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
24699ebb4caSwyllys 	char *certfile, char *keyfile, char *dir,
24799ebb4caSwyllys 	char *outfile)
2487711facfSdinak {
24999ebb4caSwyllys 	KMF_RETURN rv;
250*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
251*30a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
252*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
253*30a5e8faSwyllys 	int numattr = 0;
254*30a5e8faSwyllys 
255*30a5e8faSwyllys 	kstype = KMF_KEYSTORE_OPENSSL;
256*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
257*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
258*30a5e8faSwyllys 	numattr++;
259*30a5e8faSwyllys 
260*30a5e8faSwyllys 	if (dir != NULL) {
261*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
262*30a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dir, strlen(dir));
263*30a5e8faSwyllys 		numattr++;
264*30a5e8faSwyllys 	}
2657711facfSdinak 
266*30a5e8faSwyllys 	if (certfile != NULL) {
267*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
268*30a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
269*30a5e8faSwyllys 		numattr++;
270*30a5e8faSwyllys 	}
271*30a5e8faSwyllys 
272*30a5e8faSwyllys 	if (keyfile != NULL) {
273*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
274*30a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
275*30a5e8faSwyllys 		numattr++;
276*30a5e8faSwyllys 	}
2777711facfSdinak 
278*30a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
279*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
280*30a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
281*30a5e8faSwyllys 	numattr++;
2827711facfSdinak 
283*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
284*30a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
285*30a5e8faSwyllys 	numattr++;
2867711facfSdinak 
287*30a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
2887711facfSdinak 
289*30a5e8faSwyllys 	if (p12cred.cred)
290*30a5e8faSwyllys 		free(p12cred.cred);
2917711facfSdinak 
29299ebb4caSwyllys 	return (rv);
2937711facfSdinak }
2947711facfSdinak 
29599ebb4caSwyllys static KMF_RETURN
29699ebb4caSwyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
29799ebb4caSwyllys 	int oclass, char *certlabel, char *issuer, char *subject,
29899ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
29999ebb4caSwyllys 	char *prefix, char *filename)
3007711facfSdinak {
30199ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
30299ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
303*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
304*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
305*30a5e8faSwyllys 	int numattr = 0;
3067711facfSdinak 
30799ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
30899ebb4caSwyllys 	if (rv != KMF_OK)
3097711facfSdinak 		return (rv);
3107711facfSdinak 
31199ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
31299ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
313*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
314*30a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
315*30a5e8faSwyllys 		    sizeof (kstype));
316*30a5e8faSwyllys 		numattr++;
317*30a5e8faSwyllys 
318*30a5e8faSwyllys 		if (certlabel != NULL) {
319*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
320*30a5e8faSwyllys 			    KMF_CERT_LABEL_ATTR, certlabel,
321*30a5e8faSwyllys 			    strlen(certlabel));
322*30a5e8faSwyllys 			numattr++;
323*30a5e8faSwyllys 		}
32499ebb4caSwyllys 
325*30a5e8faSwyllys 		if (issuer != NULL) {
326*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
327*30a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
328*30a5e8faSwyllys 			    strlen(issuer));
329*30a5e8faSwyllys 			numattr++;
330*30a5e8faSwyllys 		}
33199ebb4caSwyllys 
332*30a5e8faSwyllys 		if (subject != NULL) {
333*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
334*30a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
335*30a5e8faSwyllys 			    strlen(subject));
336*30a5e8faSwyllys 			numattr++;
337*30a5e8faSwyllys 		}
338*30a5e8faSwyllys 
339*30a5e8faSwyllys 		if (serial != NULL) {
340*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
341*30a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
342*30a5e8faSwyllys 			    sizeof (KMF_BIGINT));
343*30a5e8faSwyllys 			numattr++;
344*30a5e8faSwyllys 		}
345*30a5e8faSwyllys 
346*30a5e8faSwyllys 		if (token_spec != NULL) {
347*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
348*30a5e8faSwyllys 			    KMF_TOKEN_LABEL_ATTR, token_spec,
349*30a5e8faSwyllys 			    strlen(token_spec));
350*30a5e8faSwyllys 			numattr++;
351*30a5e8faSwyllys 		}
352*30a5e8faSwyllys 
353*30a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
354*30a5e8faSwyllys 		    &kmfcert);
35599ebb4caSwyllys 		if (rv == KMF_OK) {
356*30a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
357*30a5e8faSwyllys 			numattr = 0;
358*30a5e8faSwyllys 
359*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
360*30a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
361*30a5e8faSwyllys 			numattr++;
36299ebb4caSwyllys 
363*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
364*30a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
365*30a5e8faSwyllys 			    sizeof (KMF_DATA));
366*30a5e8faSwyllys 			numattr++;
36799ebb4caSwyllys 
368*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
369*30a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
370*30a5e8faSwyllys 			    strlen(filename));
371*30a5e8faSwyllys 			numattr++;
372*30a5e8faSwyllys 
373*30a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
374*30a5e8faSwyllys 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
375*30a5e8faSwyllys 			numattr++;
376*30a5e8faSwyllys 
377*30a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
378*30a5e8faSwyllys 
379*30a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
3807711facfSdinak 		}
3817711facfSdinak 	}
38299ebb4caSwyllys 	return (rv);
38399ebb4caSwyllys }
3847711facfSdinak 
38599ebb4caSwyllys static KMF_RETURN
38699ebb4caSwyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
38799ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
38899ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
38999ebb4caSwyllys {
39099ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
391*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
392*30a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
393*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
394*30a5e8faSwyllys 	int numattr = 0;
3957711facfSdinak 
39699ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
39799ebb4caSwyllys 	if (rv != KMF_OK) {
39899ebb4caSwyllys 		return (rv);
3997711facfSdinak 	}
4007711facfSdinak 
401*30a5e8faSwyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
402*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
403*30a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
404*30a5e8faSwyllys 	numattr++;
405*30a5e8faSwyllys 
406*30a5e8faSwyllys 	if (certlabel != NULL) {
407*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
408*30a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
409*30a5e8faSwyllys 		numattr++;
410*30a5e8faSwyllys 	}
411*30a5e8faSwyllys 
412*30a5e8faSwyllys 	if (issuer != NULL) {
413*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
414*30a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
415*30a5e8faSwyllys 		numattr++;
416*30a5e8faSwyllys 	}
417*30a5e8faSwyllys 
418*30a5e8faSwyllys 	if (subject != NULL) {
419*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
420*30a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
421*30a5e8faSwyllys 		numattr++;
422*30a5e8faSwyllys 	}
423*30a5e8faSwyllys 
424*30a5e8faSwyllys 	if (serial != NULL) {
425*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
426*30a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
427*30a5e8faSwyllys 		numattr++;
428*30a5e8faSwyllys 	}
429*30a5e8faSwyllys 
430*30a5e8faSwyllys 	if (tokencred != NULL) {
431*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
432*30a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
433*30a5e8faSwyllys 		numattr++;
434*30a5e8faSwyllys 	}
435*30a5e8faSwyllys 
436*30a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
437*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
438*30a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
439*30a5e8faSwyllys 	numattr++;
440*30a5e8faSwyllys 
441*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
442*30a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
443*30a5e8faSwyllys 	numattr++;
444*30a5e8faSwyllys 
445*30a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
446*30a5e8faSwyllys 
447*30a5e8faSwyllys 	if (p12cred.cred)
448*30a5e8faSwyllys 		free(p12cred.cred);
449*30a5e8faSwyllys 
450*30a5e8faSwyllys 	return (rv);
451*30a5e8faSwyllys }
452*30a5e8faSwyllys 
453*30a5e8faSwyllys static KMF_RETURN
454*30a5e8faSwyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
455*30a5e8faSwyllys 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
456*30a5e8faSwyllys 	char *label, char *filename)
457*30a5e8faSwyllys {
458*30a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
459*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
460*30a5e8faSwyllys 	int numattr = 0;
461*30a5e8faSwyllys 	uint32_t numkeys = 1;
462*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
463*30a5e8faSwyllys 	KMF_KEY_HANDLE key;
464*30a5e8faSwyllys 	KMF_KEY_CLASS keyclass = KMF_SYMMETRIC;
465*30a5e8faSwyllys 	boolean_t is_token = B_TRUE;
466*30a5e8faSwyllys 
467*30a5e8faSwyllys 	if (EMPTYSTRING(label)) {
468*30a5e8faSwyllys 		cryptoerror(LOG_STDERR, gettext("A label "
469*30a5e8faSwyllys 		    "must be specified to export a key."));
470*30a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
471*30a5e8faSwyllys 	}
472*30a5e8faSwyllys 
473*30a5e8faSwyllys 	rv = select_token(kmfhandle, token, TRUE);
474*30a5e8faSwyllys 	if (rv != KMF_OK) {
475*30a5e8faSwyllys 		return (rv);
476*30a5e8faSwyllys 	}
477*30a5e8faSwyllys 
478*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
479*30a5e8faSwyllys 	    &kstype, sizeof (kstype));
480*30a5e8faSwyllys 	numattr++;
481*30a5e8faSwyllys 
482*30a5e8faSwyllys 	if (cred != NULL) {
483*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
484*30a5e8faSwyllys 		    cred, sizeof (KMF_CREDENTIAL));
485*30a5e8faSwyllys 		numattr++;
486*30a5e8faSwyllys 	}
487*30a5e8faSwyllys 
488*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
489*30a5e8faSwyllys 	    label, strlen(label));
490*30a5e8faSwyllys 	numattr++;
491*30a5e8faSwyllys 
492*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
493*30a5e8faSwyllys 	    &numkeys, sizeof (numkeys));
494*30a5e8faSwyllys 	numattr++;
4957711facfSdinak 
496*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
497*30a5e8faSwyllys 	    &key, sizeof (key));
498*30a5e8faSwyllys 	numattr++;
4997711facfSdinak 
500*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
501*30a5e8faSwyllys 	    &is_token, sizeof (is_token));
502*30a5e8faSwyllys 	numattr++;
5037711facfSdinak 
504*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
505*30a5e8faSwyllys 	    &format, sizeof (format));
506*30a5e8faSwyllys 	numattr++;
507*30a5e8faSwyllys 
508*30a5e8faSwyllys 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
509*30a5e8faSwyllys 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
510*30a5e8faSwyllys 		KMF_RAW_SYM_KEY rkey;
511*30a5e8faSwyllys 
512*30a5e8faSwyllys 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
513*30a5e8faSwyllys 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
514*30a5e8faSwyllys 		if (rv == KMF_OK) {
515*30a5e8faSwyllys 			int fd, n, total = 0;
516*30a5e8faSwyllys 
517*30a5e8faSwyllys 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
518*30a5e8faSwyllys 			if (fd == -1) {
519*30a5e8faSwyllys 				rv = KMF_ERR_OPEN_FILE;
520*30a5e8faSwyllys 				goto done;
521*30a5e8faSwyllys 			}
522*30a5e8faSwyllys 			do {
523*30a5e8faSwyllys 				n = write(fd, rkey.keydata.val + total,
524*30a5e8faSwyllys 				    rkey.keydata.len - total);
525*30a5e8faSwyllys 				if (n < 0) {
526*30a5e8faSwyllys 					if (errno == EINTR)
527*30a5e8faSwyllys 						continue;
528*30a5e8faSwyllys 					close(fd);
529*30a5e8faSwyllys 					rv = KMF_ERR_WRITE_FILE;
530*30a5e8faSwyllys 					goto done;
531*30a5e8faSwyllys 				}
532*30a5e8faSwyllys 				total += n;
533*30a5e8faSwyllys 
534*30a5e8faSwyllys 			} while (total < rkey.keydata.len);
535*30a5e8faSwyllys 			close(fd);
536*30a5e8faSwyllys 		}
537*30a5e8faSwyllys done:
538*30a5e8faSwyllys 		kmf_free_bigint(&rkey.keydata);
539*30a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
540*30a5e8faSwyllys 	} else if (rv == KMF_OK) {
541*30a5e8faSwyllys 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
542*30a5e8faSwyllys 		printf(gettext("Found %d asymmetric keys\n"), numkeys);
543*30a5e8faSwyllys 
544*30a5e8faSwyllys 		numattr = 0;
545*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
546*30a5e8faSwyllys 		    &sslks, sizeof (sslks));
547*30a5e8faSwyllys 		numattr++;
548*30a5e8faSwyllys 
549*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
550*30a5e8faSwyllys 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
551*30a5e8faSwyllys 		numattr++;
552*30a5e8faSwyllys 
553*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
554*30a5e8faSwyllys 		    &format, sizeof (format));
555*30a5e8faSwyllys 		numattr++;
556*30a5e8faSwyllys 
557*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
558*30a5e8faSwyllys 		    filename, strlen(filename));
559*30a5e8faSwyllys 		numattr++;
560*30a5e8faSwyllys 
561*30a5e8faSwyllys 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
562*30a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
563*30a5e8faSwyllys 	}
5647711facfSdinak 
56599ebb4caSwyllys 	return (rv);
5667711facfSdinak }
5677711facfSdinak 
56899ebb4caSwyllys static KMF_RETURN
56999ebb4caSwyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
57099ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
57199ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
57299ebb4caSwyllys 	char *filename)
5737711facfSdinak {
57499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
57599ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
576*30a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
577*30a5e8faSwyllys 	int numattr = 0;
578*30a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
5797711facfSdinak 
58099ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
5817711facfSdinak 
58299ebb4caSwyllys 	if (rv != KMF_OK) {
5837711facfSdinak 		return (rv);
5847711facfSdinak 	}
5857711facfSdinak 
586*30a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
587*30a5e8faSwyllys 	    &kstype, sizeof (kstype));
588*30a5e8faSwyllys 	numattr++;
5897711facfSdinak 
590*30a5e8faSwyllys 	if (certlabel != NULL) {
591*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
592*30a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel,
593*30a5e8faSwyllys 		    strlen(certlabel));
594*30a5e8faSwyllys 		numattr++;
595*30a5e8faSwyllys 	}
596*30a5e8faSwyllys 
597*30a5e8faSwyllys 	if (issuer != NULL) {
598*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
599*30a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer,
600*30a5e8faSwyllys 		    strlen(issuer));
601*30a5e8faSwyllys 		numattr++;
602*30a5e8faSwyllys 	}
603*30a5e8faSwyllys 
604*30a5e8faSwyllys 	if (subject != NULL) {
605*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
606*30a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject,
607*30a5e8faSwyllys 		    strlen(subject));
608*30a5e8faSwyllys 		numattr++;
609*30a5e8faSwyllys 	}
610*30a5e8faSwyllys 
611*30a5e8faSwyllys 	if (serial != NULL) {
612*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
613*30a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial,
614*30a5e8faSwyllys 		    sizeof (KMF_BIGINT));
615*30a5e8faSwyllys 		numattr++;
616*30a5e8faSwyllys 	}
617*30a5e8faSwyllys 
618*30a5e8faSwyllys 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
6197711facfSdinak 
62099ebb4caSwyllys 	if (rv == KMF_OK) {
621*30a5e8faSwyllys 		kstype = KMF_KEYSTORE_OPENSSL;
622*30a5e8faSwyllys 		numattr = 0;
623*30a5e8faSwyllys 
624*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
625*30a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
626*30a5e8faSwyllys 		numattr++;
627*30a5e8faSwyllys 
628*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
629*30a5e8faSwyllys 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
630*30a5e8faSwyllys 		    sizeof (KMF_DATA));
631*30a5e8faSwyllys 		numattr++;
632*30a5e8faSwyllys 
633*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
634*30a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
635*30a5e8faSwyllys 		numattr++;
636*30a5e8faSwyllys 
637*30a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
638*30a5e8faSwyllys 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
639*30a5e8faSwyllys 		numattr++;
6407711facfSdinak 
641*30a5e8faSwyllys 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
6427711facfSdinak 
643*30a5e8faSwyllys 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
6447711facfSdinak 	}
64599ebb4caSwyllys 	return (rv);
6467711facfSdinak }
6477711facfSdinak 
6487711facfSdinak /*
64999ebb4caSwyllys  * Export objects from one keystore to a file.
6507711facfSdinak  */
6517711facfSdinak int
6527711facfSdinak pk_export(int argc, char *argv[])
6537711facfSdinak {
65449e21299Sdinak 	int		opt;
65549e21299Sdinak 	extern int	optind_av;
65649e21299Sdinak 	extern char	*optarg_av;
65749e21299Sdinak 	char		*token_spec = NULL;
6587711facfSdinak 	char		*filename = NULL;
65999ebb4caSwyllys 	char		*dir = NULL;
66099ebb4caSwyllys 	char		*prefix = NULL;
66199ebb4caSwyllys 	char		*certlabel = NULL;
66299ebb4caSwyllys 	char		*subject = NULL;
66399ebb4caSwyllys 	char		*issuer = NULL;
66499ebb4caSwyllys 	char		*infile = NULL;
66599ebb4caSwyllys 	char		*keyfile = NULL;
66699ebb4caSwyllys 	char		*certfile = NULL;
66799ebb4caSwyllys 	char		*serstr = NULL;
66899ebb4caSwyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
66999ebb4caSwyllys 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
67099ebb4caSwyllys 	KMF_RETURN		rv = KMF_OK;
67199ebb4caSwyllys 	int		oclass = PK_CERT_OBJ;
67299ebb4caSwyllys 	KMF_BIGINT	serial = { NULL, 0 };
67399ebb4caSwyllys 	KMF_HANDLE_T	kmfhandle = NULL;
67499ebb4caSwyllys 	KMF_CREDENTIAL	tokencred = {NULL, 0};
6757711facfSdinak 
67649e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
67799ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
678*30a5e8faSwyllys 	    "k:(keystore)y:(objtype)T:(token)"
679*30a5e8faSwyllys 	    "d:(dir)p:(prefix)"
680*30a5e8faSwyllys 	    "l:(label)n:(nickname)s:(subject)"
681*30a5e8faSwyllys 	    "i:(issuer)S:(serial)"
682*30a5e8faSwyllys 	    "K:(keyfile)c:(certfile)"
683*30a5e8faSwyllys 	    "F:(outformat)"
684*30a5e8faSwyllys 	    "I:(infile)o:(outfile)")) != EOF) {
68599ebb4caSwyllys 		if (EMPTYSTRING(optarg_av))
68699ebb4caSwyllys 			return (PK_ERR_USAGE);
68749e21299Sdinak 		switch (opt) {
68899ebb4caSwyllys 		case 'k':
68999ebb4caSwyllys 			kstype = KS2Int(optarg_av);
69099ebb4caSwyllys 			if (kstype == 0)
69199ebb4caSwyllys 				return (PK_ERR_USAGE);
69299ebb4caSwyllys 			break;
69399ebb4caSwyllys 		case 'y':
69499ebb4caSwyllys 			oclass = OT2Int(optarg_av);
69599ebb4caSwyllys 			if (oclass == -1)
69699ebb4caSwyllys 				return (PK_ERR_USAGE);
69799ebb4caSwyllys 			break;
69849e21299Sdinak 		case 'T':	/* token specifier */
69949e21299Sdinak 			if (token_spec)
70049e21299Sdinak 				return (PK_ERR_USAGE);
70149e21299Sdinak 			token_spec = optarg_av;
70249e21299Sdinak 			break;
70399ebb4caSwyllys 		case 'd':
70499ebb4caSwyllys 			if (dir)
70599ebb4caSwyllys 				return (PK_ERR_USAGE);
70699ebb4caSwyllys 			dir = optarg_av;
70799ebb4caSwyllys 			break;
70899ebb4caSwyllys 		case 'p':
70999ebb4caSwyllys 			if (prefix)
71099ebb4caSwyllys 				return (PK_ERR_USAGE);
71199ebb4caSwyllys 			prefix = optarg_av;
71299ebb4caSwyllys 			break;
71399ebb4caSwyllys 		case 'n':
71499ebb4caSwyllys 		case 'l':
71599ebb4caSwyllys 			if (certlabel)
71699ebb4caSwyllys 				return (PK_ERR_USAGE);
71799ebb4caSwyllys 			certlabel = optarg_av;
71899ebb4caSwyllys 			break;
71999ebb4caSwyllys 		case 's':
72099ebb4caSwyllys 			if (subject)
72199ebb4caSwyllys 				return (PK_ERR_USAGE);
72299ebb4caSwyllys 			subject = optarg_av;
72399ebb4caSwyllys 			break;
72499ebb4caSwyllys 		case 'i':
72599ebb4caSwyllys 			if (issuer)
72699ebb4caSwyllys 				return (PK_ERR_USAGE);
72799ebb4caSwyllys 			issuer = optarg_av;
72899ebb4caSwyllys 			break;
72999ebb4caSwyllys 		case 'S':
73099ebb4caSwyllys 			serstr = optarg_av;
73199ebb4caSwyllys 			break;
73299ebb4caSwyllys 		case 'F':
73399ebb4caSwyllys 			kfmt = Str2Format(optarg_av);
73499ebb4caSwyllys 			if (kfmt == KMF_FORMAT_UNDEF)
73599ebb4caSwyllys 				return (PK_ERR_USAGE);
73699ebb4caSwyllys 			break;
73799ebb4caSwyllys 		case 'I':	/* output file name */
73899ebb4caSwyllys 			if (infile)
73999ebb4caSwyllys 				return (PK_ERR_USAGE);
74099ebb4caSwyllys 			infile = optarg_av;
74199ebb4caSwyllys 			break;
74249e21299Sdinak 		case 'o':	/* output file name */
74349e21299Sdinak 			if (filename)
74449e21299Sdinak 				return (PK_ERR_USAGE);
74549e21299Sdinak 			filename = optarg_av;
74649e21299Sdinak 			break;
74799ebb4caSwyllys 		case 'c':	/* input cert file name */
74899ebb4caSwyllys 			if (certfile)
74999ebb4caSwyllys 				return (PK_ERR_USAGE);
75099ebb4caSwyllys 			certfile = optarg_av;
75199ebb4caSwyllys 			break;
75299ebb4caSwyllys 		case 'K':	/* input key file name */
75399ebb4caSwyllys 			if (keyfile)
75499ebb4caSwyllys 				return (PK_ERR_USAGE);
75599ebb4caSwyllys 			keyfile = optarg_av;
75699ebb4caSwyllys 			break;
75749e21299Sdinak 		default:
75849e21299Sdinak 			return (PK_ERR_USAGE);
75949e21299Sdinak 			break;
76049e21299Sdinak 		}
76149e21299Sdinak 	}
7627711facfSdinak 
76399ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified */
76499ebb4caSwyllys 	if (kstype == 0)
76599ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
76649e21299Sdinak 
76749e21299Sdinak 	/* Filename arg is required. */
76899ebb4caSwyllys 	if (EMPTYSTRING(filename)) {
76999ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("You must specify "
770*30a5e8faSwyllys 		    "an 'outfile' parameter when exporting.\n"));
7717711facfSdinak 		return (PK_ERR_USAGE);
77299ebb4caSwyllys 	}
7737711facfSdinak 
77449e21299Sdinak 	/* No additional args allowed. */
77549e21299Sdinak 	argc -= optind_av;
77649e21299Sdinak 	argv += optind_av;
77749e21299Sdinak 	if (argc)
77849e21299Sdinak 		return (PK_ERR_USAGE);
77999ebb4caSwyllys 
78099ebb4caSwyllys 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
78199ebb4caSwyllys 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
782*30a5e8faSwyllys 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
78399ebb4caSwyllys 
78499ebb4caSwyllys 		(void) fprintf(stderr, gettext("The objtype parameter "
785*30a5e8faSwyllys 		    "is only relevant if keystore=pkcs11\n"));
78699ebb4caSwyllys 		return (PK_ERR_USAGE);
78799ebb4caSwyllys 	}
78899ebb4caSwyllys 
78999ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
79099ebb4caSwyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
79199ebb4caSwyllys 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
79299ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
79399ebb4caSwyllys 
79499ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_OPENSSL) {
79599ebb4caSwyllys 		if (kfmt != KMF_FORMAT_PKCS12) {
79699ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
797*30a5e8faSwyllys 			    "is the only export format "
798*30a5e8faSwyllys 			    "supported for the 'file' "
799*30a5e8faSwyllys 			    "keystore.\n"));
80099ebb4caSwyllys 			return (PK_ERR_USAGE);
80199ebb4caSwyllys 		}
80299ebb4caSwyllys 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
80399ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A cert file"
804*30a5e8faSwyllys 			    "and a key file must be specified "
805*30a5e8faSwyllys 			    "when exporting to PKCS12 from the "
806*30a5e8faSwyllys 			    "'file' keystore.\n"));
80799ebb4caSwyllys 			return (PK_ERR_USAGE);
80899ebb4caSwyllys 		}
80999ebb4caSwyllys 	}
8107711facfSdinak 
8117711facfSdinak 	/* Check if the file exists and might be overwritten. */
8127711facfSdinak 	if (access(filename, F_OK) == 0) {
81399ebb4caSwyllys 		cryptoerror(LOG_STDERR,
814*30a5e8faSwyllys 		    gettext("Warning: file \"%s\" exists, "
815*30a5e8faSwyllys 		    "will be overwritten."), filename);
8167711facfSdinak 		if (yesno(gettext("Continue with export? "),
8177711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
8187711facfSdinak 			return (0);
8197711facfSdinak 		}
82099ebb4caSwyllys 	} else {
82199ebb4caSwyllys 		rv = verify_file(filename);
82299ebb4caSwyllys 		if (rv != KMF_OK) {
82399ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("The file (%s) "
824*30a5e8faSwyllys 			    "cannot be created.\n"), filename);
82599ebb4caSwyllys 			return (PK_ERR_USAGE);
82699ebb4caSwyllys 		}
8277711facfSdinak 	}
8287711facfSdinak 
82999ebb4caSwyllys 	if (serstr != NULL) {
83099ebb4caSwyllys 		uchar_t *bytes = NULL;
83199ebb4caSwyllys 		size_t bytelen;
8327711facfSdinak 
833*30a5e8faSwyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
83499ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
83599ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
836*30a5e8faSwyllys 			    "must be specified as a hex number "
837*30a5e8faSwyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
83899ebb4caSwyllys 			return (PK_ERR_USAGE);
83999ebb4caSwyllys 		}
84099ebb4caSwyllys 		serial.val = bytes;
84199ebb4caSwyllys 		serial.len = bytelen;
8427711facfSdinak 	}
8437711facfSdinak 
84499ebb4caSwyllys 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
845*30a5e8faSwyllys 	    kstype == KMF_KEYSTORE_NSS) &&
846*30a5e8faSwyllys 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) ||
847*30a5e8faSwyllys 	    kfmt == KMF_FORMAT_PKCS12)) {
84899ebb4caSwyllys 			(void) get_token_password(kstype, token_spec,
849*30a5e8faSwyllys 			    &tokencred);
8507711facfSdinak 	}
8517711facfSdinak 
852*30a5e8faSwyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
85399ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing "
854*30a5e8faSwyllys 		    "KMF: 0x%02x\n"), rv);
85599ebb4caSwyllys 		return (rv);
8567711facfSdinak 	}
8577711facfSdinak 
85899ebb4caSwyllys 	switch (kstype) {
85999ebb4caSwyllys 		case KMF_KEYSTORE_PK11TOKEN:
86099ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
861*30a5e8faSwyllys 				rv = pk_export_pk12_pk11(kmfhandle,
862*30a5e8faSwyllys 				    token_spec, certlabel,
863*30a5e8faSwyllys 				    issuer, subject,
864*30a5e8faSwyllys 				    &serial, &tokencred,
865*30a5e8faSwyllys 				    filename);
866*30a5e8faSwyllys 			else if ((oclass & PK_KEY_OBJ) ||
867*30a5e8faSwyllys 			    kfmt == KMF_FORMAT_RAWKEY)
868*30a5e8faSwyllys 				rv = pk_export_pk11_keys(kmfhandle,
869*30a5e8faSwyllys 				    token_spec, &tokencred, kfmt,
870*30a5e8faSwyllys 				    certlabel, filename);
87199ebb4caSwyllys 			else
87299ebb4caSwyllys 				rv = pk_export_pk11_objects(kmfhandle,
873*30a5e8faSwyllys 				    token_spec, certlabel,
874*30a5e8faSwyllys 				    issuer, subject, &serial, kfmt,
875*30a5e8faSwyllys 				    filename);
87699ebb4caSwyllys 			break;
87799ebb4caSwyllys 		case KMF_KEYSTORE_NSS:
87899ebb4caSwyllys 			if (dir == NULL)
87999ebb4caSwyllys 				dir = PK_DEFAULT_DIRECTORY;
88099ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
88199ebb4caSwyllys 				rv = pk_export_pk12_nss(kmfhandle,
882*30a5e8faSwyllys 				    token_spec, dir, prefix,
883*30a5e8faSwyllys 				    certlabel, issuer,
884*30a5e8faSwyllys 				    subject, &serial,
885*30a5e8faSwyllys 				    &tokencred, filename);
88699ebb4caSwyllys 			else
88799ebb4caSwyllys 				rv = pk_export_nss_objects(kmfhandle,
888*30a5e8faSwyllys 				    token_spec,
889*30a5e8faSwyllys 				    oclass, certlabel, issuer, subject,
890*30a5e8faSwyllys 				    &serial, kfmt, dir, prefix, filename);
89199ebb4caSwyllys 			break;
89299ebb4caSwyllys 		case KMF_KEYSTORE_OPENSSL:
89399ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
89499ebb4caSwyllys 				rv = pk_export_pk12_files(kmfhandle,
895*30a5e8faSwyllys 				    certfile, keyfile, dir,
896*30a5e8faSwyllys 				    filename);
89799ebb4caSwyllys 			else
89899ebb4caSwyllys 				rv = pk_export_file_objects(kmfhandle, oclass,
899*30a5e8faSwyllys 				    issuer, subject, &serial,
900*30a5e8faSwyllys 				    dir, infile, filename);
90199ebb4caSwyllys 			break;
90299ebb4caSwyllys 		default:
90399ebb4caSwyllys 			rv = PK_ERR_USAGE;
90499ebb4caSwyllys 			break;
9057711facfSdinak 	}
9067711facfSdinak 
90799ebb4caSwyllys 	if (rv != KMF_OK) {
90899ebb4caSwyllys 		display_error(kmfhandle, rv,
909*30a5e8faSwyllys 		    gettext("Error exporting objects"));
9107711facfSdinak 	}
9117711facfSdinak 
91299ebb4caSwyllys 	if (serial.val != NULL)
91399ebb4caSwyllys 		free(serial.val);
9147711facfSdinak 
915*30a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
9167711facfSdinak 
91799ebb4caSwyllys 	return (rv);
9187711facfSdinak }
919