117Sdinak /* 217Sdinak * CDDL HEADER START 317Sdinak * 417Sdinak * The contents of this file are subject to the terms of the 51837Sdinak * Common Development and Distribution License (the "License"). 61837Sdinak * You may not use this file except in compliance with the License. 717Sdinak * 817Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 917Sdinak * or http://www.opensolaris.org/os/licensing. 1017Sdinak * See the License for the specific language governing permissions 1117Sdinak * and limitations under the License. 1217Sdinak * 1317Sdinak * When distributing Covered Code, include this CDDL HEADER in each 1417Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1517Sdinak * If applicable, add the following below this CDDL HEADER, with the 1617Sdinak * fields enclosed by brackets "[]" replaced with your own identifying 1717Sdinak * information: Portions Copyright [yyyy] [name of copyright owner] 1817Sdinak * 1917Sdinak * CDDL HEADER END 203089Swyllys * 213089Swyllys * 225051Swyllys * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2317Sdinak * Use is subject to license terms. 2417Sdinak */ 2517Sdinak 2617Sdinak #pragma ident "%Z%%M% %I% %E% SMI" 2717Sdinak 2817Sdinak /* 2917Sdinak * This file implements the export operation for this tool. 3017Sdinak * The basic flow of the process is to find the soft token, 3117Sdinak * log into it, find the PKCS#11 objects in the soft token 3217Sdinak * to be exported matching keys with their certificates, export 3317Sdinak * them to the PKCS#12 file encrypting them with a file password 3417Sdinak * if desired, and log out. 3517Sdinak */ 3617Sdinak 3717Sdinak #include <stdio.h> 3817Sdinak #include <stdlib.h> 3917Sdinak #include <string.h> 4017Sdinak #include <errno.h> 413089Swyllys #include <fcntl.h> 4217Sdinak #include "common.h" 433089Swyllys 443089Swyllys #include <kmfapi.h> 4517Sdinak 463089Swyllys static KMF_RETURN 475051Swyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist, 485051Swyllys int numattr, KMF_X509_DER_CERT *cert) 4917Sdinak { 503089Swyllys KMF_RETURN rv = KMF_OK; 513089Swyllys uint32_t numcerts = 0; 5217Sdinak 533089Swyllys numcerts = 0; 543089Swyllys (void) memset(cert, 0, sizeof (KMF_X509_DER_CERT)); 555051Swyllys 565051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 575051Swyllys &numcerts, sizeof (uint32_t)); 585051Swyllys numattr++; 595051Swyllys 605051Swyllys rv = kmf_find_cert(kmfhandle, numattr, attrlist); 613089Swyllys if (rv != KMF_OK) { 623089Swyllys return (rv); 6317Sdinak } 643089Swyllys if (numcerts == 0) { 653089Swyllys cryptoerror(LOG_STDERR, 665051Swyllys gettext("No matching certificates found.")); 673089Swyllys return (KMF_ERR_CERT_NOT_FOUND); 6817Sdinak 693089Swyllys } else if (numcerts == 1) { 705051Swyllys kmf_set_attr_at_index(attrlist, numattr, 715051Swyllys KMF_X509_DER_CERT_ATTR, cert, 725051Swyllys sizeof (KMF_X509_DER_CERT)); 735051Swyllys numattr++; 745051Swyllys rv = kmf_find_cert(kmfhandle, numattr, attrlist); 7517Sdinak 763089Swyllys } else if (numcerts > 1) { 773089Swyllys cryptoerror(LOG_STDERR, 785051Swyllys gettext("%d certificates found, refine the " 795051Swyllys "search parameters to eliminate ambiguity\n"), 805051Swyllys numcerts); 813089Swyllys return (KMF_ERR_BAD_PARAMETER); 823089Swyllys } 833089Swyllys return (rv); 843089Swyllys } 8517Sdinak 863089Swyllys static KMF_RETURN 873089Swyllys pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass, 883089Swyllys char *issuer, char *subject, KMF_BIGINT *serial, 893089Swyllys char *dir, char *infile, char *filename) 903089Swyllys { 913089Swyllys KMF_RETURN rv = KMF_OK; 923089Swyllys KMF_X509_DER_CERT kmfcert; 935051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 945051Swyllys int numattr = 0; 955051Swyllys KMF_ATTRIBUTE attrlist[16]; 9617Sdinak 973089Swyllys /* If searching for public objects or certificates, find certs now */ 983089Swyllys if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 995051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1005051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 1015051Swyllys sizeof (kstype)); 1025051Swyllys numattr++; 1035051Swyllys 1045051Swyllys if (issuer != NULL) { 1055051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1065051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 1075051Swyllys strlen(issuer)); 1085051Swyllys numattr++; 1095051Swyllys } 1105051Swyllys 1115051Swyllys if (subject != NULL) { 1125051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1135051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 1145051Swyllys strlen(subject)); 1155051Swyllys numattr++; 1165051Swyllys } 1175051Swyllys 1185051Swyllys if (serial != NULL) { 1195051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1205051Swyllys KMF_BIGINT_ATTR, serial, 1215051Swyllys sizeof (KMF_BIGINT)); 1225051Swyllys numattr++; 1235051Swyllys } 12417Sdinak 1255051Swyllys if (dir != NULL) { 1265051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1275051Swyllys KMF_DIRPATH_ATTR, dir, 1285051Swyllys strlen(dir)); 1295051Swyllys numattr++; 1305051Swyllys } 1315051Swyllys 1325051Swyllys if (infile != NULL) { 1335051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1345051Swyllys KMF_CERT_FILENAME_ATTR, infile, 1355051Swyllys strlen(infile)); 1365051Swyllys numattr++; 1375051Swyllys } 13817Sdinak 1395051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 1405051Swyllys &kmfcert); 1413089Swyllys if (rv == KMF_OK) { 1425051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 1435051Swyllys numattr = 0; 1445051Swyllys 1455051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1465051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1475051Swyllys numattr++; 14817Sdinak 1495051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1505051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 1515051Swyllys sizeof (KMF_DATA)); 1525051Swyllys numattr++; 1535051Swyllys 1545051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1555051Swyllys KMF_CERT_FILENAME_ATTR, filename, 1565051Swyllys strlen(filename)); 1575051Swyllys numattr++; 1585051Swyllys 1595051Swyllys rv = kmf_store_cert(kmfhandle, numattr, 1605051Swyllys attrlist); 1615051Swyllys 1625051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 16317Sdinak } 16417Sdinak } 1653089Swyllys return (rv); 1663089Swyllys } 16717Sdinak 1683089Swyllys static KMF_RETURN 1693089Swyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle, 1703089Swyllys char *token_spec, char *dir, char *prefix, 1713089Swyllys char *certlabel, char *issuer, char *subject, 1723089Swyllys KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, 1733089Swyllys char *filename) 1743089Swyllys { 1753089Swyllys KMF_RETURN rv = KMF_OK; 1765051Swyllys KMF_KEYSTORE_TYPE kstype; 1775051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 1785051Swyllys KMF_ATTRIBUTE attrlist[16]; 1795051Swyllys int numattr = 0; 18017Sdinak 1813089Swyllys rv = configure_nss(kmfhandle, dir, prefix); 1823089Swyllys if (rv != KMF_OK) 1833089Swyllys return (rv); 18417Sdinak 1853089Swyllys if (token_spec == NULL) 1863089Swyllys token_spec = DEFAULT_NSS_TOKEN; 18717Sdinak 1885051Swyllys kstype = KMF_KEYSTORE_NSS; 1895051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1905051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1915051Swyllys numattr++; 1925051Swyllys 1935051Swyllys if (certlabel != NULL) { 1945051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1955051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 1965051Swyllys numattr++; 1975051Swyllys } 1985051Swyllys 1995051Swyllys if (issuer != NULL) { 2005051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2015051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 2025051Swyllys numattr++; 2035051Swyllys } 2045051Swyllys 2055051Swyllys if (subject != NULL) { 2065051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2075051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 2085051Swyllys numattr++; 2095051Swyllys } 21017Sdinak 2115051Swyllys if (serial != NULL) { 2125051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2135051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 2145051Swyllys numattr++; 2155051Swyllys } 2165051Swyllys 2175051Swyllys if (tokencred != NULL) { 2185051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2195051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 2205051Swyllys numattr++; 2215051Swyllys } 22217Sdinak 2235051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 2245051Swyllys token_spec, strlen(token_spec)); 2255051Swyllys numattr++; 2265051Swyllys 2275051Swyllys (void) get_pk12_password(&p12cred); 2285051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2295051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 2305051Swyllys numattr++; 2315051Swyllys 2325051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2335051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 2345051Swyllys numattr++; 2355051Swyllys 2365051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 2375051Swyllys 2385051Swyllys if (p12cred.cred) 2395051Swyllys free(p12cred.cred); 24017Sdinak 2413089Swyllys return (rv); 24217Sdinak } 24317Sdinak 2443089Swyllys static KMF_RETURN 2453089Swyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle, 2463089Swyllys char *certfile, char *keyfile, char *dir, 2473089Swyllys char *outfile) 24817Sdinak { 2493089Swyllys KMF_RETURN rv; 2505051Swyllys KMF_KEYSTORE_TYPE kstype; 2515051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 2525051Swyllys KMF_ATTRIBUTE attrlist[16]; 2535051Swyllys int numattr = 0; 25417Sdinak 2555051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 2565051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2575051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 2585051Swyllys numattr++; 2595051Swyllys 2605051Swyllys if (dir != NULL) { 2615051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2625051Swyllys KMF_DIRPATH_ATTR, dir, strlen(dir)); 2635051Swyllys numattr++; 2645051Swyllys } 26517Sdinak 2665051Swyllys if (certfile != NULL) { 2675051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2685051Swyllys KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile)); 2695051Swyllys numattr++; 2705051Swyllys } 2715051Swyllys 2725051Swyllys if (keyfile != NULL) { 2735051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2745051Swyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 2755051Swyllys numattr++; 2765051Swyllys } 27717Sdinak 2785051Swyllys (void) get_pk12_password(&p12cred); 2795051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2805051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 2815051Swyllys numattr++; 28217Sdinak 2835051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2845051Swyllys KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile)); 2855051Swyllys numattr++; 28617Sdinak 2875051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 2885051Swyllys 2895051Swyllys if (p12cred.cred) 2905051Swyllys free(p12cred.cred); 29117Sdinak 2923089Swyllys return (rv); 29317Sdinak } 29417Sdinak 2953089Swyllys static KMF_RETURN 2963089Swyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 2973089Swyllys int oclass, char *certlabel, char *issuer, char *subject, 2983089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir, 2993089Swyllys char *prefix, char *filename) 30017Sdinak { 3013089Swyllys KMF_RETURN rv = KMF_OK; 3023089Swyllys KMF_X509_DER_CERT kmfcert; 3035051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 3045051Swyllys KMF_ATTRIBUTE attrlist[16]; 3055051Swyllys int numattr = 0; 3063089Swyllys 3073089Swyllys rv = configure_nss(kmfhandle, dir, prefix); 3083089Swyllys if (rv != KMF_OK) 3093089Swyllys return (rv); 3103089Swyllys 3113089Swyllys /* If searching for public objects or certificates, find certs now */ 3123089Swyllys if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 3135051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3145051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 3155051Swyllys sizeof (kstype)); 3165051Swyllys numattr++; 3175051Swyllys 3185051Swyllys if (certlabel != NULL) { 3195051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3205051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 3215051Swyllys strlen(certlabel)); 3225051Swyllys numattr++; 3235051Swyllys } 32417Sdinak 3255051Swyllys if (issuer != NULL) { 3265051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3275051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 3285051Swyllys strlen(issuer)); 3295051Swyllys numattr++; 3305051Swyllys } 3315051Swyllys 3325051Swyllys if (subject != NULL) { 3335051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3345051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 3355051Swyllys strlen(subject)); 3365051Swyllys numattr++; 3375051Swyllys } 3385051Swyllys 3395051Swyllys if (serial != NULL) { 3405051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3415051Swyllys KMF_BIGINT_ATTR, serial, 3425051Swyllys sizeof (KMF_BIGINT)); 3435051Swyllys numattr++; 3445051Swyllys } 34517Sdinak 3465051Swyllys if (token_spec != NULL) { 3475051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3485051Swyllys KMF_TOKEN_LABEL_ATTR, token_spec, 3495051Swyllys strlen(token_spec)); 3505051Swyllys numattr++; 3515051Swyllys } 3525051Swyllys 3535051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 3545051Swyllys &kmfcert); 3553089Swyllys if (rv == KMF_OK) { 3565051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 3575051Swyllys numattr = 0; 3585051Swyllys 3595051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3605051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 3615051Swyllys numattr++; 3625051Swyllys 3635051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3645051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 3655051Swyllys sizeof (KMF_DATA)); 3665051Swyllys numattr++; 36717Sdinak 3685051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3695051Swyllys KMF_CERT_FILENAME_ATTR, filename, 3705051Swyllys strlen(filename)); 3715051Swyllys numattr++; 3723089Swyllys 3735051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3745051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 3755051Swyllys numattr++; 3765051Swyllys 3775051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 3785051Swyllys 3795051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 3803089Swyllys } 3813089Swyllys } 3823089Swyllys return (rv); 38317Sdinak } 38417Sdinak 3853089Swyllys static KMF_RETURN 3863089Swyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec, 3873089Swyllys char *certlabel, char *issuer, char *subject, 3883089Swyllys KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename) 38917Sdinak { 3903089Swyllys KMF_RETURN rv = KMF_OK; 3915051Swyllys KMF_KEYSTORE_TYPE kstype; 3925051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 3935051Swyllys KMF_ATTRIBUTE attrlist[16]; 3945051Swyllys int numattr = 0; 39517Sdinak 3963089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 3973089Swyllys if (rv != KMF_OK) { 39817Sdinak return (rv); 39917Sdinak } 40017Sdinak 4015051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 4025051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4035051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 4045051Swyllys numattr++; 4055051Swyllys 4065051Swyllys if (certlabel != NULL) { 4075051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4085051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 4095051Swyllys numattr++; 4105051Swyllys } 4115051Swyllys 4125051Swyllys if (issuer != NULL) { 4135051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4145051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 4155051Swyllys numattr++; 4165051Swyllys } 4175051Swyllys 4185051Swyllys if (subject != NULL) { 4195051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4205051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 4215051Swyllys numattr++; 4225051Swyllys } 4235051Swyllys 4245051Swyllys if (serial != NULL) { 4255051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4265051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 4275051Swyllys numattr++; 4285051Swyllys } 4295051Swyllys 4305051Swyllys if (tokencred != NULL) { 4315051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4325051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 4335051Swyllys numattr++; 4345051Swyllys } 4355051Swyllys 4365051Swyllys (void) get_pk12_password(&p12cred); 4375051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4385051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 4395051Swyllys numattr++; 4405051Swyllys 4415051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4425051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 4435051Swyllys numattr++; 4445051Swyllys 4455051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 4465051Swyllys 4475051Swyllys if (p12cred.cred) 4485051Swyllys free(p12cred.cred); 4495051Swyllys 4505051Swyllys return (rv); 4515051Swyllys } 4525051Swyllys 4535051Swyllys static KMF_RETURN 4545051Swyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token, 4555051Swyllys KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format, 4565637Swyllys char *label, char *filename, int oclass) 4575051Swyllys { 4585051Swyllys KMF_RETURN rv = KMF_OK; 4595051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 4605637Swyllys KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE; 4615051Swyllys int numattr = 0; 4625051Swyllys uint32_t numkeys = 1; 4635051Swyllys KMF_ATTRIBUTE attrlist[16]; 4645051Swyllys KMF_KEY_HANDLE key; 4655051Swyllys boolean_t is_token = B_TRUE; 4665051Swyllys 4675051Swyllys if (EMPTYSTRING(label)) { 4685051Swyllys cryptoerror(LOG_STDERR, gettext("A label " 4695051Swyllys "must be specified to export a key.")); 4705051Swyllys return (KMF_ERR_BAD_PARAMETER); 4715051Swyllys } 4725051Swyllys 4735051Swyllys rv = select_token(kmfhandle, token, TRUE); 4745051Swyllys if (rv != KMF_OK) { 4755051Swyllys return (rv); 4765051Swyllys } 4775051Swyllys 4785051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 4795051Swyllys &kstype, sizeof (kstype)); 4805051Swyllys numattr++; 48117Sdinak 4825051Swyllys if (cred != NULL) { 4835051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 4845051Swyllys cred, sizeof (KMF_CREDENTIAL)); 4855051Swyllys numattr++; 4865051Swyllys } 4875051Swyllys 4885051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 4895051Swyllys label, strlen(label)); 4905051Swyllys numattr++; 4915051Swyllys 4925051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 4935051Swyllys &numkeys, sizeof (numkeys)); 4945051Swyllys numattr++; 4955051Swyllys 4965051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 4975051Swyllys &key, sizeof (key)); 4985051Swyllys numattr++; 4995051Swyllys 5005051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 5015051Swyllys &is_token, sizeof (is_token)); 5025051Swyllys numattr++; 5035051Swyllys 5045051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5055051Swyllys &format, sizeof (format)); 5065051Swyllys numattr++; 5075051Swyllys 5085637Swyllys /* Check to see if we are exporting private or public only */ 5095637Swyllys if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ) 5105637Swyllys kclass = KMF_ASYM_PRI; 5115637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ) 5125637Swyllys kclass = KMF_ASYM_PUB; 5135637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ) 5145637Swyllys kclass = KMF_SYMMETRIC; 5155637Swyllys else /* only 1 key at a time can be exported here, so default to pri */ 5165637Swyllys kclass = KMF_ASYM_PRI; 5175637Swyllys 5185637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 5195637Swyllys &kclass, sizeof (kclass)); 5205637Swyllys numattr++; 5215637Swyllys 5225051Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 523*5740Swyllys /* 524*5740Swyllys * If nothing found but caller wanted ALL keys, try symmetric 525*5740Swyllys * this time. 526*5740Swyllys */ 527*5740Swyllys if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 528*5740Swyllys kclass = KMF_SYMMETRIC; 529*5740Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 530*5740Swyllys } 531*5740Swyllys /* 532*5740Swyllys * If nothing found but caller wanted ALL keys, try asymmetric 533*5740Swyllys * public this time. 534*5740Swyllys */ 535*5740Swyllys if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 536*5740Swyllys kclass = KMF_ASYM_PUB; 537*5740Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 538*5740Swyllys } 5395051Swyllys if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 5405051Swyllys KMF_RAW_SYM_KEY rkey; 5415051Swyllys 5425051Swyllys (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 5435051Swyllys rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 5445051Swyllys if (rv == KMF_OK) { 5455051Swyllys int fd, n, total = 0; 54617Sdinak 5475051Swyllys fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 5485051Swyllys if (fd == -1) { 5495051Swyllys rv = KMF_ERR_OPEN_FILE; 5505051Swyllys goto done; 5515051Swyllys } 5525051Swyllys do { 5535051Swyllys n = write(fd, rkey.keydata.val + total, 5545051Swyllys rkey.keydata.len - total); 5555051Swyllys if (n < 0) { 5565051Swyllys if (errno == EINTR) 5575051Swyllys continue; 5585069Swyllys (void) close(fd); 5595051Swyllys rv = KMF_ERR_WRITE_FILE; 5605051Swyllys goto done; 5615051Swyllys } 5625051Swyllys total += n; 56317Sdinak 5645051Swyllys } while (total < rkey.keydata.len); 5655069Swyllys (void) close(fd); 5665051Swyllys } 5675051Swyllys done: 5685051Swyllys kmf_free_bigint(&rkey.keydata); 5695051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5705051Swyllys } else if (rv == KMF_OK) { 5715051Swyllys KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 5725069Swyllys (void) printf(gettext("Found %d asymmetric keys\n"), numkeys); 5735051Swyllys 5745051Swyllys numattr = 0; 5755051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 5765051Swyllys &sslks, sizeof (sslks)); 5775051Swyllys numattr++; 5785051Swyllys 5795051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 5805051Swyllys key.keyp, sizeof (KMF_RAW_KEY_DATA)); 5815051Swyllys numattr++; 5825051Swyllys 5835051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5845051Swyllys &format, sizeof (format)); 5855051Swyllys numattr++; 5865051Swyllys 5875051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 5885051Swyllys filename, strlen(filename)); 5895051Swyllys numattr++; 5905051Swyllys 5915637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 5925637Swyllys &key.keyclass, sizeof (KMF_KEY_CLASS)); 5935637Swyllys numattr++; 5945637Swyllys 5955051Swyllys rv = kmf_store_key(kmfhandle, numattr, attrlist); 5965051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5975051Swyllys } 59817Sdinak 5993089Swyllys return (rv); 60017Sdinak } 60117Sdinak 6023089Swyllys static KMF_RETURN 6033089Swyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 6043089Swyllys char *certlabel, char *issuer, char *subject, 6053089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 6063089Swyllys char *filename) 60717Sdinak { 6083089Swyllys KMF_RETURN rv = KMF_OK; 6093089Swyllys KMF_X509_DER_CERT kmfcert; 6105051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 6115051Swyllys int numattr = 0; 6125051Swyllys KMF_ATTRIBUTE attrlist[16]; 61317Sdinak 6143089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 61517Sdinak 6163089Swyllys if (rv != KMF_OK) { 61717Sdinak return (rv); 61817Sdinak } 61917Sdinak 6205051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 6215051Swyllys &kstype, sizeof (kstype)); 6225051Swyllys numattr++; 6235051Swyllys 6245051Swyllys if (certlabel != NULL) { 6255051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6265051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 6275051Swyllys strlen(certlabel)); 6285051Swyllys numattr++; 6295051Swyllys } 63017Sdinak 6315051Swyllys if (issuer != NULL) { 6325051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6335051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 6345051Swyllys strlen(issuer)); 6355051Swyllys numattr++; 6365051Swyllys } 6375051Swyllys 6385051Swyllys if (subject != NULL) { 6395051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6405051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 6415051Swyllys strlen(subject)); 6425051Swyllys numattr++; 6435051Swyllys } 6445051Swyllys 6455051Swyllys if (serial != NULL) { 6465051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6475051Swyllys KMF_BIGINT_ATTR, serial, 6485051Swyllys sizeof (KMF_BIGINT)); 6495051Swyllys numattr++; 6505051Swyllys } 6515051Swyllys 6525051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert); 65317Sdinak 6543089Swyllys if (rv == KMF_OK) { 6555051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 6565051Swyllys numattr = 0; 6575051Swyllys 6585051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6595051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 6605051Swyllys numattr++; 6615051Swyllys 6625051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6635051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 6645051Swyllys sizeof (KMF_DATA)); 6655051Swyllys numattr++; 66617Sdinak 6675051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6685051Swyllys KMF_CERT_FILENAME_ATTR, filename, strlen(filename)); 6695051Swyllys numattr++; 67017Sdinak 6715051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6725051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 6735051Swyllys numattr++; 6745051Swyllys 6755051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 6765051Swyllys 6775051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 67817Sdinak } 6793089Swyllys return (rv); 68017Sdinak } 68117Sdinak 68217Sdinak /* 6833089Swyllys * Export objects from one keystore to a file. 68417Sdinak */ 68517Sdinak int 68617Sdinak pk_export(int argc, char *argv[]) 68717Sdinak { 688864Sdinak int opt; 689864Sdinak extern int optind_av; 690864Sdinak extern char *optarg_av; 691864Sdinak char *token_spec = NULL; 69217Sdinak char *filename = NULL; 6933089Swyllys char *dir = NULL; 6943089Swyllys char *prefix = NULL; 6953089Swyllys char *certlabel = NULL; 6963089Swyllys char *subject = NULL; 6973089Swyllys char *issuer = NULL; 6983089Swyllys char *infile = NULL; 6993089Swyllys char *keyfile = NULL; 7003089Swyllys char *certfile = NULL; 7013089Swyllys char *serstr = NULL; 7023089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 7033089Swyllys KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; 7043089Swyllys KMF_RETURN rv = KMF_OK; 7053089Swyllys int oclass = PK_CERT_OBJ; 7063089Swyllys KMF_BIGINT serial = { NULL, 0 }; 7073089Swyllys KMF_HANDLE_T kmfhandle = NULL; 7083089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 70917Sdinak 710864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 7113089Swyllys while ((opt = getopt_av(argc, argv, 7125051Swyllys "k:(keystore)y:(objtype)T:(token)" 7135051Swyllys "d:(dir)p:(prefix)" 7145051Swyllys "l:(label)n:(nickname)s:(subject)" 7155051Swyllys "i:(issuer)S:(serial)" 7165051Swyllys "K:(keyfile)c:(certfile)" 7175051Swyllys "F:(outformat)" 7185051Swyllys "I:(infile)o:(outfile)")) != EOF) { 7193089Swyllys if (EMPTYSTRING(optarg_av)) 7203089Swyllys return (PK_ERR_USAGE); 721864Sdinak switch (opt) { 7223089Swyllys case 'k': 7233089Swyllys kstype = KS2Int(optarg_av); 7243089Swyllys if (kstype == 0) 7253089Swyllys return (PK_ERR_USAGE); 7263089Swyllys break; 7273089Swyllys case 'y': 7283089Swyllys oclass = OT2Int(optarg_av); 7293089Swyllys if (oclass == -1) 7303089Swyllys return (PK_ERR_USAGE); 7313089Swyllys break; 732864Sdinak case 'T': /* token specifier */ 733864Sdinak if (token_spec) 734864Sdinak return (PK_ERR_USAGE); 735864Sdinak token_spec = optarg_av; 736864Sdinak break; 7373089Swyllys case 'd': 7383089Swyllys if (dir) 7393089Swyllys return (PK_ERR_USAGE); 7403089Swyllys dir = optarg_av; 7413089Swyllys break; 7423089Swyllys case 'p': 7433089Swyllys if (prefix) 7443089Swyllys return (PK_ERR_USAGE); 7453089Swyllys prefix = optarg_av; 7463089Swyllys break; 7473089Swyllys case 'n': 7483089Swyllys case 'l': 7493089Swyllys if (certlabel) 7503089Swyllys return (PK_ERR_USAGE); 7513089Swyllys certlabel = optarg_av; 7523089Swyllys break; 7533089Swyllys case 's': 7543089Swyllys if (subject) 7553089Swyllys return (PK_ERR_USAGE); 7563089Swyllys subject = optarg_av; 7573089Swyllys break; 7583089Swyllys case 'i': 7593089Swyllys if (issuer) 7603089Swyllys return (PK_ERR_USAGE); 7613089Swyllys issuer = optarg_av; 7623089Swyllys break; 7633089Swyllys case 'S': 7643089Swyllys serstr = optarg_av; 7653089Swyllys break; 7663089Swyllys case 'F': 7673089Swyllys kfmt = Str2Format(optarg_av); 7683089Swyllys if (kfmt == KMF_FORMAT_UNDEF) 7693089Swyllys return (PK_ERR_USAGE); 7703089Swyllys break; 7713089Swyllys case 'I': /* output file name */ 7723089Swyllys if (infile) 7733089Swyllys return (PK_ERR_USAGE); 7743089Swyllys infile = optarg_av; 7753089Swyllys break; 776864Sdinak case 'o': /* output file name */ 777864Sdinak if (filename) 778864Sdinak return (PK_ERR_USAGE); 779864Sdinak filename = optarg_av; 780864Sdinak break; 7813089Swyllys case 'c': /* input cert file name */ 7823089Swyllys if (certfile) 7833089Swyllys return (PK_ERR_USAGE); 7843089Swyllys certfile = optarg_av; 7853089Swyllys break; 7863089Swyllys case 'K': /* input key file name */ 7873089Swyllys if (keyfile) 7883089Swyllys return (PK_ERR_USAGE); 7893089Swyllys keyfile = optarg_av; 7903089Swyllys break; 791864Sdinak default: 792864Sdinak return (PK_ERR_USAGE); 793864Sdinak break; 794864Sdinak } 795864Sdinak } 79617Sdinak 7973089Swyllys /* Assume keystore = PKCS#11 if not specified */ 7983089Swyllys if (kstype == 0) 7993089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 800864Sdinak 801864Sdinak /* Filename arg is required. */ 8023089Swyllys if (EMPTYSTRING(filename)) { 8033089Swyllys cryptoerror(LOG_STDERR, gettext("You must specify " 8045051Swyllys "an 'outfile' parameter when exporting.\n")); 80517Sdinak return (PK_ERR_USAGE); 8063089Swyllys } 80717Sdinak 808864Sdinak /* No additional args allowed. */ 809864Sdinak argc -= optind_av; 810864Sdinak argv += optind_av; 811864Sdinak if (argc) 812864Sdinak return (PK_ERR_USAGE); 8133089Swyllys 8143089Swyllys /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 8153089Swyllys if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 8165051Swyllys kstype != KMF_KEYSTORE_PK11TOKEN) { 8173089Swyllys 8183089Swyllys (void) fprintf(stderr, gettext("The objtype parameter " 8195051Swyllys "is only relevant if keystore=pkcs11\n")); 8203089Swyllys return (PK_ERR_USAGE); 8213089Swyllys } 8223089Swyllys 8233089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 8243089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 8253089Swyllys else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 8263089Swyllys token_spec = DEFAULT_NSS_TOKEN; 8273089Swyllys 8283089Swyllys if (kstype == KMF_KEYSTORE_OPENSSL) { 8293089Swyllys if (kfmt != KMF_FORMAT_PKCS12) { 8303089Swyllys cryptoerror(LOG_STDERR, gettext("PKCS12 " 8315051Swyllys "is the only export format " 8325051Swyllys "supported for the 'file' " 8335051Swyllys "keystore.\n")); 8343089Swyllys return (PK_ERR_USAGE); 8353089Swyllys } 8363089Swyllys if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 8373089Swyllys cryptoerror(LOG_STDERR, gettext("A cert file" 8385051Swyllys "and a key file must be specified " 8395051Swyllys "when exporting to PKCS12 from the " 8405051Swyllys "'file' keystore.\n")); 8413089Swyllys return (PK_ERR_USAGE); 8423089Swyllys } 8433089Swyllys } 84417Sdinak 84517Sdinak /* Check if the file exists and might be overwritten. */ 84617Sdinak if (access(filename, F_OK) == 0) { 8473089Swyllys cryptoerror(LOG_STDERR, 8485051Swyllys gettext("Warning: file \"%s\" exists, " 8495051Swyllys "will be overwritten."), filename); 85017Sdinak if (yesno(gettext("Continue with export? "), 85117Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 85217Sdinak return (0); 8535637Swyllys } else { 8545637Swyllys /* remove the file */ 8555637Swyllys (void) unlink(filename); 85617Sdinak } 8573089Swyllys } else { 8583089Swyllys rv = verify_file(filename); 8593089Swyllys if (rv != KMF_OK) { 8603089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 8615051Swyllys "cannot be created.\n"), filename); 8623089Swyllys return (PK_ERR_USAGE); 8633089Swyllys } 86417Sdinak } 86517Sdinak 8663089Swyllys if (serstr != NULL) { 8673089Swyllys uchar_t *bytes = NULL; 8683089Swyllys size_t bytelen; 86917Sdinak 8705051Swyllys rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 8713089Swyllys if (rv != KMF_OK || bytes == NULL) { 8723089Swyllys (void) fprintf(stderr, gettext("serial number " 8735051Swyllys "must be specified as a hex number " 8745051Swyllys "(ex: 0x0102030405ffeeddee)\n")); 8753089Swyllys return (PK_ERR_USAGE); 8763089Swyllys } 8773089Swyllys serial.val = bytes; 8783089Swyllys serial.len = bytelen; 87917Sdinak } 88017Sdinak 8813089Swyllys if ((kstype == KMF_KEYSTORE_PK11TOKEN || 8825051Swyllys kstype == KMF_KEYSTORE_NSS) && 8835051Swyllys (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || 8845051Swyllys kfmt == KMF_FORMAT_PKCS12)) { 8853089Swyllys (void) get_token_password(kstype, token_spec, 8865051Swyllys &tokencred); 88717Sdinak } 88817Sdinak 8895051Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 8903089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing " 8915051Swyllys "KMF: 0x%02x\n"), rv); 8923089Swyllys return (rv); 89317Sdinak } 89417Sdinak 8953089Swyllys switch (kstype) { 8963089Swyllys case KMF_KEYSTORE_PK11TOKEN: 8973089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8985051Swyllys rv = pk_export_pk12_pk11(kmfhandle, 8995051Swyllys token_spec, certlabel, 9005051Swyllys issuer, subject, 9015051Swyllys &serial, &tokencred, 9025051Swyllys filename); 9035051Swyllys else if ((oclass & PK_KEY_OBJ) || 9045051Swyllys kfmt == KMF_FORMAT_RAWKEY) 9055051Swyllys rv = pk_export_pk11_keys(kmfhandle, 9065051Swyllys token_spec, &tokencred, kfmt, 9075637Swyllys certlabel, filename, oclass); 9083089Swyllys else 9093089Swyllys rv = pk_export_pk11_objects(kmfhandle, 9105051Swyllys token_spec, certlabel, 9115051Swyllys issuer, subject, &serial, kfmt, 9125051Swyllys filename); 9133089Swyllys break; 9143089Swyllys case KMF_KEYSTORE_NSS: 9153089Swyllys if (dir == NULL) 9163089Swyllys dir = PK_DEFAULT_DIRECTORY; 9173089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9183089Swyllys rv = pk_export_pk12_nss(kmfhandle, 9195051Swyllys token_spec, dir, prefix, 9205051Swyllys certlabel, issuer, 9215051Swyllys subject, &serial, 9225051Swyllys &tokencred, filename); 9233089Swyllys else 9243089Swyllys rv = pk_export_nss_objects(kmfhandle, 9255051Swyllys token_spec, 9265051Swyllys oclass, certlabel, issuer, subject, 9275051Swyllys &serial, kfmt, dir, prefix, filename); 9283089Swyllys break; 9293089Swyllys case KMF_KEYSTORE_OPENSSL: 9303089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9313089Swyllys rv = pk_export_pk12_files(kmfhandle, 9325051Swyllys certfile, keyfile, dir, 9335051Swyllys filename); 9343089Swyllys else 9353089Swyllys rv = pk_export_file_objects(kmfhandle, oclass, 9365051Swyllys issuer, subject, &serial, 9375051Swyllys dir, infile, filename); 9383089Swyllys break; 9393089Swyllys default: 9403089Swyllys rv = PK_ERR_USAGE; 9413089Swyllys break; 94217Sdinak } 94317Sdinak 9443089Swyllys if (rv != KMF_OK) { 9453089Swyllys display_error(kmfhandle, rv, 9465051Swyllys gettext("Error exporting objects")); 9473089Swyllys } 94817Sdinak 9493089Swyllys if (serial.val != NULL) 9503089Swyllys free(serial.val); 95117Sdinak 9525051Swyllys (void) kmf_finalize(kmfhandle); 9533089Swyllys 9543089Swyllys return (rv); 95517Sdinak } 956