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*592106a2SWyllys Ingersoll  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237711facfSdinak  * Use is subject to license terms.
247711facfSdinak  */
257711facfSdinak 
267711facfSdinak /*
277711facfSdinak  * This file implements the export operation for this tool.
287711facfSdinak  * The basic flow of the process is to find the soft token,
297711facfSdinak  * log into it, find the PKCS#11 objects in the soft token
307711facfSdinak  * to be exported matching keys with their certificates, export
317711facfSdinak  * them to the PKCS#12 file encrypting them with a file password
327711facfSdinak  * if desired, and log out.
337711facfSdinak  */
347711facfSdinak 
357711facfSdinak #include <stdio.h>
367711facfSdinak #include <stdlib.h>
377711facfSdinak #include <string.h>
387711facfSdinak #include <errno.h>
3999ebb4caSwyllys #include <fcntl.h>
407711facfSdinak #include "common.h"
417711facfSdinak 
4299ebb4caSwyllys #include <kmfapi.h>
437711facfSdinak 
4499ebb4caSwyllys static KMF_RETURN
4530a5e8faSwyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist,
4630a5e8faSwyllys 	int numattr, KMF_X509_DER_CERT *cert)
477711facfSdinak {
4899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
4999ebb4caSwyllys 	uint32_t numcerts = 0;
507711facfSdinak 
5199ebb4caSwyllys 	numcerts = 0;
5299ebb4caSwyllys 	(void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
5330a5e8faSwyllys 
5430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
5530a5e8faSwyllys 	    &numcerts, sizeof (uint32_t));
5630a5e8faSwyllys 	numattr++;
5730a5e8faSwyllys 
5830a5e8faSwyllys 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
5999ebb4caSwyllys 	if (rv != KMF_OK) {
607711facfSdinak 		return (rv);
617711facfSdinak 	}
6299ebb4caSwyllys 	if (numcerts == 0) {
6399ebb4caSwyllys 		cryptoerror(LOG_STDERR,
6430a5e8faSwyllys 		    gettext("No matching certificates found."));
6599ebb4caSwyllys 		return (KMF_ERR_CERT_NOT_FOUND);
667711facfSdinak 
6799ebb4caSwyllys 	} else if (numcerts == 1) {
6830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
6930a5e8faSwyllys 		    KMF_X509_DER_CERT_ATTR, cert,
7030a5e8faSwyllys 		    sizeof (KMF_X509_DER_CERT));
7130a5e8faSwyllys 		numattr++;
7230a5e8faSwyllys 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
737711facfSdinak 
7499ebb4caSwyllys 	} else if (numcerts > 1) {
7599ebb4caSwyllys 		cryptoerror(LOG_STDERR,
7630a5e8faSwyllys 		    gettext("%d certificates found, refine the "
7730a5e8faSwyllys 		    "search parameters to eliminate ambiguity\n"),
7830a5e8faSwyllys 		    numcerts);
7999ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
807711facfSdinak 	}
8199ebb4caSwyllys 	return (rv);
827711facfSdinak }
837711facfSdinak 
8499ebb4caSwyllys static KMF_RETURN
8599ebb4caSwyllys pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
8699ebb4caSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
87448b8615Swyllys 	char *infile, char *filename)
887711facfSdinak {
8999ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
9099ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
9130a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
9230a5e8faSwyllys 	int numattr = 0;
9330a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
9499ebb4caSwyllys 
9599ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
9699ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
9730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
9830a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
9930a5e8faSwyllys 		    sizeof (kstype));
10030a5e8faSwyllys 		numattr++;
10130a5e8faSwyllys 
10230a5e8faSwyllys 		if (issuer != NULL) {
10330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
10430a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
10530a5e8faSwyllys 			    strlen(issuer));
10630a5e8faSwyllys 			numattr++;
10730a5e8faSwyllys 		}
10830a5e8faSwyllys 
10930a5e8faSwyllys 		if (subject != NULL) {
11030a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
11130a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
11230a5e8faSwyllys 			    strlen(subject));
11330a5e8faSwyllys 			numattr++;
11430a5e8faSwyllys 		}
11530a5e8faSwyllys 
11630a5e8faSwyllys 		if (serial != NULL) {
11730a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
11830a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
11930a5e8faSwyllys 			    sizeof (KMF_BIGINT));
12030a5e8faSwyllys 			numattr++;
12130a5e8faSwyllys 		}
12230a5e8faSwyllys 
12330a5e8faSwyllys 		if (infile != NULL) {
12430a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
12530a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, infile,
12630a5e8faSwyllys 			    strlen(infile));
12730a5e8faSwyllys 			numattr++;
12830a5e8faSwyllys 		}
12930a5e8faSwyllys 
13030a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
13130a5e8faSwyllys 		    &kmfcert);
13299ebb4caSwyllys 		if (rv == KMF_OK) {
13330a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
13430a5e8faSwyllys 			numattr = 0;
13599ebb4caSwyllys 
13630a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
13730a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
13830a5e8faSwyllys 			numattr++;
13930a5e8faSwyllys 
14030a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
14130a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
14230a5e8faSwyllys 			    sizeof (KMF_DATA));
14330a5e8faSwyllys 			numattr++;
14430a5e8faSwyllys 
14530a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
14630a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
14730a5e8faSwyllys 			    strlen(filename));
14830a5e8faSwyllys 			numattr++;
14930a5e8faSwyllys 
15030a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr,
15130a5e8faSwyllys 			    attrlist);
15230a5e8faSwyllys 
15330a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
15499ebb4caSwyllys 		}
15599ebb4caSwyllys 	}
15699ebb4caSwyllys 	return (rv);
1577711facfSdinak }
1587711facfSdinak 
15999ebb4caSwyllys static KMF_RETURN
16099ebb4caSwyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
16199ebb4caSwyllys 	char *token_spec, char *dir, char *prefix,
16299ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
16399ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
16499ebb4caSwyllys 	char *filename)
1657711facfSdinak {
16699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
16730a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
16830a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
16930a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
17030a5e8faSwyllys 	int numattr = 0;
1717711facfSdinak 
17299ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
17399ebb4caSwyllys 	if (rv != KMF_OK)
1747711facfSdinak 		return (rv);
1757711facfSdinak 
17699ebb4caSwyllys 	if (token_spec == NULL)
17799ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
1787711facfSdinak 
17930a5e8faSwyllys 	kstype = KMF_KEYSTORE_NSS;
18030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
18130a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
18230a5e8faSwyllys 	numattr++;
18330a5e8faSwyllys 
18430a5e8faSwyllys 	if (certlabel != NULL) {
18530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
18630a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
18730a5e8faSwyllys 		numattr++;
18830a5e8faSwyllys 	}
18930a5e8faSwyllys 
19030a5e8faSwyllys 	if (issuer != NULL) {
19130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
19230a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
19330a5e8faSwyllys 		numattr++;
19430a5e8faSwyllys 	}
19530a5e8faSwyllys 
19630a5e8faSwyllys 	if (subject != NULL) {
19730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
19830a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
19930a5e8faSwyllys 		numattr++;
20030a5e8faSwyllys 	}
2017711facfSdinak 
20230a5e8faSwyllys 	if (serial != NULL) {
20330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
20430a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
20530a5e8faSwyllys 		numattr++;
20630a5e8faSwyllys 	}
2077711facfSdinak 
20830a5e8faSwyllys 	if (tokencred != NULL) {
20930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
21030a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
21130a5e8faSwyllys 		numattr++;
21230a5e8faSwyllys 	}
21330a5e8faSwyllys 
21430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
21530a5e8faSwyllys 	    token_spec, strlen(token_spec));
21630a5e8faSwyllys 	numattr++;
21730a5e8faSwyllys 
21830a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
21930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
22030a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
22130a5e8faSwyllys 	numattr++;
22230a5e8faSwyllys 
22330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
22430a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
22530a5e8faSwyllys 	numattr++;
22630a5e8faSwyllys 
22730a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
22830a5e8faSwyllys 
22930a5e8faSwyllys 	if (p12cred.cred)
23030a5e8faSwyllys 		free(p12cred.cred);
2317711facfSdinak 
23299ebb4caSwyllys 	return (rv);
2337711facfSdinak }
2347711facfSdinak 
23599ebb4caSwyllys static KMF_RETURN
23699ebb4caSwyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
237448b8615Swyllys 	char *certfile, char *keyfile,
23899ebb4caSwyllys 	char *outfile)
2397711facfSdinak {
24099ebb4caSwyllys 	KMF_RETURN rv;
24130a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
24230a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
24330a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
24430a5e8faSwyllys 	int numattr = 0;
24530a5e8faSwyllys 
24630a5e8faSwyllys 	kstype = KMF_KEYSTORE_OPENSSL;
24730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
24830a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
24930a5e8faSwyllys 	numattr++;
25030a5e8faSwyllys 
25130a5e8faSwyllys 	if (certfile != NULL) {
25230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
25330a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
25430a5e8faSwyllys 		numattr++;
25530a5e8faSwyllys 	}
25630a5e8faSwyllys 
25730a5e8faSwyllys 	if (keyfile != NULL) {
25830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
25930a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
26030a5e8faSwyllys 		numattr++;
26130a5e8faSwyllys 	}
2627711facfSdinak 
26330a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
26430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
26530a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
26630a5e8faSwyllys 	numattr++;
2677711facfSdinak 
26830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
26930a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
27030a5e8faSwyllys 	numattr++;
2717711facfSdinak 
27230a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
2737711facfSdinak 
27430a5e8faSwyllys 	if (p12cred.cred)
27530a5e8faSwyllys 		free(p12cred.cred);
2767711facfSdinak 
27799ebb4caSwyllys 	return (rv);
2787711facfSdinak }
2797711facfSdinak 
28099ebb4caSwyllys static KMF_RETURN
28199ebb4caSwyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
28299ebb4caSwyllys 	int oclass, char *certlabel, char *issuer, char *subject,
28399ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
28499ebb4caSwyllys 	char *prefix, char *filename)
2857711facfSdinak {
28699ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
28799ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
28830a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
28930a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
29030a5e8faSwyllys 	int numattr = 0;
2917711facfSdinak 
29299ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
29399ebb4caSwyllys 	if (rv != KMF_OK)
2947711facfSdinak 		return (rv);
2957711facfSdinak 
29699ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
29799ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
29830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
29930a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
30030a5e8faSwyllys 		    sizeof (kstype));
30130a5e8faSwyllys 		numattr++;
30230a5e8faSwyllys 
30330a5e8faSwyllys 		if (certlabel != NULL) {
30430a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
30530a5e8faSwyllys 			    KMF_CERT_LABEL_ATTR, certlabel,
30630a5e8faSwyllys 			    strlen(certlabel));
30730a5e8faSwyllys 			numattr++;
30830a5e8faSwyllys 		}
30999ebb4caSwyllys 
31030a5e8faSwyllys 		if (issuer != NULL) {
31130a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
31230a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
31330a5e8faSwyllys 			    strlen(issuer));
31430a5e8faSwyllys 			numattr++;
31530a5e8faSwyllys 		}
31699ebb4caSwyllys 
31730a5e8faSwyllys 		if (subject != NULL) {
31830a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
31930a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
32030a5e8faSwyllys 			    strlen(subject));
32130a5e8faSwyllys 			numattr++;
32230a5e8faSwyllys 		}
32330a5e8faSwyllys 
32430a5e8faSwyllys 		if (serial != NULL) {
32530a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
32630a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
32730a5e8faSwyllys 			    sizeof (KMF_BIGINT));
32830a5e8faSwyllys 			numattr++;
32930a5e8faSwyllys 		}
33030a5e8faSwyllys 
33130a5e8faSwyllys 		if (token_spec != NULL) {
33230a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
33330a5e8faSwyllys 			    KMF_TOKEN_LABEL_ATTR, token_spec,
33430a5e8faSwyllys 			    strlen(token_spec));
33530a5e8faSwyllys 			numattr++;
33630a5e8faSwyllys 		}
33730a5e8faSwyllys 
33830a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
33930a5e8faSwyllys 		    &kmfcert);
34099ebb4caSwyllys 		if (rv == KMF_OK) {
34130a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
34230a5e8faSwyllys 			numattr = 0;
34330a5e8faSwyllys 
34430a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
34530a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
34630a5e8faSwyllys 			numattr++;
34799ebb4caSwyllys 
34830a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
34930a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
35030a5e8faSwyllys 			    sizeof (KMF_DATA));
35130a5e8faSwyllys 			numattr++;
35299ebb4caSwyllys 
35330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
35430a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
35530a5e8faSwyllys 			    strlen(filename));
35630a5e8faSwyllys 			numattr++;
35730a5e8faSwyllys 
35830a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
35930a5e8faSwyllys 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
36030a5e8faSwyllys 			numattr++;
36130a5e8faSwyllys 
36230a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
36330a5e8faSwyllys 
36430a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
3657711facfSdinak 		}
3667711facfSdinak 	}
36799ebb4caSwyllys 	return (rv);
36899ebb4caSwyllys }
3697711facfSdinak 
37099ebb4caSwyllys static KMF_RETURN
37199ebb4caSwyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
37299ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
37399ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
37499ebb4caSwyllys {
37599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
37630a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
37730a5e8faSwyllys 	KMF_CREDENTIAL p12cred = { NULL, 0};
37830a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
37930a5e8faSwyllys 	int numattr = 0;
3807711facfSdinak 
38199ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
38299ebb4caSwyllys 	if (rv != KMF_OK) {
38399ebb4caSwyllys 		return (rv);
3847711facfSdinak 	}
3857711facfSdinak 
38630a5e8faSwyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
38730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
38830a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
38930a5e8faSwyllys 	numattr++;
39030a5e8faSwyllys 
39130a5e8faSwyllys 	if (certlabel != NULL) {
39230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
39330a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
39430a5e8faSwyllys 		numattr++;
39530a5e8faSwyllys 	}
39630a5e8faSwyllys 
39730a5e8faSwyllys 	if (issuer != NULL) {
39830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
39930a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
40030a5e8faSwyllys 		numattr++;
40130a5e8faSwyllys 	}
40230a5e8faSwyllys 
40330a5e8faSwyllys 	if (subject != NULL) {
40430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
40530a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
40630a5e8faSwyllys 		numattr++;
40730a5e8faSwyllys 	}
40830a5e8faSwyllys 
40930a5e8faSwyllys 	if (serial != NULL) {
41030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
41130a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
41230a5e8faSwyllys 		numattr++;
41330a5e8faSwyllys 	}
41430a5e8faSwyllys 
41530a5e8faSwyllys 	if (tokencred != NULL) {
41630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
41730a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
41830a5e8faSwyllys 		numattr++;
41930a5e8faSwyllys 	}
42030a5e8faSwyllys 
42130a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
42230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
42330a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
42430a5e8faSwyllys 	numattr++;
42530a5e8faSwyllys 
42630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
42730a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
42830a5e8faSwyllys 	numattr++;
42930a5e8faSwyllys 
43030a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
43130a5e8faSwyllys 
43230a5e8faSwyllys 	if (p12cred.cred)
43330a5e8faSwyllys 		free(p12cred.cred);
43430a5e8faSwyllys 
43530a5e8faSwyllys 	return (rv);
43630a5e8faSwyllys }
43730a5e8faSwyllys 
43830a5e8faSwyllys static KMF_RETURN
43930a5e8faSwyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
44030a5e8faSwyllys 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
44173cc0e02Swyllys 	char *label, char *filename, int oclass)
44230a5e8faSwyllys {
44330a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
44430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
44573cc0e02Swyllys 	KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE;
44630a5e8faSwyllys 	int numattr = 0;
44730a5e8faSwyllys 	uint32_t numkeys = 1;
44830a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
44930a5e8faSwyllys 	KMF_KEY_HANDLE key;
45030a5e8faSwyllys 	boolean_t is_token = B_TRUE;
45130a5e8faSwyllys 
45230a5e8faSwyllys 	if (EMPTYSTRING(label)) {
45330a5e8faSwyllys 		cryptoerror(LOG_STDERR, gettext("A label "
45430a5e8faSwyllys 		    "must be specified to export a key."));
45530a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
45630a5e8faSwyllys 	}
45730a5e8faSwyllys 
45830a5e8faSwyllys 	rv = select_token(kmfhandle, token, TRUE);
45930a5e8faSwyllys 	if (rv != KMF_OK) {
46030a5e8faSwyllys 		return (rv);
46130a5e8faSwyllys 	}
46230a5e8faSwyllys 
46330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
46430a5e8faSwyllys 	    &kstype, sizeof (kstype));
46530a5e8faSwyllys 	numattr++;
46630a5e8faSwyllys 
46730a5e8faSwyllys 	if (cred != NULL) {
46830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
46930a5e8faSwyllys 		    cred, sizeof (KMF_CREDENTIAL));
47030a5e8faSwyllys 		numattr++;
47130a5e8faSwyllys 	}
47230a5e8faSwyllys 
47330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
47430a5e8faSwyllys 	    label, strlen(label));
47530a5e8faSwyllys 	numattr++;
47630a5e8faSwyllys 
47730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
47830a5e8faSwyllys 	    &numkeys, sizeof (numkeys));
47930a5e8faSwyllys 	numattr++;
4807711facfSdinak 
48130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
48230a5e8faSwyllys 	    &key, sizeof (key));
48330a5e8faSwyllys 	numattr++;
4847711facfSdinak 
48530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
48630a5e8faSwyllys 	    &is_token, sizeof (is_token));
48730a5e8faSwyllys 	numattr++;
4887711facfSdinak 
48930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
49030a5e8faSwyllys 	    &format, sizeof (format));
49130a5e8faSwyllys 	numattr++;
49230a5e8faSwyllys 
49373cc0e02Swyllys 	/* Check to see if we are exporting private or public only */
49473cc0e02Swyllys 	if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ)
49573cc0e02Swyllys 		kclass = KMF_ASYM_PRI;
49673cc0e02Swyllys 	else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ)
49773cc0e02Swyllys 		kclass = KMF_ASYM_PUB;
49873cc0e02Swyllys 	else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ)
49973cc0e02Swyllys 		kclass = KMF_SYMMETRIC;
50073cc0e02Swyllys 	else /* only 1 key at a time can be exported here, so default to pri */
50173cc0e02Swyllys 		kclass = KMF_ASYM_PRI;
50273cc0e02Swyllys 
50373cc0e02Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
50473cc0e02Swyllys 	    &kclass, sizeof (kclass));
50573cc0e02Swyllys 	numattr++;
50673cc0e02Swyllys 
50730a5e8faSwyllys 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
50871a79fe7Swyllys 	/*
50971a79fe7Swyllys 	 * If nothing found but caller wanted ALL keys, try symmetric
51071a79fe7Swyllys 	 * this time.
51171a79fe7Swyllys 	 */
51271a79fe7Swyllys 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
51371a79fe7Swyllys 		kclass = KMF_SYMMETRIC;
51471a79fe7Swyllys 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
51571a79fe7Swyllys 	}
51671a79fe7Swyllys 	/*
51771a79fe7Swyllys 	 * If nothing found but caller wanted ALL keys, try asymmetric
51871a79fe7Swyllys 	 * public this time.
51971a79fe7Swyllys 	 */
52071a79fe7Swyllys 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
52171a79fe7Swyllys 		kclass = KMF_ASYM_PUB;
52271a79fe7Swyllys 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
52371a79fe7Swyllys 	}
52430a5e8faSwyllys 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
52530a5e8faSwyllys 		KMF_RAW_SYM_KEY rkey;
52630a5e8faSwyllys 
52730a5e8faSwyllys 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
52830a5e8faSwyllys 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
52930a5e8faSwyllys 		if (rv == KMF_OK) {
53030a5e8faSwyllys 			int fd, n, total = 0;
53130a5e8faSwyllys 
53230a5e8faSwyllys 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
53330a5e8faSwyllys 			if (fd == -1) {
53430a5e8faSwyllys 				rv = KMF_ERR_OPEN_FILE;
53530a5e8faSwyllys 				goto done;
53630a5e8faSwyllys 			}
53730a5e8faSwyllys 			do {
53830a5e8faSwyllys 				n = write(fd, rkey.keydata.val + total,
53930a5e8faSwyllys 				    rkey.keydata.len - total);
54030a5e8faSwyllys 				if (n < 0) {
54130a5e8faSwyllys 					if (errno == EINTR)
54230a5e8faSwyllys 						continue;
54346d33f7eSwyllys 					(void) close(fd);
54430a5e8faSwyllys 					rv = KMF_ERR_WRITE_FILE;
54530a5e8faSwyllys 					goto done;
54630a5e8faSwyllys 				}
54730a5e8faSwyllys 				total += n;
54830a5e8faSwyllys 
54930a5e8faSwyllys 			} while (total < rkey.keydata.len);
55046d33f7eSwyllys 			(void) close(fd);
55130a5e8faSwyllys 		}
55230a5e8faSwyllys done:
55330a5e8faSwyllys 		kmf_free_bigint(&rkey.keydata);
55430a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
55530a5e8faSwyllys 	} else if (rv == KMF_OK) {
55630a5e8faSwyllys 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
55746d33f7eSwyllys 		(void) printf(gettext("Found %d asymmetric keys\n"), numkeys);
55830a5e8faSwyllys 
55930a5e8faSwyllys 		numattr = 0;
56030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
56130a5e8faSwyllys 		    &sslks, sizeof (sslks));
56230a5e8faSwyllys 		numattr++;
56330a5e8faSwyllys 
56430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
56530a5e8faSwyllys 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
56630a5e8faSwyllys 		numattr++;
56730a5e8faSwyllys 
56830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
56930a5e8faSwyllys 		    &format, sizeof (format));
57030a5e8faSwyllys 		numattr++;
57130a5e8faSwyllys 
57230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
57330a5e8faSwyllys 		    filename, strlen(filename));
57430a5e8faSwyllys 		numattr++;
57530a5e8faSwyllys 
57673cc0e02Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
57773cc0e02Swyllys 		    &key.keyclass, sizeof (KMF_KEY_CLASS));
57873cc0e02Swyllys 		numattr++;
57973cc0e02Swyllys 
58030a5e8faSwyllys 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
58130a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
58230a5e8faSwyllys 	}
5837711facfSdinak 
58499ebb4caSwyllys 	return (rv);
5857711facfSdinak }
5867711facfSdinak 
58799ebb4caSwyllys static KMF_RETURN
58899ebb4caSwyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
589*592106a2SWyllys Ingersoll 	KMF_CREDENTIAL *cred, char *certlabel, char *issuer, char *subject,
59099ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
59199ebb4caSwyllys 	char *filename)
5927711facfSdinak {
59399ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
59499ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
59530a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
59630a5e8faSwyllys 	int numattr = 0;
59730a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
5987711facfSdinak 
59999ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
6007711facfSdinak 
601*592106a2SWyllys Ingersoll 	if (rv != KMF_OK)
6027711facfSdinak 		return (rv);
6037711facfSdinak 
60430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
60530a5e8faSwyllys 	    &kstype, sizeof (kstype));
60630a5e8faSwyllys 	numattr++;
6077711facfSdinak 
608*592106a2SWyllys Ingersoll 	if (cred != NULL) {
609*592106a2SWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
610*592106a2SWyllys Ingersoll 		    cred, sizeof (KMF_CREDENTIAL));
611*592106a2SWyllys Ingersoll 		numattr++;
612*592106a2SWyllys Ingersoll 	}
61330a5e8faSwyllys 	if (certlabel != NULL) {
61430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
61530a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel,
61630a5e8faSwyllys 		    strlen(certlabel));
61730a5e8faSwyllys 		numattr++;
61830a5e8faSwyllys 	}
61930a5e8faSwyllys 
62030a5e8faSwyllys 	if (issuer != NULL) {
62130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
62230a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer,
62330a5e8faSwyllys 		    strlen(issuer));
62430a5e8faSwyllys 		numattr++;
62530a5e8faSwyllys 	}
62630a5e8faSwyllys 
62730a5e8faSwyllys 	if (subject != NULL) {
62830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
62930a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject,
63030a5e8faSwyllys 		    strlen(subject));
63130a5e8faSwyllys 		numattr++;
63230a5e8faSwyllys 	}
63330a5e8faSwyllys 
63430a5e8faSwyllys 	if (serial != NULL) {
63530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
63630a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial,
63730a5e8faSwyllys 		    sizeof (KMF_BIGINT));
63830a5e8faSwyllys 		numattr++;
63930a5e8faSwyllys 	}
64030a5e8faSwyllys 
64130a5e8faSwyllys 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
6427711facfSdinak 
64399ebb4caSwyllys 	if (rv == KMF_OK) {
64430a5e8faSwyllys 		kstype = KMF_KEYSTORE_OPENSSL;
64530a5e8faSwyllys 		numattr = 0;
64630a5e8faSwyllys 
64730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
64830a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
64930a5e8faSwyllys 		numattr++;
65030a5e8faSwyllys 
65130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
65230a5e8faSwyllys 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
65330a5e8faSwyllys 		    sizeof (KMF_DATA));
65430a5e8faSwyllys 		numattr++;
65530a5e8faSwyllys 
65630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
65730a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
65830a5e8faSwyllys 		numattr++;
65930a5e8faSwyllys 
66030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
66130a5e8faSwyllys 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
66230a5e8faSwyllys 		numattr++;
6637711facfSdinak 
66430a5e8faSwyllys 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
6657711facfSdinak 
66630a5e8faSwyllys 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
6677711facfSdinak 	}
66899ebb4caSwyllys 	return (rv);
6697711facfSdinak }
6707711facfSdinak 
6717711facfSdinak /*
67299ebb4caSwyllys  * Export objects from one keystore to a file.
6737711facfSdinak  */
6747711facfSdinak int
6757711facfSdinak pk_export(int argc, char *argv[])
6767711facfSdinak {
67749e21299Sdinak 	int		opt;
67849e21299Sdinak 	extern int	optind_av;
67949e21299Sdinak 	extern char	*optarg_av;
68049e21299Sdinak 	char		*token_spec = NULL;
6817711facfSdinak 	char		*filename = NULL;
68299ebb4caSwyllys 	char		*dir = NULL;
68399ebb4caSwyllys 	char		*prefix = NULL;
68499ebb4caSwyllys 	char		*certlabel = NULL;
68599ebb4caSwyllys 	char		*subject = NULL;
68699ebb4caSwyllys 	char		*issuer = NULL;
68799ebb4caSwyllys 	char		*infile = NULL;
68899ebb4caSwyllys 	char		*keyfile = NULL;
68999ebb4caSwyllys 	char		*certfile = NULL;
69099ebb4caSwyllys 	char		*serstr = NULL;
69199ebb4caSwyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
69299ebb4caSwyllys 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
69399ebb4caSwyllys 	KMF_RETURN		rv = KMF_OK;
69499ebb4caSwyllys 	int		oclass = PK_CERT_OBJ;
69599ebb4caSwyllys 	KMF_BIGINT	serial = { NULL, 0 };
69699ebb4caSwyllys 	KMF_HANDLE_T	kmfhandle = NULL;
69799ebb4caSwyllys 	KMF_CREDENTIAL	tokencred = {NULL, 0};
6987711facfSdinak 
69949e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
70099ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
70130a5e8faSwyllys 	    "k:(keystore)y:(objtype)T:(token)"
70230a5e8faSwyllys 	    "d:(dir)p:(prefix)"
70330a5e8faSwyllys 	    "l:(label)n:(nickname)s:(subject)"
70430a5e8faSwyllys 	    "i:(issuer)S:(serial)"
70530a5e8faSwyllys 	    "K:(keyfile)c:(certfile)"
70630a5e8faSwyllys 	    "F:(outformat)"
70730a5e8faSwyllys 	    "I:(infile)o:(outfile)")) != EOF) {
70899ebb4caSwyllys 		if (EMPTYSTRING(optarg_av))
70999ebb4caSwyllys 			return (PK_ERR_USAGE);
71049e21299Sdinak 		switch (opt) {
71199ebb4caSwyllys 		case 'k':
71299ebb4caSwyllys 			kstype = KS2Int(optarg_av);
71399ebb4caSwyllys 			if (kstype == 0)
71499ebb4caSwyllys 				return (PK_ERR_USAGE);
71599ebb4caSwyllys 			break;
71699ebb4caSwyllys 		case 'y':
71799ebb4caSwyllys 			oclass = OT2Int(optarg_av);
71899ebb4caSwyllys 			if (oclass == -1)
71999ebb4caSwyllys 				return (PK_ERR_USAGE);
72099ebb4caSwyllys 			break;
72149e21299Sdinak 		case 'T':	/* token specifier */
72249e21299Sdinak 			if (token_spec)
72349e21299Sdinak 				return (PK_ERR_USAGE);
72449e21299Sdinak 			token_spec = optarg_av;
72549e21299Sdinak 			break;
72699ebb4caSwyllys 		case 'd':
72799ebb4caSwyllys 			if (dir)
72899ebb4caSwyllys 				return (PK_ERR_USAGE);
72999ebb4caSwyllys 			dir = optarg_av;
73099ebb4caSwyllys 			break;
73199ebb4caSwyllys 		case 'p':
73299ebb4caSwyllys 			if (prefix)
73399ebb4caSwyllys 				return (PK_ERR_USAGE);
73499ebb4caSwyllys 			prefix = optarg_av;
73599ebb4caSwyllys 			break;
73699ebb4caSwyllys 		case 'n':
73799ebb4caSwyllys 		case 'l':
73899ebb4caSwyllys 			if (certlabel)
73999ebb4caSwyllys 				return (PK_ERR_USAGE);
74099ebb4caSwyllys 			certlabel = optarg_av;
74199ebb4caSwyllys 			break;
74299ebb4caSwyllys 		case 's':
74399ebb4caSwyllys 			if (subject)
74499ebb4caSwyllys 				return (PK_ERR_USAGE);
74599ebb4caSwyllys 			subject = optarg_av;
74699ebb4caSwyllys 			break;
74799ebb4caSwyllys 		case 'i':
74899ebb4caSwyllys 			if (issuer)
74999ebb4caSwyllys 				return (PK_ERR_USAGE);
75099ebb4caSwyllys 			issuer = optarg_av;
75199ebb4caSwyllys 			break;
75299ebb4caSwyllys 		case 'S':
75399ebb4caSwyllys 			serstr = optarg_av;
75499ebb4caSwyllys 			break;
75599ebb4caSwyllys 		case 'F':
75699ebb4caSwyllys 			kfmt = Str2Format(optarg_av);
75799ebb4caSwyllys 			if (kfmt == KMF_FORMAT_UNDEF)
75899ebb4caSwyllys 				return (PK_ERR_USAGE);
75999ebb4caSwyllys 			break;
76099ebb4caSwyllys 		case 'I':	/* output file name */
76199ebb4caSwyllys 			if (infile)
76299ebb4caSwyllys 				return (PK_ERR_USAGE);
76399ebb4caSwyllys 			infile = optarg_av;
76499ebb4caSwyllys 			break;
76549e21299Sdinak 		case 'o':	/* output file name */
76649e21299Sdinak 			if (filename)
76749e21299Sdinak 				return (PK_ERR_USAGE);
76849e21299Sdinak 			filename = optarg_av;
76949e21299Sdinak 			break;
77099ebb4caSwyllys 		case 'c':	/* input cert file name */
77199ebb4caSwyllys 			if (certfile)
77299ebb4caSwyllys 				return (PK_ERR_USAGE);
77399ebb4caSwyllys 			certfile = optarg_av;
77499ebb4caSwyllys 			break;
77599ebb4caSwyllys 		case 'K':	/* input key file name */
77699ebb4caSwyllys 			if (keyfile)
77799ebb4caSwyllys 				return (PK_ERR_USAGE);
77899ebb4caSwyllys 			keyfile = optarg_av;
77999ebb4caSwyllys 			break;
78049e21299Sdinak 		default:
78149e21299Sdinak 			return (PK_ERR_USAGE);
78249e21299Sdinak 			break;
78349e21299Sdinak 		}
78449e21299Sdinak 	}
7857711facfSdinak 
78699ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified */
78799ebb4caSwyllys 	if (kstype == 0)
78899ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
78949e21299Sdinak 
79049e21299Sdinak 	/* Filename arg is required. */
79199ebb4caSwyllys 	if (EMPTYSTRING(filename)) {
79299ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("You must specify "
79330a5e8faSwyllys 		    "an 'outfile' parameter when exporting.\n"));
7947711facfSdinak 		return (PK_ERR_USAGE);
79599ebb4caSwyllys 	}
7967711facfSdinak 
79749e21299Sdinak 	/* No additional args allowed. */
79849e21299Sdinak 	argc -= optind_av;
79949e21299Sdinak 	argv += optind_av;
80049e21299Sdinak 	if (argc)
80149e21299Sdinak 		return (PK_ERR_USAGE);
80299ebb4caSwyllys 
803577f4726Swyllys 	DIR_OPTION_CHECK(kstype, dir);
804577f4726Swyllys 
80599ebb4caSwyllys 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
80699ebb4caSwyllys 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
80730a5e8faSwyllys 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
80899ebb4caSwyllys 
80999ebb4caSwyllys 		(void) fprintf(stderr, gettext("The objtype parameter "
81030a5e8faSwyllys 		    "is only relevant if keystore=pkcs11\n"));
81199ebb4caSwyllys 		return (PK_ERR_USAGE);
81299ebb4caSwyllys 	}
81399ebb4caSwyllys 
81499ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
81599ebb4caSwyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
81699ebb4caSwyllys 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
81799ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
81899ebb4caSwyllys 
81999ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_OPENSSL) {
82099ebb4caSwyllys 		if (kfmt != KMF_FORMAT_PKCS12) {
82199ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
82230a5e8faSwyllys 			    "is the only export format "
82330a5e8faSwyllys 			    "supported for the 'file' "
82430a5e8faSwyllys 			    "keystore.\n"));
82599ebb4caSwyllys 			return (PK_ERR_USAGE);
82699ebb4caSwyllys 		}
82799ebb4caSwyllys 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
82899ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A cert file"
82930a5e8faSwyllys 			    "and a key file must be specified "
83030a5e8faSwyllys 			    "when exporting to PKCS12 from the "
83130a5e8faSwyllys 			    "'file' keystore.\n"));
83299ebb4caSwyllys 			return (PK_ERR_USAGE);
83399ebb4caSwyllys 		}
83499ebb4caSwyllys 	}
8357711facfSdinak 
8367711facfSdinak 	/* Check if the file exists and might be overwritten. */
8377711facfSdinak 	if (access(filename, F_OK) == 0) {
83899ebb4caSwyllys 		cryptoerror(LOG_STDERR,
83930a5e8faSwyllys 		    gettext("Warning: file \"%s\" exists, "
84030a5e8faSwyllys 		    "will be overwritten."), filename);
8417711facfSdinak 		if (yesno(gettext("Continue with export? "),
8427711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
8437711facfSdinak 			return (0);
84473cc0e02Swyllys 		} else {
84573cc0e02Swyllys 			/* remove the file */
84673cc0e02Swyllys 			(void) unlink(filename);
8477711facfSdinak 		}
84899ebb4caSwyllys 	} else {
84999ebb4caSwyllys 		rv = verify_file(filename);
85099ebb4caSwyllys 		if (rv != KMF_OK) {
85199ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("The file (%s) "
85230a5e8faSwyllys 			    "cannot be created.\n"), filename);
85399ebb4caSwyllys 			return (PK_ERR_USAGE);
85499ebb4caSwyllys 		}
8557711facfSdinak 	}
8567711facfSdinak 
85799ebb4caSwyllys 	if (serstr != NULL) {
85899ebb4caSwyllys 		uchar_t *bytes = NULL;
85999ebb4caSwyllys 		size_t bytelen;
8607711facfSdinak 
86130a5e8faSwyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
86299ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
86399ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
86430a5e8faSwyllys 			    "must be specified as a hex number "
86530a5e8faSwyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
86699ebb4caSwyllys 			return (PK_ERR_USAGE);
86799ebb4caSwyllys 		}
86899ebb4caSwyllys 		serial.val = bytes;
86999ebb4caSwyllys 		serial.len = bytelen;
8707711facfSdinak 	}
8717711facfSdinak 
872*592106a2SWyllys Ingersoll 	if (kstype == KMF_KEYSTORE_PK11TOKEN ||
873*592106a2SWyllys Ingersoll 	    ((kstype == KMF_KEYSTORE_NSS) &&
874*592106a2SWyllys Ingersoll 	    (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) ||
875*592106a2SWyllys Ingersoll 	    kfmt == KMF_FORMAT_PKCS12) {
87699ebb4caSwyllys 			(void) get_token_password(kstype, token_spec,
87730a5e8faSwyllys 			    &tokencred);
8787711facfSdinak 	}
8797711facfSdinak 
88030a5e8faSwyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
88199ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing "
88230a5e8faSwyllys 		    "KMF: 0x%02x\n"), rv);
88399ebb4caSwyllys 		return (rv);
8847711facfSdinak 	}
8857711facfSdinak 
88699ebb4caSwyllys 	switch (kstype) {
88799ebb4caSwyllys 		case KMF_KEYSTORE_PK11TOKEN:
88899ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
88930a5e8faSwyllys 				rv = pk_export_pk12_pk11(kmfhandle,
89030a5e8faSwyllys 				    token_spec, certlabel,
89130a5e8faSwyllys 				    issuer, subject,
89230a5e8faSwyllys 				    &serial, &tokencred,
89330a5e8faSwyllys 				    filename);
89430a5e8faSwyllys 			else if ((oclass & PK_KEY_OBJ) ||
89530a5e8faSwyllys 			    kfmt == KMF_FORMAT_RAWKEY)
89630a5e8faSwyllys 				rv = pk_export_pk11_keys(kmfhandle,
89730a5e8faSwyllys 				    token_spec, &tokencred, kfmt,
89873cc0e02Swyllys 				    certlabel, filename, oclass);
89999ebb4caSwyllys 			else
90099ebb4caSwyllys 				rv = pk_export_pk11_objects(kmfhandle,
901*592106a2SWyllys Ingersoll 				    token_spec, &tokencred, certlabel,
90230a5e8faSwyllys 				    issuer, subject, &serial, kfmt,
90330a5e8faSwyllys 				    filename);
90499ebb4caSwyllys 			break;
90599ebb4caSwyllys 		case KMF_KEYSTORE_NSS:
90699ebb4caSwyllys 			if (dir == NULL)
90799ebb4caSwyllys 				dir = PK_DEFAULT_DIRECTORY;
90899ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
90999ebb4caSwyllys 				rv = pk_export_pk12_nss(kmfhandle,
91030a5e8faSwyllys 				    token_spec, dir, prefix,
91130a5e8faSwyllys 				    certlabel, issuer,
91230a5e8faSwyllys 				    subject, &serial,
91330a5e8faSwyllys 				    &tokencred, filename);
91499ebb4caSwyllys 			else
91599ebb4caSwyllys 				rv = pk_export_nss_objects(kmfhandle,
91630a5e8faSwyllys 				    token_spec,
91730a5e8faSwyllys 				    oclass, certlabel, issuer, subject,
91830a5e8faSwyllys 				    &serial, kfmt, dir, prefix, filename);
91999ebb4caSwyllys 			break;
92099ebb4caSwyllys 		case KMF_KEYSTORE_OPENSSL:
92199ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
92299ebb4caSwyllys 				rv = pk_export_pk12_files(kmfhandle,
923448b8615Swyllys 				    certfile, keyfile, filename);
92499ebb4caSwyllys 			else
92599ebb4caSwyllys 				rv = pk_export_file_objects(kmfhandle, oclass,
92630a5e8faSwyllys 				    issuer, subject, &serial,
927448b8615Swyllys 				    infile, filename);
92899ebb4caSwyllys 			break;
92999ebb4caSwyllys 		default:
93099ebb4caSwyllys 			rv = PK_ERR_USAGE;
93199ebb4caSwyllys 			break;
9327711facfSdinak 	}
9337711facfSdinak 
93499ebb4caSwyllys 	if (rv != KMF_OK) {
93599ebb4caSwyllys 		display_error(kmfhandle, rv,
93630a5e8faSwyllys 		    gettext("Error exporting objects"));
9377711facfSdinak 	}
9387711facfSdinak 
93999ebb4caSwyllys 	if (serial.val != NULL)
94099ebb4caSwyllys 		free(serial.val);
9417711facfSdinak 
94230a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
9437711facfSdinak 
94499ebb4caSwyllys 	return (rv);
9457711facfSdinak }
946