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  *
2230a5e8faSwyllys  * 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
4730a5e8faSwyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist,
4830a5e8faSwyllys 	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));
5530a5e8faSwyllys 
5630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
5730a5e8faSwyllys 	    &numcerts, sizeof (uint32_t));
5830a5e8faSwyllys 	numattr++;
5930a5e8faSwyllys 
6030a5e8faSwyllys 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
6199ebb4caSwyllys 	if (rv != KMF_OK) {
627711facfSdinak 		return (rv);
637711facfSdinak 	}
6499ebb4caSwyllys 	if (numcerts == 0) {
6599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
6630a5e8faSwyllys 		    gettext("No matching certificates found."));
6799ebb4caSwyllys 		return (KMF_ERR_CERT_NOT_FOUND);
687711facfSdinak 
6999ebb4caSwyllys 	} else if (numcerts == 1) {
7030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
7130a5e8faSwyllys 		    KMF_X509_DER_CERT_ATTR, cert,
7230a5e8faSwyllys 		    sizeof (KMF_X509_DER_CERT));
7330a5e8faSwyllys 		numattr++;
7430a5e8faSwyllys 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
757711facfSdinak 
7699ebb4caSwyllys 	} else if (numcerts > 1) {
7799ebb4caSwyllys 		cryptoerror(LOG_STDERR,
7830a5e8faSwyllys 		    gettext("%d certificates found, refine the "
7930a5e8faSwyllys 		    "search parameters to eliminate ambiguity\n"),
8030a5e8faSwyllys 		    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;
9330a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
9430a5e8faSwyllys 	int numattr = 0;
9530a5e8faSwyllys 	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)) {
9930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
10030a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
10130a5e8faSwyllys 		    sizeof (kstype));
10230a5e8faSwyllys 		numattr++;
10330a5e8faSwyllys 
10430a5e8faSwyllys 		if (issuer != NULL) {
10530a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
10630a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
10730a5e8faSwyllys 			    strlen(issuer));
10830a5e8faSwyllys 			numattr++;
10930a5e8faSwyllys 		}
11030a5e8faSwyllys 
11130a5e8faSwyllys 		if (subject != NULL) {
11230a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
11330a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
11430a5e8faSwyllys 			    strlen(subject));
11530a5e8faSwyllys 			numattr++;
11630a5e8faSwyllys 		}
11730a5e8faSwyllys 
11830a5e8faSwyllys 		if (serial != NULL) {
11930a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
12030a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
12130a5e8faSwyllys 			    sizeof (KMF_BIGINT));
12230a5e8faSwyllys 			numattr++;
12330a5e8faSwyllys 		}
12430a5e8faSwyllys 
12530a5e8faSwyllys 		if (dir != NULL) {
12630a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
12730a5e8faSwyllys 			    KMF_DIRPATH_ATTR, dir,
12830a5e8faSwyllys 			    strlen(dir));
12930a5e8faSwyllys 			numattr++;
13030a5e8faSwyllys 		}
13130a5e8faSwyllys 
13230a5e8faSwyllys 		if (infile != NULL) {
13330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
13430a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, infile,
13530a5e8faSwyllys 			    strlen(infile));
13630a5e8faSwyllys 			numattr++;
13730a5e8faSwyllys 		}
13830a5e8faSwyllys 
13930a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
14030a5e8faSwyllys 		    &kmfcert);
14199ebb4caSwyllys 		if (rv == KMF_OK) {
14230a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
14330a5e8faSwyllys 			numattr = 0;
14499ebb4caSwyllys 
14530a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
14630a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
14730a5e8faSwyllys 			numattr++;
14830a5e8faSwyllys 
14930a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
15030a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
15130a5e8faSwyllys 			    sizeof (KMF_DATA));
15230a5e8faSwyllys 			numattr++;
15330a5e8faSwyllys 
15430a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
15530a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
15630a5e8faSwyllys 			    strlen(filename));
15730a5e8faSwyllys 			numattr++;
15830a5e8faSwyllys 
15930a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr,
16030a5e8faSwyllys 			    attrlist);
16130a5e8faSwyllys 
16230a5e8faSwyllys 			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;
17630a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
17730a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
17830a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
17930a5e8faSwyllys 	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 
18830a5e8faSwyllys 	kstype = KMF_KEYSTORE_NSS;
18930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
19030a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
19130a5e8faSwyllys 	numattr++;
19230a5e8faSwyllys 
19330a5e8faSwyllys 	if (certlabel != NULL) {
19430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
19530a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
19630a5e8faSwyllys 		numattr++;
19730a5e8faSwyllys 	}
19830a5e8faSwyllys 
19930a5e8faSwyllys 	if (issuer != NULL) {
20030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
20130a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
20230a5e8faSwyllys 		numattr++;
20330a5e8faSwyllys 	}
20430a5e8faSwyllys 
20530a5e8faSwyllys 	if (subject != NULL) {
20630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
20730a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
20830a5e8faSwyllys 		numattr++;
20930a5e8faSwyllys 	}
2107711facfSdinak 
21130a5e8faSwyllys 	if (serial != NULL) {
21230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
21330a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
21430a5e8faSwyllys 		numattr++;
21530a5e8faSwyllys 	}
2167711facfSdinak 
21730a5e8faSwyllys 	if (tokencred != NULL) {
21830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
21930a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
22030a5e8faSwyllys 		numattr++;
22130a5e8faSwyllys 	}
22230a5e8faSwyllys 
22330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
22430a5e8faSwyllys 	    token_spec, strlen(token_spec));
22530a5e8faSwyllys 	numattr++;
22630a5e8faSwyllys 
22730a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
22830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
22930a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
23030a5e8faSwyllys 	numattr++;
23130a5e8faSwyllys 
23230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
23330a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
23430a5e8faSwyllys 	numattr++;
23530a5e8faSwyllys 
23630a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
23730a5e8faSwyllys 
23830a5e8faSwyllys 	if (p12cred.cred)
23930a5e8faSwyllys 		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;
25030a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
25130a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
25230a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
25330a5e8faSwyllys 	int numattr = 0;
25430a5e8faSwyllys 
25530a5e8faSwyllys 	kstype = KMF_KEYSTORE_OPENSSL;
25630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
25730a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
25830a5e8faSwyllys 	numattr++;
25930a5e8faSwyllys 
26030a5e8faSwyllys 	if (dir != NULL) {
26130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
26230a5e8faSwyllys 		    KMF_DIRPATH_ATTR, dir, strlen(dir));
26330a5e8faSwyllys 		numattr++;
26430a5e8faSwyllys 	}
2657711facfSdinak 
26630a5e8faSwyllys 	if (certfile != NULL) {
26730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
26830a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
26930a5e8faSwyllys 		numattr++;
27030a5e8faSwyllys 	}
27130a5e8faSwyllys 
27230a5e8faSwyllys 	if (keyfile != NULL) {
27330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
27430a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
27530a5e8faSwyllys 		numattr++;
27630a5e8faSwyllys 	}
2777711facfSdinak 
27830a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
27930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
28030a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
28130a5e8faSwyllys 	numattr++;
2827711facfSdinak 
28330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
28430a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
28530a5e8faSwyllys 	numattr++;
2867711facfSdinak 
28730a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
2887711facfSdinak 
28930a5e8faSwyllys 	if (p12cred.cred)
29030a5e8faSwyllys 		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;
30330a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
30430a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
30530a5e8faSwyllys 	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)) {
31330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
31430a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
31530a5e8faSwyllys 		    sizeof (kstype));
31630a5e8faSwyllys 		numattr++;
31730a5e8faSwyllys 
31830a5e8faSwyllys 		if (certlabel != NULL) {
31930a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
32030a5e8faSwyllys 			    KMF_CERT_LABEL_ATTR, certlabel,
32130a5e8faSwyllys 			    strlen(certlabel));
32230a5e8faSwyllys 			numattr++;
32330a5e8faSwyllys 		}
32499ebb4caSwyllys 
32530a5e8faSwyllys 		if (issuer != NULL) {
32630a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
32730a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
32830a5e8faSwyllys 			    strlen(issuer));
32930a5e8faSwyllys 			numattr++;
33030a5e8faSwyllys 		}
33199ebb4caSwyllys 
33230a5e8faSwyllys 		if (subject != NULL) {
33330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
33430a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
33530a5e8faSwyllys 			    strlen(subject));
33630a5e8faSwyllys 			numattr++;
33730a5e8faSwyllys 		}
33830a5e8faSwyllys 
33930a5e8faSwyllys 		if (serial != NULL) {
34030a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
34130a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
34230a5e8faSwyllys 			    sizeof (KMF_BIGINT));
34330a5e8faSwyllys 			numattr++;
34430a5e8faSwyllys 		}
34530a5e8faSwyllys 
34630a5e8faSwyllys 		if (token_spec != NULL) {
34730a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
34830a5e8faSwyllys 			    KMF_TOKEN_LABEL_ATTR, token_spec,
34930a5e8faSwyllys 			    strlen(token_spec));
35030a5e8faSwyllys 			numattr++;
35130a5e8faSwyllys 		}
35230a5e8faSwyllys 
35330a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
35430a5e8faSwyllys 		    &kmfcert);
35599ebb4caSwyllys 		if (rv == KMF_OK) {
35630a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
35730a5e8faSwyllys 			numattr = 0;
35830a5e8faSwyllys 
35930a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
36030a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
36130a5e8faSwyllys 			numattr++;
36299ebb4caSwyllys 
36330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
36430a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
36530a5e8faSwyllys 			    sizeof (KMF_DATA));
36630a5e8faSwyllys 			numattr++;
36799ebb4caSwyllys 
36830a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
36930a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
37030a5e8faSwyllys 			    strlen(filename));
37130a5e8faSwyllys 			numattr++;
37230a5e8faSwyllys 
37330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
37430a5e8faSwyllys 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
37530a5e8faSwyllys 			numattr++;
37630a5e8faSwyllys 
37730a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
37830a5e8faSwyllys 
37930a5e8faSwyllys 			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;
39130a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
39230a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
39330a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
39430a5e8faSwyllys 	int numattr = 0;
3957711facfSdinak 
39699ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
39799ebb4caSwyllys 	if (rv != KMF_OK) {
39899ebb4caSwyllys 		return (rv);
3997711facfSdinak 	}
4007711facfSdinak 
40130a5e8faSwyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
40230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
40330a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
40430a5e8faSwyllys 	numattr++;
40530a5e8faSwyllys 
40630a5e8faSwyllys 	if (certlabel != NULL) {
40730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
40830a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
40930a5e8faSwyllys 		numattr++;
41030a5e8faSwyllys 	}
41130a5e8faSwyllys 
41230a5e8faSwyllys 	if (issuer != NULL) {
41330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
41430a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
41530a5e8faSwyllys 		numattr++;
41630a5e8faSwyllys 	}
41730a5e8faSwyllys 
41830a5e8faSwyllys 	if (subject != NULL) {
41930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
42030a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
42130a5e8faSwyllys 		numattr++;
42230a5e8faSwyllys 	}
42330a5e8faSwyllys 
42430a5e8faSwyllys 	if (serial != NULL) {
42530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
42630a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
42730a5e8faSwyllys 		numattr++;
42830a5e8faSwyllys 	}
42930a5e8faSwyllys 
43030a5e8faSwyllys 	if (tokencred != NULL) {
43130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
43230a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
43330a5e8faSwyllys 		numattr++;
43430a5e8faSwyllys 	}
43530a5e8faSwyllys 
43630a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
43730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
43830a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
43930a5e8faSwyllys 	numattr++;
44030a5e8faSwyllys 
44130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
44230a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
44330a5e8faSwyllys 	numattr++;
44430a5e8faSwyllys 
44530a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
44630a5e8faSwyllys 
44730a5e8faSwyllys 	if (p12cred.cred)
44830a5e8faSwyllys 		free(p12cred.cred);
44930a5e8faSwyllys 
45030a5e8faSwyllys 	return (rv);
45130a5e8faSwyllys }
45230a5e8faSwyllys 
45330a5e8faSwyllys static KMF_RETURN
45430a5e8faSwyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
45530a5e8faSwyllys 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
45673cc0e02Swyllys 	char *label, char *filename, int oclass)
45730a5e8faSwyllys {
45830a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
45930a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
46073cc0e02Swyllys 	KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE;
46130a5e8faSwyllys 	int numattr = 0;
46230a5e8faSwyllys 	uint32_t numkeys = 1;
46330a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
46430a5e8faSwyllys 	KMF_KEY_HANDLE key;
46530a5e8faSwyllys 	boolean_t is_token = B_TRUE;
46630a5e8faSwyllys 
46730a5e8faSwyllys 	if (EMPTYSTRING(label)) {
46830a5e8faSwyllys 		cryptoerror(LOG_STDERR, gettext("A label "
46930a5e8faSwyllys 		    "must be specified to export a key."));
47030a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
47130a5e8faSwyllys 	}
47230a5e8faSwyllys 
47330a5e8faSwyllys 	rv = select_token(kmfhandle, token, TRUE);
47430a5e8faSwyllys 	if (rv != KMF_OK) {
47530a5e8faSwyllys 		return (rv);
47630a5e8faSwyllys 	}
47730a5e8faSwyllys 
47830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
47930a5e8faSwyllys 	    &kstype, sizeof (kstype));
48030a5e8faSwyllys 	numattr++;
48130a5e8faSwyllys 
48230a5e8faSwyllys 	if (cred != NULL) {
48330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
48430a5e8faSwyllys 		    cred, sizeof (KMF_CREDENTIAL));
48530a5e8faSwyllys 		numattr++;
48630a5e8faSwyllys 	}
48730a5e8faSwyllys 
48830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
48930a5e8faSwyllys 	    label, strlen(label));
49030a5e8faSwyllys 	numattr++;
49130a5e8faSwyllys 
49230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
49330a5e8faSwyllys 	    &numkeys, sizeof (numkeys));
49430a5e8faSwyllys 	numattr++;
4957711facfSdinak 
49630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
49730a5e8faSwyllys 	    &key, sizeof (key));
49830a5e8faSwyllys 	numattr++;
4997711facfSdinak 
50030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
50130a5e8faSwyllys 	    &is_token, sizeof (is_token));
50230a5e8faSwyllys 	numattr++;
5037711facfSdinak 
50430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
50530a5e8faSwyllys 	    &format, sizeof (format));
50630a5e8faSwyllys 	numattr++;
50730a5e8faSwyllys 
50873cc0e02Swyllys 	/* Check to see if we are exporting private or public only */
50973cc0e02Swyllys 	if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ)
51073cc0e02Swyllys 		kclass = KMF_ASYM_PRI;
51173cc0e02Swyllys 	else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ)
51273cc0e02Swyllys 		kclass = KMF_ASYM_PUB;
51373cc0e02Swyllys 	else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ)
51473cc0e02Swyllys 		kclass = KMF_SYMMETRIC;
51573cc0e02Swyllys 	else /* only 1 key at a time can be exported here, so default to pri */
51673cc0e02Swyllys 		kclass = KMF_ASYM_PRI;
51773cc0e02Swyllys 
51873cc0e02Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
51973cc0e02Swyllys 	    &kclass, sizeof (kclass));
52073cc0e02Swyllys 	numattr++;
52173cc0e02Swyllys 
52230a5e8faSwyllys 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
523*71a79fe7Swyllys 	/*
524*71a79fe7Swyllys 	 * If nothing found but caller wanted ALL keys, try symmetric
525*71a79fe7Swyllys 	 * this time.
526*71a79fe7Swyllys 	 */
527*71a79fe7Swyllys 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
528*71a79fe7Swyllys 		kclass = KMF_SYMMETRIC;
529*71a79fe7Swyllys 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
530*71a79fe7Swyllys 	}
531*71a79fe7Swyllys 	/*
532*71a79fe7Swyllys 	 * If nothing found but caller wanted ALL keys, try asymmetric
533*71a79fe7Swyllys 	 * public this time.
534*71a79fe7Swyllys 	 */
535*71a79fe7Swyllys 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
536*71a79fe7Swyllys 		kclass = KMF_ASYM_PUB;
537*71a79fe7Swyllys 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
538*71a79fe7Swyllys 	}
53930a5e8faSwyllys 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
54030a5e8faSwyllys 		KMF_RAW_SYM_KEY rkey;
54130a5e8faSwyllys 
54230a5e8faSwyllys 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
54330a5e8faSwyllys 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
54430a5e8faSwyllys 		if (rv == KMF_OK) {
54530a5e8faSwyllys 			int fd, n, total = 0;
54630a5e8faSwyllys 
54730a5e8faSwyllys 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
54830a5e8faSwyllys 			if (fd == -1) {
54930a5e8faSwyllys 				rv = KMF_ERR_OPEN_FILE;
55030a5e8faSwyllys 				goto done;
55130a5e8faSwyllys 			}
55230a5e8faSwyllys 			do {
55330a5e8faSwyllys 				n = write(fd, rkey.keydata.val + total,
55430a5e8faSwyllys 				    rkey.keydata.len - total);
55530a5e8faSwyllys 				if (n < 0) {
55630a5e8faSwyllys 					if (errno == EINTR)
55730a5e8faSwyllys 						continue;
55846d33f7eSwyllys 					(void) close(fd);
55930a5e8faSwyllys 					rv = KMF_ERR_WRITE_FILE;
56030a5e8faSwyllys 					goto done;
56130a5e8faSwyllys 				}
56230a5e8faSwyllys 				total += n;
56330a5e8faSwyllys 
56430a5e8faSwyllys 			} while (total < rkey.keydata.len);
56546d33f7eSwyllys 			(void) close(fd);
56630a5e8faSwyllys 		}
56730a5e8faSwyllys done:
56830a5e8faSwyllys 		kmf_free_bigint(&rkey.keydata);
56930a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
57030a5e8faSwyllys 	} else if (rv == KMF_OK) {
57130a5e8faSwyllys 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
57246d33f7eSwyllys 		(void) printf(gettext("Found %d asymmetric keys\n"), numkeys);
57330a5e8faSwyllys 
57430a5e8faSwyllys 		numattr = 0;
57530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
57630a5e8faSwyllys 		    &sslks, sizeof (sslks));
57730a5e8faSwyllys 		numattr++;
57830a5e8faSwyllys 
57930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
58030a5e8faSwyllys 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
58130a5e8faSwyllys 		numattr++;
58230a5e8faSwyllys 
58330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
58430a5e8faSwyllys 		    &format, sizeof (format));
58530a5e8faSwyllys 		numattr++;
58630a5e8faSwyllys 
58730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
58830a5e8faSwyllys 		    filename, strlen(filename));
58930a5e8faSwyllys 		numattr++;
59030a5e8faSwyllys 
59173cc0e02Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
59273cc0e02Swyllys 		    &key.keyclass, sizeof (KMF_KEY_CLASS));
59373cc0e02Swyllys 		numattr++;
59473cc0e02Swyllys 
59530a5e8faSwyllys 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
59630a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
59730a5e8faSwyllys 	}
5987711facfSdinak 
59999ebb4caSwyllys 	return (rv);
6007711facfSdinak }
6017711facfSdinak 
60299ebb4caSwyllys static KMF_RETURN
60399ebb4caSwyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
60499ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
60599ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
60699ebb4caSwyllys 	char *filename)
6077711facfSdinak {
60899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
60999ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
61030a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
61130a5e8faSwyllys 	int numattr = 0;
61230a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
6137711facfSdinak 
61499ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
6157711facfSdinak 
61699ebb4caSwyllys 	if (rv != KMF_OK) {
6177711facfSdinak 		return (rv);
6187711facfSdinak 	}
6197711facfSdinak 
62030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
62130a5e8faSwyllys 	    &kstype, sizeof (kstype));
62230a5e8faSwyllys 	numattr++;
6237711facfSdinak 
62430a5e8faSwyllys 	if (certlabel != NULL) {
62530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
62630a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel,
62730a5e8faSwyllys 		    strlen(certlabel));
62830a5e8faSwyllys 		numattr++;
62930a5e8faSwyllys 	}
63030a5e8faSwyllys 
63130a5e8faSwyllys 	if (issuer != NULL) {
63230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
63330a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer,
63430a5e8faSwyllys 		    strlen(issuer));
63530a5e8faSwyllys 		numattr++;
63630a5e8faSwyllys 	}
63730a5e8faSwyllys 
63830a5e8faSwyllys 	if (subject != NULL) {
63930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
64030a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject,
64130a5e8faSwyllys 		    strlen(subject));
64230a5e8faSwyllys 		numattr++;
64330a5e8faSwyllys 	}
64430a5e8faSwyllys 
64530a5e8faSwyllys 	if (serial != NULL) {
64630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
64730a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial,
64830a5e8faSwyllys 		    sizeof (KMF_BIGINT));
64930a5e8faSwyllys 		numattr++;
65030a5e8faSwyllys 	}
65130a5e8faSwyllys 
65230a5e8faSwyllys 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
6537711facfSdinak 
65499ebb4caSwyllys 	if (rv == KMF_OK) {
65530a5e8faSwyllys 		kstype = KMF_KEYSTORE_OPENSSL;
65630a5e8faSwyllys 		numattr = 0;
65730a5e8faSwyllys 
65830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
65930a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
66030a5e8faSwyllys 		numattr++;
66130a5e8faSwyllys 
66230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
66330a5e8faSwyllys 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
66430a5e8faSwyllys 		    sizeof (KMF_DATA));
66530a5e8faSwyllys 		numattr++;
66630a5e8faSwyllys 
66730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
66830a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
66930a5e8faSwyllys 		numattr++;
67030a5e8faSwyllys 
67130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
67230a5e8faSwyllys 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
67330a5e8faSwyllys 		numattr++;
6747711facfSdinak 
67530a5e8faSwyllys 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
6767711facfSdinak 
67730a5e8faSwyllys 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
6787711facfSdinak 	}
67999ebb4caSwyllys 	return (rv);
6807711facfSdinak }
6817711facfSdinak 
6827711facfSdinak /*
68399ebb4caSwyllys  * Export objects from one keystore to a file.
6847711facfSdinak  */
6857711facfSdinak int
6867711facfSdinak pk_export(int argc, char *argv[])
6877711facfSdinak {
68849e21299Sdinak 	int		opt;
68949e21299Sdinak 	extern int	optind_av;
69049e21299Sdinak 	extern char	*optarg_av;
69149e21299Sdinak 	char		*token_spec = NULL;
6927711facfSdinak 	char		*filename = NULL;
69399ebb4caSwyllys 	char		*dir = NULL;
69499ebb4caSwyllys 	char		*prefix = NULL;
69599ebb4caSwyllys 	char		*certlabel = NULL;
69699ebb4caSwyllys 	char		*subject = NULL;
69799ebb4caSwyllys 	char		*issuer = NULL;
69899ebb4caSwyllys 	char		*infile = NULL;
69999ebb4caSwyllys 	char		*keyfile = NULL;
70099ebb4caSwyllys 	char		*certfile = NULL;
70199ebb4caSwyllys 	char		*serstr = NULL;
70299ebb4caSwyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
70399ebb4caSwyllys 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
70499ebb4caSwyllys 	KMF_RETURN		rv = KMF_OK;
70599ebb4caSwyllys 	int		oclass = PK_CERT_OBJ;
70699ebb4caSwyllys 	KMF_BIGINT	serial = { NULL, 0 };
70799ebb4caSwyllys 	KMF_HANDLE_T	kmfhandle = NULL;
70899ebb4caSwyllys 	KMF_CREDENTIAL	tokencred = {NULL, 0};
7097711facfSdinak 
71049e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
71199ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
71230a5e8faSwyllys 	    "k:(keystore)y:(objtype)T:(token)"
71330a5e8faSwyllys 	    "d:(dir)p:(prefix)"
71430a5e8faSwyllys 	    "l:(label)n:(nickname)s:(subject)"
71530a5e8faSwyllys 	    "i:(issuer)S:(serial)"
71630a5e8faSwyllys 	    "K:(keyfile)c:(certfile)"
71730a5e8faSwyllys 	    "F:(outformat)"
71830a5e8faSwyllys 	    "I:(infile)o:(outfile)")) != EOF) {
71999ebb4caSwyllys 		if (EMPTYSTRING(optarg_av))
72099ebb4caSwyllys 			return (PK_ERR_USAGE);
72149e21299Sdinak 		switch (opt) {
72299ebb4caSwyllys 		case 'k':
72399ebb4caSwyllys 			kstype = KS2Int(optarg_av);
72499ebb4caSwyllys 			if (kstype == 0)
72599ebb4caSwyllys 				return (PK_ERR_USAGE);
72699ebb4caSwyllys 			break;
72799ebb4caSwyllys 		case 'y':
72899ebb4caSwyllys 			oclass = OT2Int(optarg_av);
72999ebb4caSwyllys 			if (oclass == -1)
73099ebb4caSwyllys 				return (PK_ERR_USAGE);
73199ebb4caSwyllys 			break;
73249e21299Sdinak 		case 'T':	/* token specifier */
73349e21299Sdinak 			if (token_spec)
73449e21299Sdinak 				return (PK_ERR_USAGE);
73549e21299Sdinak 			token_spec = optarg_av;
73649e21299Sdinak 			break;
73799ebb4caSwyllys 		case 'd':
73899ebb4caSwyllys 			if (dir)
73999ebb4caSwyllys 				return (PK_ERR_USAGE);
74099ebb4caSwyllys 			dir = optarg_av;
74199ebb4caSwyllys 			break;
74299ebb4caSwyllys 		case 'p':
74399ebb4caSwyllys 			if (prefix)
74499ebb4caSwyllys 				return (PK_ERR_USAGE);
74599ebb4caSwyllys 			prefix = optarg_av;
74699ebb4caSwyllys 			break;
74799ebb4caSwyllys 		case 'n':
74899ebb4caSwyllys 		case 'l':
74999ebb4caSwyllys 			if (certlabel)
75099ebb4caSwyllys 				return (PK_ERR_USAGE);
75199ebb4caSwyllys 			certlabel = optarg_av;
75299ebb4caSwyllys 			break;
75399ebb4caSwyllys 		case 's':
75499ebb4caSwyllys 			if (subject)
75599ebb4caSwyllys 				return (PK_ERR_USAGE);
75699ebb4caSwyllys 			subject = optarg_av;
75799ebb4caSwyllys 			break;
75899ebb4caSwyllys 		case 'i':
75999ebb4caSwyllys 			if (issuer)
76099ebb4caSwyllys 				return (PK_ERR_USAGE);
76199ebb4caSwyllys 			issuer = optarg_av;
76299ebb4caSwyllys 			break;
76399ebb4caSwyllys 		case 'S':
76499ebb4caSwyllys 			serstr = optarg_av;
76599ebb4caSwyllys 			break;
76699ebb4caSwyllys 		case 'F':
76799ebb4caSwyllys 			kfmt = Str2Format(optarg_av);
76899ebb4caSwyllys 			if (kfmt == KMF_FORMAT_UNDEF)
76999ebb4caSwyllys 				return (PK_ERR_USAGE);
77099ebb4caSwyllys 			break;
77199ebb4caSwyllys 		case 'I':	/* output file name */
77299ebb4caSwyllys 			if (infile)
77399ebb4caSwyllys 				return (PK_ERR_USAGE);
77499ebb4caSwyllys 			infile = optarg_av;
77599ebb4caSwyllys 			break;
77649e21299Sdinak 		case 'o':	/* output file name */
77749e21299Sdinak 			if (filename)
77849e21299Sdinak 				return (PK_ERR_USAGE);
77949e21299Sdinak 			filename = optarg_av;
78049e21299Sdinak 			break;
78199ebb4caSwyllys 		case 'c':	/* input cert file name */
78299ebb4caSwyllys 			if (certfile)
78399ebb4caSwyllys 				return (PK_ERR_USAGE);
78499ebb4caSwyllys 			certfile = optarg_av;
78599ebb4caSwyllys 			break;
78699ebb4caSwyllys 		case 'K':	/* input key file name */
78799ebb4caSwyllys 			if (keyfile)
78899ebb4caSwyllys 				return (PK_ERR_USAGE);
78999ebb4caSwyllys 			keyfile = optarg_av;
79099ebb4caSwyllys 			break;
79149e21299Sdinak 		default:
79249e21299Sdinak 			return (PK_ERR_USAGE);
79349e21299Sdinak 			break;
79449e21299Sdinak 		}
79549e21299Sdinak 	}
7967711facfSdinak 
79799ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified */
79899ebb4caSwyllys 	if (kstype == 0)
79999ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
80049e21299Sdinak 
80149e21299Sdinak 	/* Filename arg is required. */
80299ebb4caSwyllys 	if (EMPTYSTRING(filename)) {
80399ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("You must specify "
80430a5e8faSwyllys 		    "an 'outfile' parameter when exporting.\n"));
8057711facfSdinak 		return (PK_ERR_USAGE);
80699ebb4caSwyllys 	}
8077711facfSdinak 
80849e21299Sdinak 	/* No additional args allowed. */
80949e21299Sdinak 	argc -= optind_av;
81049e21299Sdinak 	argv += optind_av;
81149e21299Sdinak 	if (argc)
81249e21299Sdinak 		return (PK_ERR_USAGE);
81399ebb4caSwyllys 
81499ebb4caSwyllys 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
81599ebb4caSwyllys 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
81630a5e8faSwyllys 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
81799ebb4caSwyllys 
81899ebb4caSwyllys 		(void) fprintf(stderr, gettext("The objtype parameter "
81930a5e8faSwyllys 		    "is only relevant if keystore=pkcs11\n"));
82099ebb4caSwyllys 		return (PK_ERR_USAGE);
82199ebb4caSwyllys 	}
82299ebb4caSwyllys 
82399ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
82499ebb4caSwyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
82599ebb4caSwyllys 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
82699ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
82799ebb4caSwyllys 
82899ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_OPENSSL) {
82999ebb4caSwyllys 		if (kfmt != KMF_FORMAT_PKCS12) {
83099ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
83130a5e8faSwyllys 			    "is the only export format "
83230a5e8faSwyllys 			    "supported for the 'file' "
83330a5e8faSwyllys 			    "keystore.\n"));
83499ebb4caSwyllys 			return (PK_ERR_USAGE);
83599ebb4caSwyllys 		}
83699ebb4caSwyllys 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
83799ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A cert file"
83830a5e8faSwyllys 			    "and a key file must be specified "
83930a5e8faSwyllys 			    "when exporting to PKCS12 from the "
84030a5e8faSwyllys 			    "'file' keystore.\n"));
84199ebb4caSwyllys 			return (PK_ERR_USAGE);
84299ebb4caSwyllys 		}
84399ebb4caSwyllys 	}
8447711facfSdinak 
8457711facfSdinak 	/* Check if the file exists and might be overwritten. */
8467711facfSdinak 	if (access(filename, F_OK) == 0) {
84799ebb4caSwyllys 		cryptoerror(LOG_STDERR,
84830a5e8faSwyllys 		    gettext("Warning: file \"%s\" exists, "
84930a5e8faSwyllys 		    "will be overwritten."), filename);
8507711facfSdinak 		if (yesno(gettext("Continue with export? "),
8517711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
8527711facfSdinak 			return (0);
85373cc0e02Swyllys 		} else {
85473cc0e02Swyllys 			/* remove the file */
85573cc0e02Swyllys 			(void) unlink(filename);
8567711facfSdinak 		}
85799ebb4caSwyllys 	} else {
85899ebb4caSwyllys 		rv = verify_file(filename);
85999ebb4caSwyllys 		if (rv != KMF_OK) {
86099ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("The file (%s) "
86130a5e8faSwyllys 			    "cannot be created.\n"), filename);
86299ebb4caSwyllys 			return (PK_ERR_USAGE);
86399ebb4caSwyllys 		}
8647711facfSdinak 	}
8657711facfSdinak 
86699ebb4caSwyllys 	if (serstr != NULL) {
86799ebb4caSwyllys 		uchar_t *bytes = NULL;
86899ebb4caSwyllys 		size_t bytelen;
8697711facfSdinak 
87030a5e8faSwyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
87199ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
87299ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
87330a5e8faSwyllys 			    "must be specified as a hex number "
87430a5e8faSwyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
87599ebb4caSwyllys 			return (PK_ERR_USAGE);
87699ebb4caSwyllys 		}
87799ebb4caSwyllys 		serial.val = bytes;
87899ebb4caSwyllys 		serial.len = bytelen;
8797711facfSdinak 	}
8807711facfSdinak 
88199ebb4caSwyllys 	if ((kstype == KMF_KEYSTORE_PK11TOKEN ||
88230a5e8faSwyllys 	    kstype == KMF_KEYSTORE_NSS) &&
88330a5e8faSwyllys 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) ||
88430a5e8faSwyllys 	    kfmt == KMF_FORMAT_PKCS12)) {
88599ebb4caSwyllys 			(void) get_token_password(kstype, token_spec,
88630a5e8faSwyllys 			    &tokencred);
8877711facfSdinak 	}
8887711facfSdinak 
88930a5e8faSwyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
89099ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing "
89130a5e8faSwyllys 		    "KMF: 0x%02x\n"), rv);
89299ebb4caSwyllys 		return (rv);
8937711facfSdinak 	}
8947711facfSdinak 
89599ebb4caSwyllys 	switch (kstype) {
89699ebb4caSwyllys 		case KMF_KEYSTORE_PK11TOKEN:
89799ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
89830a5e8faSwyllys 				rv = pk_export_pk12_pk11(kmfhandle,
89930a5e8faSwyllys 				    token_spec, certlabel,
90030a5e8faSwyllys 				    issuer, subject,
90130a5e8faSwyllys 				    &serial, &tokencred,
90230a5e8faSwyllys 				    filename);
90330a5e8faSwyllys 			else if ((oclass & PK_KEY_OBJ) ||
90430a5e8faSwyllys 			    kfmt == KMF_FORMAT_RAWKEY)
90530a5e8faSwyllys 				rv = pk_export_pk11_keys(kmfhandle,
90630a5e8faSwyllys 				    token_spec, &tokencred, kfmt,
90773cc0e02Swyllys 				    certlabel, filename, oclass);
90899ebb4caSwyllys 			else
90999ebb4caSwyllys 				rv = pk_export_pk11_objects(kmfhandle,
91030a5e8faSwyllys 				    token_spec, certlabel,
91130a5e8faSwyllys 				    issuer, subject, &serial, kfmt,
91230a5e8faSwyllys 				    filename);
91399ebb4caSwyllys 			break;
91499ebb4caSwyllys 		case KMF_KEYSTORE_NSS:
91599ebb4caSwyllys 			if (dir == NULL)
91699ebb4caSwyllys 				dir = PK_DEFAULT_DIRECTORY;
91799ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
91899ebb4caSwyllys 				rv = pk_export_pk12_nss(kmfhandle,
91930a5e8faSwyllys 				    token_spec, dir, prefix,
92030a5e8faSwyllys 				    certlabel, issuer,
92130a5e8faSwyllys 				    subject, &serial,
92230a5e8faSwyllys 				    &tokencred, filename);
92399ebb4caSwyllys 			else
92499ebb4caSwyllys 				rv = pk_export_nss_objects(kmfhandle,
92530a5e8faSwyllys 				    token_spec,
92630a5e8faSwyllys 				    oclass, certlabel, issuer, subject,
92730a5e8faSwyllys 				    &serial, kfmt, dir, prefix, filename);
92899ebb4caSwyllys 			break;
92999ebb4caSwyllys 		case KMF_KEYSTORE_OPENSSL:
93099ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
93199ebb4caSwyllys 				rv = pk_export_pk12_files(kmfhandle,
93230a5e8faSwyllys 				    certfile, keyfile, dir,
93330a5e8faSwyllys 				    filename);
93499ebb4caSwyllys 			else
93599ebb4caSwyllys 				rv = pk_export_file_objects(kmfhandle, oclass,
93630a5e8faSwyllys 				    issuer, subject, &serial,
93730a5e8faSwyllys 				    dir, infile, filename);
93899ebb4caSwyllys 			break;
93999ebb4caSwyllys 		default:
94099ebb4caSwyllys 			rv = PK_ERR_USAGE;
94199ebb4caSwyllys 			break;
9427711facfSdinak 	}
9437711facfSdinak 
94499ebb4caSwyllys 	if (rv != KMF_OK) {
94599ebb4caSwyllys 		display_error(kmfhandle, rv,
94630a5e8faSwyllys 		    gettext("Error exporting objects"));
9477711facfSdinak 	}
9487711facfSdinak 
94999ebb4caSwyllys 	if (serial.val != NULL)
95099ebb4caSwyllys 		free(serial.val);
9517711facfSdinak 
95230a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
9537711facfSdinak 
95499ebb4caSwyllys 	return (rv);
9557711facfSdinak }
956