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  *
212c9a247fSWyllys Ingersoll  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2233f5ff17SMilan Jurik  * Copyright 2012 Milan Jurik. All rights reserved.
237711facfSdinak  */
247711facfSdinak 
257711facfSdinak /*
267711facfSdinak  * This file implements the export operation for this tool.
277711facfSdinak  * The basic flow of the process is to find the soft token,
287711facfSdinak  * log into it, find the PKCS#11 objects in the soft token
297711facfSdinak  * to be exported matching keys with their certificates, export
307711facfSdinak  * them to the PKCS#12 file encrypting them with a file password
317711facfSdinak  * if desired, and log out.
327711facfSdinak  */
337711facfSdinak 
347711facfSdinak #include <stdio.h>
357711facfSdinak #include <stdlib.h>
367711facfSdinak #include <string.h>
377711facfSdinak #include <errno.h>
3899ebb4caSwyllys #include <fcntl.h>
397711facfSdinak #include "common.h"
407711facfSdinak 
4199ebb4caSwyllys #include <kmfapi.h>
427711facfSdinak 
4399ebb4caSwyllys static KMF_RETURN
pk_find_export_cert(KMF_HANDLE_T kmfhandle,KMF_ATTRIBUTE * attrlist,int numattr,KMF_X509_DER_CERT * cert)4430a5e8faSwyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist,
4530a5e8faSwyllys 	int numattr, KMF_X509_DER_CERT *cert)
467711facfSdinak {
4799ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
4899ebb4caSwyllys 	uint32_t numcerts = 0;
497711facfSdinak 
5099ebb4caSwyllys 	numcerts = 0;
5199ebb4caSwyllys 	(void) memset(cert, 0, sizeof (KMF_X509_DER_CERT));
5230a5e8faSwyllys 
5330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
5430a5e8faSwyllys 	    &numcerts, sizeof (uint32_t));
5530a5e8faSwyllys 	numattr++;
5630a5e8faSwyllys 
5730a5e8faSwyllys 	rv = kmf_find_cert(kmfhandle, numattr, attrlist);
5899ebb4caSwyllys 	if (rv != KMF_OK) {
597711facfSdinak 		return (rv);
607711facfSdinak 	}
6199ebb4caSwyllys 	if (numcerts == 0) {
6299ebb4caSwyllys 		cryptoerror(LOG_STDERR,
6330a5e8faSwyllys 		    gettext("No matching certificates found."));
6499ebb4caSwyllys 		return (KMF_ERR_CERT_NOT_FOUND);
657711facfSdinak 
6699ebb4caSwyllys 	} else if (numcerts == 1) {
6730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
6830a5e8faSwyllys 		    KMF_X509_DER_CERT_ATTR, cert,
6930a5e8faSwyllys 		    sizeof (KMF_X509_DER_CERT));
7030a5e8faSwyllys 		numattr++;
7130a5e8faSwyllys 		rv = kmf_find_cert(kmfhandle, numattr, attrlist);
727711facfSdinak 
7399ebb4caSwyllys 	} else if (numcerts > 1) {
7499ebb4caSwyllys 		cryptoerror(LOG_STDERR,
7530a5e8faSwyllys 		    gettext("%d certificates found, refine the "
7630a5e8faSwyllys 		    "search parameters to eliminate ambiguity\n"),
7730a5e8faSwyllys 		    numcerts);
7899ebb4caSwyllys 		return (KMF_ERR_BAD_PARAMETER);
797711facfSdinak 	}
8099ebb4caSwyllys 	return (rv);
817711facfSdinak }
827711facfSdinak 
8399ebb4caSwyllys static KMF_RETURN
pk_export_file_objects(KMF_HANDLE_T kmfhandle,int oclass,char * issuer,char * subject,KMF_BIGINT * serial,char * infile,char * filename)8499ebb4caSwyllys pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass,
8599ebb4caSwyllys 	char *issuer, char *subject, KMF_BIGINT *serial,
86448b8615Swyllys 	char *infile, char *filename)
877711facfSdinak {
8899ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
8999ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
9030a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
9130a5e8faSwyllys 	int numattr = 0;
9230a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
9399ebb4caSwyllys 
9499ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
9599ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
9630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
9730a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
9830a5e8faSwyllys 		    sizeof (kstype));
9930a5e8faSwyllys 		numattr++;
10030a5e8faSwyllys 
10130a5e8faSwyllys 		if (issuer != NULL) {
10230a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
10330a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
10430a5e8faSwyllys 			    strlen(issuer));
10530a5e8faSwyllys 			numattr++;
10630a5e8faSwyllys 		}
10730a5e8faSwyllys 
10830a5e8faSwyllys 		if (subject != NULL) {
10930a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
11030a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
11130a5e8faSwyllys 			    strlen(subject));
11230a5e8faSwyllys 			numattr++;
11330a5e8faSwyllys 		}
11430a5e8faSwyllys 
11530a5e8faSwyllys 		if (serial != NULL) {
11630a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
11730a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
11830a5e8faSwyllys 			    sizeof (KMF_BIGINT));
11930a5e8faSwyllys 			numattr++;
12030a5e8faSwyllys 		}
12130a5e8faSwyllys 
12230a5e8faSwyllys 		if (infile != NULL) {
12330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
12430a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, infile,
12530a5e8faSwyllys 			    strlen(infile));
12630a5e8faSwyllys 			numattr++;
12730a5e8faSwyllys 		}
12830a5e8faSwyllys 
12930a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
13030a5e8faSwyllys 		    &kmfcert);
13199ebb4caSwyllys 		if (rv == KMF_OK) {
13230a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
13330a5e8faSwyllys 			numattr = 0;
13499ebb4caSwyllys 
13530a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
13630a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
13730a5e8faSwyllys 			numattr++;
13830a5e8faSwyllys 
13930a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
14030a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
14130a5e8faSwyllys 			    sizeof (KMF_DATA));
14230a5e8faSwyllys 			numattr++;
14330a5e8faSwyllys 
14430a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
14530a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
14630a5e8faSwyllys 			    strlen(filename));
14730a5e8faSwyllys 			numattr++;
14830a5e8faSwyllys 
14930a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr,
15030a5e8faSwyllys 			    attrlist);
15130a5e8faSwyllys 
15230a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
15399ebb4caSwyllys 		}
15499ebb4caSwyllys 	}
15599ebb4caSwyllys 	return (rv);
1567711facfSdinak }
1577711facfSdinak 
15899ebb4caSwyllys static KMF_RETURN
pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,char * token_spec,char * dir,char * prefix,char * certlabel,char * issuer,char * subject,KMF_BIGINT * serial,KMF_CREDENTIAL * tokencred,char * filename)15999ebb4caSwyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle,
16099ebb4caSwyllys 	char *token_spec, char *dir, char *prefix,
16199ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
16299ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred,
16399ebb4caSwyllys 	char *filename)
1647711facfSdinak {
16599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
16630a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
167*6b35cb3cSRichard PALO 	KMF_CREDENTIAL p12cred = { NULL, 0 };
16830a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
16930a5e8faSwyllys 	int numattr = 0;
1707711facfSdinak 
17199ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
17299ebb4caSwyllys 	if (rv != KMF_OK)
1737711facfSdinak 		return (rv);
1747711facfSdinak 
17599ebb4caSwyllys 	if (token_spec == NULL)
17699ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
1777711facfSdinak 
17830a5e8faSwyllys 	kstype = KMF_KEYSTORE_NSS;
17930a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
18030a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
18130a5e8faSwyllys 	numattr++;
18230a5e8faSwyllys 
18330a5e8faSwyllys 	if (certlabel != NULL) {
18430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
18530a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
18630a5e8faSwyllys 		numattr++;
18730a5e8faSwyllys 	}
18830a5e8faSwyllys 
18930a5e8faSwyllys 	if (issuer != NULL) {
19030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
19130a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
19230a5e8faSwyllys 		numattr++;
19330a5e8faSwyllys 	}
19430a5e8faSwyllys 
19530a5e8faSwyllys 	if (subject != NULL) {
19630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
19730a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
19830a5e8faSwyllys 		numattr++;
19930a5e8faSwyllys 	}
2007711facfSdinak 
20130a5e8faSwyllys 	if (serial != NULL) {
20230a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
20330a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
20430a5e8faSwyllys 		numattr++;
20530a5e8faSwyllys 	}
2067711facfSdinak 
20730a5e8faSwyllys 	if (tokencred != NULL) {
20830a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
20930a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
21030a5e8faSwyllys 		numattr++;
21130a5e8faSwyllys 	}
21230a5e8faSwyllys 
21330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR,
21430a5e8faSwyllys 	    token_spec, strlen(token_spec));
21530a5e8faSwyllys 	numattr++;
21630a5e8faSwyllys 
21730a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
21830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
21930a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
22030a5e8faSwyllys 	numattr++;
22130a5e8faSwyllys 
22230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
22330a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
22430a5e8faSwyllys 	numattr++;
22530a5e8faSwyllys 
22630a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
22730a5e8faSwyllys 
22830a5e8faSwyllys 	if (p12cred.cred)
22930a5e8faSwyllys 		free(p12cred.cred);
2307711facfSdinak 
23199ebb4caSwyllys 	return (rv);
2327711facfSdinak }
2337711facfSdinak 
23499ebb4caSwyllys static KMF_RETURN
pk_export_pk12_files(KMF_HANDLE_T kmfhandle,char * certfile,char * keyfile,char * outfile)23599ebb4caSwyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle,
236448b8615Swyllys 	char *certfile, char *keyfile,
23799ebb4caSwyllys 	char *outfile)
2387711facfSdinak {
23999ebb4caSwyllys 	KMF_RETURN rv;
24030a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
241*6b35cb3cSRichard PALO 	KMF_CREDENTIAL p12cred = { NULL, 0 };
24230a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
24330a5e8faSwyllys 	int numattr = 0;
24430a5e8faSwyllys 
24530a5e8faSwyllys 	kstype = KMF_KEYSTORE_OPENSSL;
24630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
24730a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
24830a5e8faSwyllys 	numattr++;
24930a5e8faSwyllys 
25030a5e8faSwyllys 	if (certfile != NULL) {
25130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
25230a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile));
25330a5e8faSwyllys 		numattr++;
25430a5e8faSwyllys 	}
25530a5e8faSwyllys 
25630a5e8faSwyllys 	if (keyfile != NULL) {
25730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
25830a5e8faSwyllys 		    KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile));
25930a5e8faSwyllys 		numattr++;
26030a5e8faSwyllys 	}
2617711facfSdinak 
26230a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
26330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
26430a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
26530a5e8faSwyllys 	numattr++;
2667711facfSdinak 
26730a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
26830a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile));
26930a5e8faSwyllys 	numattr++;
2707711facfSdinak 
27130a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
2727711facfSdinak 
27330a5e8faSwyllys 	if (p12cred.cred)
27430a5e8faSwyllys 		free(p12cred.cred);
2757711facfSdinak 
27699ebb4caSwyllys 	return (rv);
2777711facfSdinak }
2787711facfSdinak 
27999ebb4caSwyllys static KMF_RETURN
pk_export_nss_objects(KMF_HANDLE_T kmfhandle,char * token_spec,int oclass,char * certlabel,char * issuer,char * subject,KMF_BIGINT * serial,KMF_ENCODE_FORMAT kfmt,char * dir,char * prefix,char * filename)28099ebb4caSwyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
28199ebb4caSwyllys 	int oclass, char *certlabel, char *issuer, char *subject,
28299ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir,
28399ebb4caSwyllys 	char *prefix, char *filename)
2847711facfSdinak {
28599ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
28699ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
28730a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS;
28830a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
28930a5e8faSwyllys 	int numattr = 0;
2907711facfSdinak 
29199ebb4caSwyllys 	rv = configure_nss(kmfhandle, dir, prefix);
29299ebb4caSwyllys 	if (rv != KMF_OK)
2937711facfSdinak 		return (rv);
2947711facfSdinak 
29599ebb4caSwyllys 	/* If searching for public objects or certificates, find certs now */
29699ebb4caSwyllys 	if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) {
29730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
29830a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype,
29930a5e8faSwyllys 		    sizeof (kstype));
30030a5e8faSwyllys 		numattr++;
30130a5e8faSwyllys 
30230a5e8faSwyllys 		if (certlabel != NULL) {
30330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
30430a5e8faSwyllys 			    KMF_CERT_LABEL_ATTR, certlabel,
30530a5e8faSwyllys 			    strlen(certlabel));
30630a5e8faSwyllys 			numattr++;
30730a5e8faSwyllys 		}
30899ebb4caSwyllys 
30930a5e8faSwyllys 		if (issuer != NULL) {
31030a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
31130a5e8faSwyllys 			    KMF_ISSUER_NAME_ATTR, issuer,
31230a5e8faSwyllys 			    strlen(issuer));
31330a5e8faSwyllys 			numattr++;
31430a5e8faSwyllys 		}
31599ebb4caSwyllys 
31630a5e8faSwyllys 		if (subject != NULL) {
31730a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
31830a5e8faSwyllys 			    KMF_SUBJECT_NAME_ATTR, subject,
31930a5e8faSwyllys 			    strlen(subject));
32030a5e8faSwyllys 			numattr++;
32130a5e8faSwyllys 		}
32230a5e8faSwyllys 
32330a5e8faSwyllys 		if (serial != NULL) {
32430a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
32530a5e8faSwyllys 			    KMF_BIGINT_ATTR, serial,
32630a5e8faSwyllys 			    sizeof (KMF_BIGINT));
32730a5e8faSwyllys 			numattr++;
32830a5e8faSwyllys 		}
32930a5e8faSwyllys 
33030a5e8faSwyllys 		if (token_spec != NULL) {
33130a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
33230a5e8faSwyllys 			    KMF_TOKEN_LABEL_ATTR, token_spec,
33330a5e8faSwyllys 			    strlen(token_spec));
33430a5e8faSwyllys 			numattr++;
33530a5e8faSwyllys 		}
33630a5e8faSwyllys 
33730a5e8faSwyllys 		rv = pk_find_export_cert(kmfhandle, attrlist, numattr,
33830a5e8faSwyllys 		    &kmfcert);
33999ebb4caSwyllys 		if (rv == KMF_OK) {
34030a5e8faSwyllys 			kstype = KMF_KEYSTORE_OPENSSL;
34130a5e8faSwyllys 			numattr = 0;
34230a5e8faSwyllys 
34330a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
34430a5e8faSwyllys 			    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
34530a5e8faSwyllys 			numattr++;
34699ebb4caSwyllys 
34730a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
34830a5e8faSwyllys 			    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
34930a5e8faSwyllys 			    sizeof (KMF_DATA));
35030a5e8faSwyllys 			numattr++;
35199ebb4caSwyllys 
35230a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
35330a5e8faSwyllys 			    KMF_CERT_FILENAME_ATTR, filename,
35430a5e8faSwyllys 			    strlen(filename));
35530a5e8faSwyllys 			numattr++;
35630a5e8faSwyllys 
35730a5e8faSwyllys 			kmf_set_attr_at_index(attrlist, numattr,
35830a5e8faSwyllys 			    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
35930a5e8faSwyllys 			numattr++;
36030a5e8faSwyllys 
36130a5e8faSwyllys 			rv = kmf_store_cert(kmfhandle, numattr, attrlist);
36230a5e8faSwyllys 
36330a5e8faSwyllys 			kmf_free_kmf_cert(kmfhandle, &kmfcert);
3647711facfSdinak 		}
3657711facfSdinak 	}
36699ebb4caSwyllys 	return (rv);
36799ebb4caSwyllys }
3687711facfSdinak 
36999ebb4caSwyllys static KMF_RETURN
pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle,char * token_spec,char * certlabel,char * issuer,char * subject,KMF_BIGINT * serial,KMF_CREDENTIAL * tokencred,char * filename)37099ebb4caSwyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec,
37199ebb4caSwyllys 	char *certlabel, char *issuer, char *subject,
37299ebb4caSwyllys 	KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename)
37399ebb4caSwyllys {
37499ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
37530a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype;
376*6b35cb3cSRichard PALO 	KMF_CREDENTIAL p12cred = { NULL, 0 };
37730a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
37830a5e8faSwyllys 	int numattr = 0;
3797711facfSdinak 
38099ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
38199ebb4caSwyllys 	if (rv != KMF_OK) {
38299ebb4caSwyllys 		return (rv);
3837711facfSdinak 	}
3847711facfSdinak 
38530a5e8faSwyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
38630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
38730a5e8faSwyllys 	    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
38830a5e8faSwyllys 	numattr++;
38930a5e8faSwyllys 
39030a5e8faSwyllys 	if (certlabel != NULL) {
39130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
39230a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel));
39330a5e8faSwyllys 		numattr++;
39430a5e8faSwyllys 	}
39530a5e8faSwyllys 
39630a5e8faSwyllys 	if (issuer != NULL) {
39730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
39830a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer));
39930a5e8faSwyllys 		numattr++;
40030a5e8faSwyllys 	}
40130a5e8faSwyllys 
40230a5e8faSwyllys 	if (subject != NULL) {
40330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
40430a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject, strlen(subject));
40530a5e8faSwyllys 		numattr++;
40630a5e8faSwyllys 	}
40730a5e8faSwyllys 
40830a5e8faSwyllys 	if (serial != NULL) {
40930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
41030a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT));
41130a5e8faSwyllys 		numattr++;
41230a5e8faSwyllys 	}
41330a5e8faSwyllys 
41430a5e8faSwyllys 	if (tokencred != NULL) {
41530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
41630a5e8faSwyllys 		    KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL));
41730a5e8faSwyllys 		numattr++;
41830a5e8faSwyllys 	}
41930a5e8faSwyllys 
42030a5e8faSwyllys 	(void) get_pk12_password(&p12cred);
42130a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
42230a5e8faSwyllys 	    KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL));
42330a5e8faSwyllys 	numattr++;
42430a5e8faSwyllys 
42530a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr,
42630a5e8faSwyllys 	    KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename));
42730a5e8faSwyllys 	numattr++;
42830a5e8faSwyllys 
42930a5e8faSwyllys 	rv = kmf_export_pk12(kmfhandle, numattr, attrlist);
43030a5e8faSwyllys 
43130a5e8faSwyllys 	if (p12cred.cred)
43230a5e8faSwyllys 		free(p12cred.cred);
43330a5e8faSwyllys 
43430a5e8faSwyllys 	return (rv);
43530a5e8faSwyllys }
43630a5e8faSwyllys 
43730a5e8faSwyllys static KMF_RETURN
pk_export_pk11_keys(KMF_HANDLE_T kmfhandle,char * token,KMF_CREDENTIAL * cred,KMF_ENCODE_FORMAT format,char * label,char * filename,int oclass)43830a5e8faSwyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token,
43930a5e8faSwyllys 	KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format,
44073cc0e02Swyllys 	char *label, char *filename, int oclass)
44130a5e8faSwyllys {
44230a5e8faSwyllys 	KMF_RETURN rv = KMF_OK;
44330a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
44473cc0e02Swyllys 	KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE;
44530a5e8faSwyllys 	int numattr = 0;
44630a5e8faSwyllys 	uint32_t numkeys = 1;
44730a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
44830a5e8faSwyllys 	KMF_KEY_HANDLE key;
44930a5e8faSwyllys 	boolean_t is_token = B_TRUE;
45030a5e8faSwyllys 
45130a5e8faSwyllys 	if (EMPTYSTRING(label)) {
45230a5e8faSwyllys 		cryptoerror(LOG_STDERR, gettext("A label "
45330a5e8faSwyllys 		    "must be specified to export a key."));
45430a5e8faSwyllys 		return (KMF_ERR_BAD_PARAMETER);
45530a5e8faSwyllys 	}
45630a5e8faSwyllys 
45730a5e8faSwyllys 	rv = select_token(kmfhandle, token, TRUE);
45830a5e8faSwyllys 	if (rv != KMF_OK) {
45930a5e8faSwyllys 		return (rv);
46030a5e8faSwyllys 	}
46130a5e8faSwyllys 
46230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
46330a5e8faSwyllys 	    &kstype, sizeof (kstype));
46430a5e8faSwyllys 	numattr++;
46530a5e8faSwyllys 
46630a5e8faSwyllys 	if (cred != NULL) {
46730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
46830a5e8faSwyllys 		    cred, sizeof (KMF_CREDENTIAL));
46930a5e8faSwyllys 		numattr++;
47030a5e8faSwyllys 	}
47130a5e8faSwyllys 
47230a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
47330a5e8faSwyllys 	    label, strlen(label));
47430a5e8faSwyllys 	numattr++;
47530a5e8faSwyllys 
47630a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
47730a5e8faSwyllys 	    &numkeys, sizeof (numkeys));
47830a5e8faSwyllys 	numattr++;
4797711facfSdinak 
48030a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
48130a5e8faSwyllys 	    &key, sizeof (key));
48230a5e8faSwyllys 	numattr++;
4837711facfSdinak 
48430a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
48530a5e8faSwyllys 	    &is_token, sizeof (is_token));
48630a5e8faSwyllys 	numattr++;
4877711facfSdinak 
48830a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
48930a5e8faSwyllys 	    &format, sizeof (format));
49030a5e8faSwyllys 	numattr++;
49130a5e8faSwyllys 
49273cc0e02Swyllys 	/* Check to see if we are exporting private or public only */
49373cc0e02Swyllys 	if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ)
49473cc0e02Swyllys 		kclass = KMF_ASYM_PRI;
49573cc0e02Swyllys 	else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ)
49673cc0e02Swyllys 		kclass = KMF_ASYM_PUB;
49773cc0e02Swyllys 	else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ)
49873cc0e02Swyllys 		kclass = KMF_SYMMETRIC;
49973cc0e02Swyllys 	else /* only 1 key at a time can be exported here, so default to pri */
50073cc0e02Swyllys 		kclass = KMF_ASYM_PRI;
50173cc0e02Swyllys 
50273cc0e02Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
50373cc0e02Swyllys 	    &kclass, sizeof (kclass));
50473cc0e02Swyllys 	numattr++;
50573cc0e02Swyllys 
50630a5e8faSwyllys 	rv = kmf_find_key(kmfhandle, numattr, attrlist);
50771a79fe7Swyllys 	/*
50871a79fe7Swyllys 	 * If nothing found but caller wanted ALL keys, try symmetric
50971a79fe7Swyllys 	 * this time.
51071a79fe7Swyllys 	 */
51171a79fe7Swyllys 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
51271a79fe7Swyllys 		kclass = KMF_SYMMETRIC;
51371a79fe7Swyllys 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
51471a79fe7Swyllys 	}
51571a79fe7Swyllys 	/*
51671a79fe7Swyllys 	 * If nothing found but caller wanted ALL keys, try asymmetric
51771a79fe7Swyllys 	 * public this time.
51871a79fe7Swyllys 	 */
51971a79fe7Swyllys 	if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) {
52071a79fe7Swyllys 		kclass = KMF_ASYM_PUB;
52171a79fe7Swyllys 		rv = kmf_find_key(kmfhandle, numattr, attrlist);
52271a79fe7Swyllys 	}
52330a5e8faSwyllys 	if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) {
52430a5e8faSwyllys 		KMF_RAW_SYM_KEY rkey;
52530a5e8faSwyllys 
52630a5e8faSwyllys 		(void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY));
52730a5e8faSwyllys 		rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey);
52830a5e8faSwyllys 		if (rv == KMF_OK) {
52930a5e8faSwyllys 			int fd, n, total = 0;
53030a5e8faSwyllys 
53130a5e8faSwyllys 			fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600);
53230a5e8faSwyllys 			if (fd == -1) {
53330a5e8faSwyllys 				rv = KMF_ERR_OPEN_FILE;
53430a5e8faSwyllys 				goto done;
53530a5e8faSwyllys 			}
53630a5e8faSwyllys 			do {
53730a5e8faSwyllys 				n = write(fd, rkey.keydata.val + total,
53830a5e8faSwyllys 				    rkey.keydata.len - total);
53930a5e8faSwyllys 				if (n < 0) {
54030a5e8faSwyllys 					if (errno == EINTR)
54130a5e8faSwyllys 						continue;
54246d33f7eSwyllys 					(void) close(fd);
54330a5e8faSwyllys 					rv = KMF_ERR_WRITE_FILE;
54430a5e8faSwyllys 					goto done;
54530a5e8faSwyllys 				}
54630a5e8faSwyllys 				total += n;
54730a5e8faSwyllys 
54830a5e8faSwyllys 			} while (total < rkey.keydata.len);
54946d33f7eSwyllys 			(void) close(fd);
55030a5e8faSwyllys 		}
55130a5e8faSwyllys done:
55230a5e8faSwyllys 		kmf_free_bigint(&rkey.keydata);
55330a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
55430a5e8faSwyllys 	} else if (rv == KMF_OK) {
55530a5e8faSwyllys 		KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL;
55646d33f7eSwyllys 		(void) printf(gettext("Found %d asymmetric keys\n"), numkeys);
55730a5e8faSwyllys 
55830a5e8faSwyllys 		numattr = 0;
55930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
56030a5e8faSwyllys 		    &sslks, sizeof (sslks));
56130a5e8faSwyllys 		numattr++;
56230a5e8faSwyllys 
56330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR,
56430a5e8faSwyllys 		    key.keyp, sizeof (KMF_RAW_KEY_DATA));
56530a5e8faSwyllys 		numattr++;
56630a5e8faSwyllys 
56730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
56830a5e8faSwyllys 		    &format, sizeof (format));
56930a5e8faSwyllys 		numattr++;
57030a5e8faSwyllys 
57130a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR,
57230a5e8faSwyllys 		    filename, strlen(filename));
57330a5e8faSwyllys 		numattr++;
57430a5e8faSwyllys 
57573cc0e02Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
57673cc0e02Swyllys 		    &key.keyclass, sizeof (KMF_KEY_CLASS));
57773cc0e02Swyllys 		numattr++;
57873cc0e02Swyllys 
57930a5e8faSwyllys 		rv = kmf_store_key(kmfhandle, numattr, attrlist);
58030a5e8faSwyllys 		kmf_free_kmf_key(kmfhandle, &key);
58130a5e8faSwyllys 	}
5827711facfSdinak 
58399ebb4caSwyllys 	return (rv);
5847711facfSdinak }
5857711facfSdinak 
58699ebb4caSwyllys static KMF_RETURN
pk_export_pk11_objects(KMF_HANDLE_T kmfhandle,char * token_spec,KMF_CREDENTIAL * cred,char * certlabel,char * issuer,char * subject,KMF_BIGINT * serial,KMF_ENCODE_FORMAT kfmt,char * filename)58799ebb4caSwyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec,
588592106a2SWyllys Ingersoll 	KMF_CREDENTIAL *cred, char *certlabel, char *issuer, char *subject,
58999ebb4caSwyllys 	KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt,
59099ebb4caSwyllys 	char *filename)
5917711facfSdinak {
59299ebb4caSwyllys 	KMF_RETURN rv = KMF_OK;
59399ebb4caSwyllys 	KMF_X509_DER_CERT kmfcert;
59430a5e8faSwyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN;
59530a5e8faSwyllys 	int numattr = 0;
59630a5e8faSwyllys 	KMF_ATTRIBUTE attrlist[16];
5977711facfSdinak 
59899ebb4caSwyllys 	rv = select_token(kmfhandle, token_spec, TRUE);
5997711facfSdinak 
600592106a2SWyllys Ingersoll 	if (rv != KMF_OK)
6017711facfSdinak 		return (rv);
6027711facfSdinak 
60330a5e8faSwyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
60430a5e8faSwyllys 	    &kstype, sizeof (kstype));
60530a5e8faSwyllys 	numattr++;
6067711facfSdinak 
607592106a2SWyllys Ingersoll 	if (cred != NULL) {
608592106a2SWyllys Ingersoll 		kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
609592106a2SWyllys Ingersoll 		    cred, sizeof (KMF_CREDENTIAL));
610592106a2SWyllys Ingersoll 		numattr++;
611592106a2SWyllys Ingersoll 	}
61230a5e8faSwyllys 	if (certlabel != NULL) {
61330a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
61430a5e8faSwyllys 		    KMF_CERT_LABEL_ATTR, certlabel,
61530a5e8faSwyllys 		    strlen(certlabel));
61630a5e8faSwyllys 		numattr++;
61730a5e8faSwyllys 	}
61830a5e8faSwyllys 
61930a5e8faSwyllys 	if (issuer != NULL) {
62030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
62130a5e8faSwyllys 		    KMF_ISSUER_NAME_ATTR, issuer,
62230a5e8faSwyllys 		    strlen(issuer));
62330a5e8faSwyllys 		numattr++;
62430a5e8faSwyllys 	}
62530a5e8faSwyllys 
62630a5e8faSwyllys 	if (subject != NULL) {
62730a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
62830a5e8faSwyllys 		    KMF_SUBJECT_NAME_ATTR, subject,
62930a5e8faSwyllys 		    strlen(subject));
63030a5e8faSwyllys 		numattr++;
63130a5e8faSwyllys 	}
63230a5e8faSwyllys 
63330a5e8faSwyllys 	if (serial != NULL) {
63430a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
63530a5e8faSwyllys 		    KMF_BIGINT_ATTR, serial,
63630a5e8faSwyllys 		    sizeof (KMF_BIGINT));
63730a5e8faSwyllys 		numattr++;
63830a5e8faSwyllys 	}
63930a5e8faSwyllys 
64030a5e8faSwyllys 	rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert);
6417711facfSdinak 
64299ebb4caSwyllys 	if (rv == KMF_OK) {
64330a5e8faSwyllys 		kstype = KMF_KEYSTORE_OPENSSL;
64430a5e8faSwyllys 		numattr = 0;
64530a5e8faSwyllys 
64630a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
64730a5e8faSwyllys 		    KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype));
64830a5e8faSwyllys 		numattr++;
64930a5e8faSwyllys 
65030a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
65130a5e8faSwyllys 		    KMF_CERT_DATA_ATTR, &kmfcert.certificate,
65230a5e8faSwyllys 		    sizeof (KMF_DATA));
65330a5e8faSwyllys 		numattr++;
65430a5e8faSwyllys 
65530a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
65630a5e8faSwyllys 		    KMF_CERT_FILENAME_ATTR, filename, strlen(filename));
65730a5e8faSwyllys 		numattr++;
65830a5e8faSwyllys 
65930a5e8faSwyllys 		kmf_set_attr_at_index(attrlist, numattr,
66030a5e8faSwyllys 		    KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt));
66130a5e8faSwyllys 		numattr++;
6627711facfSdinak 
66330a5e8faSwyllys 		rv = kmf_store_cert(kmfhandle, numattr, attrlist);
6647711facfSdinak 
66530a5e8faSwyllys 		kmf_free_kmf_cert(kmfhandle, &kmfcert);
6667711facfSdinak 	}
66799ebb4caSwyllys 	return (rv);
6687711facfSdinak }
6697711facfSdinak 
6707711facfSdinak /*
67199ebb4caSwyllys  * Export objects from one keystore to a file.
6727711facfSdinak  */
6737711facfSdinak int
pk_export(int argc,char * argv[])6747711facfSdinak pk_export(int argc, char *argv[])
6757711facfSdinak {
67649e21299Sdinak 	int		opt;
67749e21299Sdinak 	extern int	optind_av;
67849e21299Sdinak 	extern char	*optarg_av;
67949e21299Sdinak 	char		*token_spec = NULL;
6807711facfSdinak 	char		*filename = NULL;
68199ebb4caSwyllys 	char		*dir = NULL;
68299ebb4caSwyllys 	char		*prefix = NULL;
68399ebb4caSwyllys 	char		*certlabel = NULL;
68499ebb4caSwyllys 	char		*subject = NULL;
68599ebb4caSwyllys 	char		*issuer = NULL;
68699ebb4caSwyllys 	char		*infile = NULL;
68799ebb4caSwyllys 	char		*keyfile = NULL;
68899ebb4caSwyllys 	char		*certfile = NULL;
68999ebb4caSwyllys 	char		*serstr = NULL;
69099ebb4caSwyllys 	KMF_KEYSTORE_TYPE	kstype = 0;
69199ebb4caSwyllys 	KMF_ENCODE_FORMAT	kfmt = KMF_FORMAT_PKCS12;
69299ebb4caSwyllys 	KMF_RETURN		rv = KMF_OK;
69399ebb4caSwyllys 	int		oclass = PK_CERT_OBJ;
69499ebb4caSwyllys 	KMF_BIGINT	serial = { NULL, 0 };
69599ebb4caSwyllys 	KMF_HANDLE_T	kmfhandle = NULL;
696*6b35cb3cSRichard PALO 	KMF_CREDENTIAL	tokencred = { NULL, 0 };
6977711facfSdinak 
69849e21299Sdinak 	/* Parse command line options.  Do NOT i18n/l10n. */
69999ebb4caSwyllys 	while ((opt = getopt_av(argc, argv,
70030a5e8faSwyllys 	    "k:(keystore)y:(objtype)T:(token)"
70130a5e8faSwyllys 	    "d:(dir)p:(prefix)"
70230a5e8faSwyllys 	    "l:(label)n:(nickname)s:(subject)"
70330a5e8faSwyllys 	    "i:(issuer)S:(serial)"
70430a5e8faSwyllys 	    "K:(keyfile)c:(certfile)"
70530a5e8faSwyllys 	    "F:(outformat)"
70630a5e8faSwyllys 	    "I:(infile)o:(outfile)")) != EOF) {
70799ebb4caSwyllys 		if (EMPTYSTRING(optarg_av))
70899ebb4caSwyllys 			return (PK_ERR_USAGE);
70949e21299Sdinak 		switch (opt) {
71099ebb4caSwyllys 		case 'k':
71199ebb4caSwyllys 			kstype = KS2Int(optarg_av);
71299ebb4caSwyllys 			if (kstype == 0)
71399ebb4caSwyllys 				return (PK_ERR_USAGE);
71499ebb4caSwyllys 			break;
71599ebb4caSwyllys 		case 'y':
71699ebb4caSwyllys 			oclass = OT2Int(optarg_av);
71799ebb4caSwyllys 			if (oclass == -1)
71899ebb4caSwyllys 				return (PK_ERR_USAGE);
71999ebb4caSwyllys 			break;
72049e21299Sdinak 		case 'T':	/* token specifier */
72149e21299Sdinak 			if (token_spec)
72249e21299Sdinak 				return (PK_ERR_USAGE);
72349e21299Sdinak 			token_spec = optarg_av;
72449e21299Sdinak 			break;
72599ebb4caSwyllys 		case 'd':
72699ebb4caSwyllys 			if (dir)
72799ebb4caSwyllys 				return (PK_ERR_USAGE);
72899ebb4caSwyllys 			dir = optarg_av;
72999ebb4caSwyllys 			break;
73099ebb4caSwyllys 		case 'p':
73199ebb4caSwyllys 			if (prefix)
73299ebb4caSwyllys 				return (PK_ERR_USAGE);
73399ebb4caSwyllys 			prefix = optarg_av;
73499ebb4caSwyllys 			break;
73599ebb4caSwyllys 		case 'n':
73699ebb4caSwyllys 		case 'l':
73799ebb4caSwyllys 			if (certlabel)
73899ebb4caSwyllys 				return (PK_ERR_USAGE);
73999ebb4caSwyllys 			certlabel = optarg_av;
74099ebb4caSwyllys 			break;
74199ebb4caSwyllys 		case 's':
74299ebb4caSwyllys 			if (subject)
74399ebb4caSwyllys 				return (PK_ERR_USAGE);
74499ebb4caSwyllys 			subject = optarg_av;
74599ebb4caSwyllys 			break;
74699ebb4caSwyllys 		case 'i':
74799ebb4caSwyllys 			if (issuer)
74899ebb4caSwyllys 				return (PK_ERR_USAGE);
74999ebb4caSwyllys 			issuer = optarg_av;
75099ebb4caSwyllys 			break;
75199ebb4caSwyllys 		case 'S':
75299ebb4caSwyllys 			serstr = optarg_av;
75399ebb4caSwyllys 			break;
75499ebb4caSwyllys 		case 'F':
75599ebb4caSwyllys 			kfmt = Str2Format(optarg_av);
75699ebb4caSwyllys 			if (kfmt == KMF_FORMAT_UNDEF)
75799ebb4caSwyllys 				return (PK_ERR_USAGE);
75899ebb4caSwyllys 			break;
75999ebb4caSwyllys 		case 'I':	/* output file name */
76099ebb4caSwyllys 			if (infile)
76199ebb4caSwyllys 				return (PK_ERR_USAGE);
76299ebb4caSwyllys 			infile = optarg_av;
76399ebb4caSwyllys 			break;
76449e21299Sdinak 		case 'o':	/* output file name */
76549e21299Sdinak 			if (filename)
76649e21299Sdinak 				return (PK_ERR_USAGE);
76749e21299Sdinak 			filename = optarg_av;
76849e21299Sdinak 			break;
76999ebb4caSwyllys 		case 'c':	/* input cert file name */
77099ebb4caSwyllys 			if (certfile)
77199ebb4caSwyllys 				return (PK_ERR_USAGE);
77299ebb4caSwyllys 			certfile = optarg_av;
77399ebb4caSwyllys 			break;
77499ebb4caSwyllys 		case 'K':	/* input key file name */
77599ebb4caSwyllys 			if (keyfile)
77699ebb4caSwyllys 				return (PK_ERR_USAGE);
77799ebb4caSwyllys 			keyfile = optarg_av;
77899ebb4caSwyllys 			break;
77949e21299Sdinak 		default:
78049e21299Sdinak 			return (PK_ERR_USAGE);
78149e21299Sdinak 		}
78249e21299Sdinak 	}
7837711facfSdinak 
78499ebb4caSwyllys 	/* Assume keystore = PKCS#11 if not specified */
78599ebb4caSwyllys 	if (kstype == 0)
78699ebb4caSwyllys 		kstype = KMF_KEYSTORE_PK11TOKEN;
78749e21299Sdinak 
78849e21299Sdinak 	/* Filename arg is required. */
78999ebb4caSwyllys 	if (EMPTYSTRING(filename)) {
79099ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("You must specify "
79130a5e8faSwyllys 		    "an 'outfile' parameter when exporting.\n"));
7927711facfSdinak 		return (PK_ERR_USAGE);
79399ebb4caSwyllys 	}
7947711facfSdinak 
79549e21299Sdinak 	/* No additional args allowed. */
79649e21299Sdinak 	argc -= optind_av;
79749e21299Sdinak 	argv += optind_av;
79849e21299Sdinak 	if (argc)
79949e21299Sdinak 		return (PK_ERR_USAGE);
80099ebb4caSwyllys 
801577f4726Swyllys 	DIR_OPTION_CHECK(kstype, dir);
802577f4726Swyllys 
80399ebb4caSwyllys 	/* if PUBLIC or PRIVATE obj was given, the old syntax was used. */
80499ebb4caSwyllys 	if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) &&
80530a5e8faSwyllys 	    kstype != KMF_KEYSTORE_PK11TOKEN) {
80699ebb4caSwyllys 
80799ebb4caSwyllys 		(void) fprintf(stderr, gettext("The objtype parameter "
80830a5e8faSwyllys 		    "is only relevant if keystore=pkcs11\n"));
80999ebb4caSwyllys 		return (PK_ERR_USAGE);
81099ebb4caSwyllys 	}
81199ebb4caSwyllys 
81299ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec))
81399ebb4caSwyllys 		token_spec = PK_DEFAULT_PK11TOKEN;
81499ebb4caSwyllys 	else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec))
81599ebb4caSwyllys 		token_spec = DEFAULT_NSS_TOKEN;
81699ebb4caSwyllys 
81799ebb4caSwyllys 	if (kstype == KMF_KEYSTORE_OPENSSL) {
81899ebb4caSwyllys 		if (kfmt != KMF_FORMAT_PKCS12) {
81999ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("PKCS12 "
82030a5e8faSwyllys 			    "is the only export format "
82130a5e8faSwyllys 			    "supported for the 'file' "
82230a5e8faSwyllys 			    "keystore.\n"));
82399ebb4caSwyllys 			return (PK_ERR_USAGE);
82499ebb4caSwyllys 		}
82599ebb4caSwyllys 		if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) {
82699ebb4caSwyllys 			cryptoerror(LOG_STDERR, gettext("A cert file"
82730a5e8faSwyllys 			    "and a key file must be specified "
82830a5e8faSwyllys 			    "when exporting to PKCS12 from the "
82930a5e8faSwyllys 			    "'file' keystore.\n"));
83099ebb4caSwyllys 			return (PK_ERR_USAGE);
83199ebb4caSwyllys 		}
83299ebb4caSwyllys 	}
8337711facfSdinak 
8342c9a247fSWyllys Ingersoll 	/* Check if the file exists */
8352c9a247fSWyllys Ingersoll 	if (verify_file(filename) != KMF_OK) {
83699ebb4caSwyllys 		cryptoerror(LOG_STDERR,
83730a5e8faSwyllys 		    gettext("Warning: file \"%s\" exists, "
83830a5e8faSwyllys 		    "will be overwritten."), filename);
8397711facfSdinak 		if (yesno(gettext("Continue with export? "),
8407711facfSdinak 		    gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
8417711facfSdinak 			return (0);
84273cc0e02Swyllys 		} else {
84373cc0e02Swyllys 			/* remove the file */
84473cc0e02Swyllys 			(void) unlink(filename);
8457711facfSdinak 		}
8467711facfSdinak 	}
8477711facfSdinak 
84899ebb4caSwyllys 	if (serstr != NULL) {
84999ebb4caSwyllys 		uchar_t *bytes = NULL;
85099ebb4caSwyllys 		size_t bytelen;
8517711facfSdinak 
85230a5e8faSwyllys 		rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen);
85399ebb4caSwyllys 		if (rv != KMF_OK || bytes == NULL) {
85499ebb4caSwyllys 			(void) fprintf(stderr, gettext("serial number "
85530a5e8faSwyllys 			    "must be specified as a hex number "
85630a5e8faSwyllys 			    "(ex: 0x0102030405ffeeddee)\n"));
85799ebb4caSwyllys 			return (PK_ERR_USAGE);
85899ebb4caSwyllys 		}
85999ebb4caSwyllys 		serial.val = bytes;
86099ebb4caSwyllys 		serial.len = bytelen;
8617711facfSdinak 	}
8627711facfSdinak 
863ab8b4e5cSWyllys Ingersoll 	/*
864ab8b4e5cSWyllys Ingersoll 	 * We need a password in the following situations:
865ab8b4e5cSWyllys Ingersoll 	 * 1.  When accessing PKCS11 token
866ab8b4e5cSWyllys Ingersoll 	 * 2.  If NSS keystore, when making a PKCS12 file or when
867ab8b4e5cSWyllys Ingersoll 	 * accessing any private object or key.
868ab8b4e5cSWyllys Ingersoll 	 */
869592106a2SWyllys Ingersoll 	if (kstype == KMF_KEYSTORE_PK11TOKEN ||
870592106a2SWyllys Ingersoll 	    ((kstype == KMF_KEYSTORE_NSS) &&
871ab8b4e5cSWyllys Ingersoll 	    ((oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ)) ||
872ab8b4e5cSWyllys Ingersoll 	    (kfmt == KMF_FORMAT_PKCS12)))) {
87399ebb4caSwyllys 			(void) get_token_password(kstype, token_spec,
87430a5e8faSwyllys 			    &tokencred);
8757711facfSdinak 	}
8767711facfSdinak 
87730a5e8faSwyllys 	if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) {
87899ebb4caSwyllys 		cryptoerror(LOG_STDERR, gettext("Error initializing "
87930a5e8faSwyllys 		    "KMF: 0x%02x\n"), rv);
88099ebb4caSwyllys 		return (rv);
8817711facfSdinak 	}
8827711facfSdinak 
88399ebb4caSwyllys 	switch (kstype) {
88499ebb4caSwyllys 		case KMF_KEYSTORE_PK11TOKEN:
88599ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
88630a5e8faSwyllys 				rv = pk_export_pk12_pk11(kmfhandle,
88730a5e8faSwyllys 				    token_spec, certlabel,
88830a5e8faSwyllys 				    issuer, subject,
88930a5e8faSwyllys 				    &serial, &tokencred,
89030a5e8faSwyllys 				    filename);
89130a5e8faSwyllys 			else if ((oclass & PK_KEY_OBJ) ||
89230a5e8faSwyllys 			    kfmt == KMF_FORMAT_RAWKEY)
89330a5e8faSwyllys 				rv = pk_export_pk11_keys(kmfhandle,
89430a5e8faSwyllys 				    token_spec, &tokencred, kfmt,
89573cc0e02Swyllys 				    certlabel, filename, oclass);
89699ebb4caSwyllys 			else
89799ebb4caSwyllys 				rv = pk_export_pk11_objects(kmfhandle,
898592106a2SWyllys Ingersoll 				    token_spec, &tokencred, certlabel,
89930a5e8faSwyllys 				    issuer, subject, &serial, kfmt,
90030a5e8faSwyllys 				    filename);
90199ebb4caSwyllys 			break;
90299ebb4caSwyllys 		case KMF_KEYSTORE_NSS:
90399ebb4caSwyllys 			if (dir == NULL)
90499ebb4caSwyllys 				dir = PK_DEFAULT_DIRECTORY;
90599ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
90699ebb4caSwyllys 				rv = pk_export_pk12_nss(kmfhandle,
90730a5e8faSwyllys 				    token_spec, dir, prefix,
90830a5e8faSwyllys 				    certlabel, issuer,
90930a5e8faSwyllys 				    subject, &serial,
91030a5e8faSwyllys 				    &tokencred, filename);
91199ebb4caSwyllys 			else
91299ebb4caSwyllys 				rv = pk_export_nss_objects(kmfhandle,
91330a5e8faSwyllys 				    token_spec,
91430a5e8faSwyllys 				    oclass, certlabel, issuer, subject,
91530a5e8faSwyllys 				    &serial, kfmt, dir, prefix, filename);
91699ebb4caSwyllys 			break;
91799ebb4caSwyllys 		case KMF_KEYSTORE_OPENSSL:
91899ebb4caSwyllys 			if (kfmt == KMF_FORMAT_PKCS12)
91999ebb4caSwyllys 				rv = pk_export_pk12_files(kmfhandle,
920448b8615Swyllys 				    certfile, keyfile, filename);
92199ebb4caSwyllys 			else
92299ebb4caSwyllys 				rv = pk_export_file_objects(kmfhandle, oclass,
92330a5e8faSwyllys 				    issuer, subject, &serial,
924448b8615Swyllys 				    infile, filename);
92599ebb4caSwyllys 			break;
92699ebb4caSwyllys 		default:
92799ebb4caSwyllys 			rv = PK_ERR_USAGE;
92899ebb4caSwyllys 			break;
9297711facfSdinak 	}
9307711facfSdinak 
93199ebb4caSwyllys 	if (rv != KMF_OK) {
93299ebb4caSwyllys 		display_error(kmfhandle, rv,
93330a5e8faSwyllys 		    gettext("Error exporting objects"));
9347711facfSdinak 	}
9357711facfSdinak 
93699ebb4caSwyllys 	if (serial.val != NULL)
93799ebb4caSwyllys 		free(serial.val);
9387711facfSdinak 
93930a5e8faSwyllys 	(void) kmf_finalize(kmfhandle);
9407711facfSdinak 
94199ebb4caSwyllys 	return (rv);
9427711facfSdinak }
943