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, 456*5637Swyllys char *label, char *filename, int oclass) 4575051Swyllys { 4585051Swyllys KMF_RETURN rv = KMF_OK; 4595051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 460*5637Swyllys 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 508*5637Swyllys /* Check to see if we are exporting private or public only */ 509*5637Swyllys if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ) 510*5637Swyllys kclass = KMF_ASYM_PRI; 511*5637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ) 512*5637Swyllys kclass = KMF_ASYM_PUB; 513*5637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ) 514*5637Swyllys kclass = KMF_SYMMETRIC; 515*5637Swyllys else /* only 1 key at a time can be exported here, so default to pri */ 516*5637Swyllys kclass = KMF_ASYM_PRI; 517*5637Swyllys 518*5637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 519*5637Swyllys &kclass, sizeof (kclass)); 520*5637Swyllys numattr++; 521*5637Swyllys 5225051Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5235051Swyllys if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 5245051Swyllys KMF_RAW_SYM_KEY rkey; 5255051Swyllys 5265051Swyllys (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 5275051Swyllys rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 5285051Swyllys if (rv == KMF_OK) { 5295051Swyllys int fd, n, total = 0; 53017Sdinak 5315051Swyllys fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 5325051Swyllys if (fd == -1) { 5335051Swyllys rv = KMF_ERR_OPEN_FILE; 5345051Swyllys goto done; 5355051Swyllys } 5365051Swyllys do { 5375051Swyllys n = write(fd, rkey.keydata.val + total, 5385051Swyllys rkey.keydata.len - total); 5395051Swyllys if (n < 0) { 5405051Swyllys if (errno == EINTR) 5415051Swyllys continue; 5425069Swyllys (void) close(fd); 5435051Swyllys rv = KMF_ERR_WRITE_FILE; 5445051Swyllys goto done; 5455051Swyllys } 5465051Swyllys total += n; 54717Sdinak 5485051Swyllys } while (total < rkey.keydata.len); 5495069Swyllys (void) close(fd); 5505051Swyllys } 5515051Swyllys done: 5525051Swyllys kmf_free_bigint(&rkey.keydata); 5535051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5545051Swyllys } else if (rv == KMF_OK) { 5555051Swyllys KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 5565069Swyllys (void) printf(gettext("Found %d asymmetric keys\n"), numkeys); 5575051Swyllys 5585051Swyllys numattr = 0; 5595051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 5605051Swyllys &sslks, sizeof (sslks)); 5615051Swyllys numattr++; 5625051Swyllys 5635051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 5645051Swyllys key.keyp, sizeof (KMF_RAW_KEY_DATA)); 5655051Swyllys numattr++; 5665051Swyllys 5675051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5685051Swyllys &format, sizeof (format)); 5695051Swyllys numattr++; 5705051Swyllys 5715051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 5725051Swyllys filename, strlen(filename)); 5735051Swyllys numattr++; 5745051Swyllys 575*5637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 576*5637Swyllys &key.keyclass, sizeof (KMF_KEY_CLASS)); 577*5637Swyllys numattr++; 578*5637Swyllys 5795051Swyllys rv = kmf_store_key(kmfhandle, numattr, attrlist); 5805051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5815051Swyllys } 58217Sdinak 5833089Swyllys return (rv); 58417Sdinak } 58517Sdinak 5863089Swyllys static KMF_RETURN 5873089Swyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 5883089Swyllys char *certlabel, char *issuer, char *subject, 5893089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 5903089Swyllys char *filename) 59117Sdinak { 5923089Swyllys KMF_RETURN rv = KMF_OK; 5933089Swyllys KMF_X509_DER_CERT kmfcert; 5945051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 5955051Swyllys int numattr = 0; 5965051Swyllys KMF_ATTRIBUTE attrlist[16]; 59717Sdinak 5983089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 59917Sdinak 6003089Swyllys if (rv != KMF_OK) { 60117Sdinak return (rv); 60217Sdinak } 60317Sdinak 6045051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 6055051Swyllys &kstype, sizeof (kstype)); 6065051Swyllys numattr++; 6075051Swyllys 6085051Swyllys if (certlabel != NULL) { 6095051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6105051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 6115051Swyllys strlen(certlabel)); 6125051Swyllys numattr++; 6135051Swyllys } 61417Sdinak 6155051Swyllys if (issuer != NULL) { 6165051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6175051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 6185051Swyllys strlen(issuer)); 6195051Swyllys numattr++; 6205051Swyllys } 6215051Swyllys 6225051Swyllys if (subject != NULL) { 6235051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6245051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 6255051Swyllys strlen(subject)); 6265051Swyllys numattr++; 6275051Swyllys } 6285051Swyllys 6295051Swyllys if (serial != NULL) { 6305051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6315051Swyllys KMF_BIGINT_ATTR, serial, 6325051Swyllys sizeof (KMF_BIGINT)); 6335051Swyllys numattr++; 6345051Swyllys } 6355051Swyllys 6365051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert); 63717Sdinak 6383089Swyllys if (rv == KMF_OK) { 6395051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 6405051Swyllys numattr = 0; 6415051Swyllys 6425051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6435051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 6445051Swyllys numattr++; 6455051Swyllys 6465051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6475051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 6485051Swyllys sizeof (KMF_DATA)); 6495051Swyllys numattr++; 65017Sdinak 6515051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6525051Swyllys KMF_CERT_FILENAME_ATTR, filename, strlen(filename)); 6535051Swyllys numattr++; 65417Sdinak 6555051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6565051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 6575051Swyllys numattr++; 6585051Swyllys 6595051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 6605051Swyllys 6615051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 66217Sdinak } 6633089Swyllys return (rv); 66417Sdinak } 66517Sdinak 66617Sdinak /* 6673089Swyllys * Export objects from one keystore to a file. 66817Sdinak */ 66917Sdinak int 67017Sdinak pk_export(int argc, char *argv[]) 67117Sdinak { 672864Sdinak int opt; 673864Sdinak extern int optind_av; 674864Sdinak extern char *optarg_av; 675864Sdinak char *token_spec = NULL; 67617Sdinak char *filename = NULL; 6773089Swyllys char *dir = NULL; 6783089Swyllys char *prefix = NULL; 6793089Swyllys char *certlabel = NULL; 6803089Swyllys char *subject = NULL; 6813089Swyllys char *issuer = NULL; 6823089Swyllys char *infile = NULL; 6833089Swyllys char *keyfile = NULL; 6843089Swyllys char *certfile = NULL; 6853089Swyllys char *serstr = NULL; 6863089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 6873089Swyllys KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; 6883089Swyllys KMF_RETURN rv = KMF_OK; 6893089Swyllys int oclass = PK_CERT_OBJ; 6903089Swyllys KMF_BIGINT serial = { NULL, 0 }; 6913089Swyllys KMF_HANDLE_T kmfhandle = NULL; 6923089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 69317Sdinak 694864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 6953089Swyllys while ((opt = getopt_av(argc, argv, 6965051Swyllys "k:(keystore)y:(objtype)T:(token)" 6975051Swyllys "d:(dir)p:(prefix)" 6985051Swyllys "l:(label)n:(nickname)s:(subject)" 6995051Swyllys "i:(issuer)S:(serial)" 7005051Swyllys "K:(keyfile)c:(certfile)" 7015051Swyllys "F:(outformat)" 7025051Swyllys "I:(infile)o:(outfile)")) != EOF) { 7033089Swyllys if (EMPTYSTRING(optarg_av)) 7043089Swyllys return (PK_ERR_USAGE); 705864Sdinak switch (opt) { 7063089Swyllys case 'k': 7073089Swyllys kstype = KS2Int(optarg_av); 7083089Swyllys if (kstype == 0) 7093089Swyllys return (PK_ERR_USAGE); 7103089Swyllys break; 7113089Swyllys case 'y': 7123089Swyllys oclass = OT2Int(optarg_av); 7133089Swyllys if (oclass == -1) 7143089Swyllys return (PK_ERR_USAGE); 7153089Swyllys break; 716864Sdinak case 'T': /* token specifier */ 717864Sdinak if (token_spec) 718864Sdinak return (PK_ERR_USAGE); 719864Sdinak token_spec = optarg_av; 720864Sdinak break; 7213089Swyllys case 'd': 7223089Swyllys if (dir) 7233089Swyllys return (PK_ERR_USAGE); 7243089Swyllys dir = optarg_av; 7253089Swyllys break; 7263089Swyllys case 'p': 7273089Swyllys if (prefix) 7283089Swyllys return (PK_ERR_USAGE); 7293089Swyllys prefix = optarg_av; 7303089Swyllys break; 7313089Swyllys case 'n': 7323089Swyllys case 'l': 7333089Swyllys if (certlabel) 7343089Swyllys return (PK_ERR_USAGE); 7353089Swyllys certlabel = optarg_av; 7363089Swyllys break; 7373089Swyllys case 's': 7383089Swyllys if (subject) 7393089Swyllys return (PK_ERR_USAGE); 7403089Swyllys subject = optarg_av; 7413089Swyllys break; 7423089Swyllys case 'i': 7433089Swyllys if (issuer) 7443089Swyllys return (PK_ERR_USAGE); 7453089Swyllys issuer = optarg_av; 7463089Swyllys break; 7473089Swyllys case 'S': 7483089Swyllys serstr = optarg_av; 7493089Swyllys break; 7503089Swyllys case 'F': 7513089Swyllys kfmt = Str2Format(optarg_av); 7523089Swyllys if (kfmt == KMF_FORMAT_UNDEF) 7533089Swyllys return (PK_ERR_USAGE); 7543089Swyllys break; 7553089Swyllys case 'I': /* output file name */ 7563089Swyllys if (infile) 7573089Swyllys return (PK_ERR_USAGE); 7583089Swyllys infile = optarg_av; 7593089Swyllys break; 760864Sdinak case 'o': /* output file name */ 761864Sdinak if (filename) 762864Sdinak return (PK_ERR_USAGE); 763864Sdinak filename = optarg_av; 764864Sdinak break; 7653089Swyllys case 'c': /* input cert file name */ 7663089Swyllys if (certfile) 7673089Swyllys return (PK_ERR_USAGE); 7683089Swyllys certfile = optarg_av; 7693089Swyllys break; 7703089Swyllys case 'K': /* input key file name */ 7713089Swyllys if (keyfile) 7723089Swyllys return (PK_ERR_USAGE); 7733089Swyllys keyfile = optarg_av; 7743089Swyllys break; 775864Sdinak default: 776864Sdinak return (PK_ERR_USAGE); 777864Sdinak break; 778864Sdinak } 779864Sdinak } 78017Sdinak 7813089Swyllys /* Assume keystore = PKCS#11 if not specified */ 7823089Swyllys if (kstype == 0) 7833089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 784864Sdinak 785864Sdinak /* Filename arg is required. */ 7863089Swyllys if (EMPTYSTRING(filename)) { 7873089Swyllys cryptoerror(LOG_STDERR, gettext("You must specify " 7885051Swyllys "an 'outfile' parameter when exporting.\n")); 78917Sdinak return (PK_ERR_USAGE); 7903089Swyllys } 79117Sdinak 792864Sdinak /* No additional args allowed. */ 793864Sdinak argc -= optind_av; 794864Sdinak argv += optind_av; 795864Sdinak if (argc) 796864Sdinak return (PK_ERR_USAGE); 7973089Swyllys 7983089Swyllys /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 7993089Swyllys if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 8005051Swyllys kstype != KMF_KEYSTORE_PK11TOKEN) { 8013089Swyllys 8023089Swyllys (void) fprintf(stderr, gettext("The objtype parameter " 8035051Swyllys "is only relevant if keystore=pkcs11\n")); 8043089Swyllys return (PK_ERR_USAGE); 8053089Swyllys } 8063089Swyllys 8073089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 8083089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 8093089Swyllys else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 8103089Swyllys token_spec = DEFAULT_NSS_TOKEN; 8113089Swyllys 8123089Swyllys if (kstype == KMF_KEYSTORE_OPENSSL) { 8133089Swyllys if (kfmt != KMF_FORMAT_PKCS12) { 8143089Swyllys cryptoerror(LOG_STDERR, gettext("PKCS12 " 8155051Swyllys "is the only export format " 8165051Swyllys "supported for the 'file' " 8175051Swyllys "keystore.\n")); 8183089Swyllys return (PK_ERR_USAGE); 8193089Swyllys } 8203089Swyllys if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 8213089Swyllys cryptoerror(LOG_STDERR, gettext("A cert file" 8225051Swyllys "and a key file must be specified " 8235051Swyllys "when exporting to PKCS12 from the " 8245051Swyllys "'file' keystore.\n")); 8253089Swyllys return (PK_ERR_USAGE); 8263089Swyllys } 8273089Swyllys } 82817Sdinak 82917Sdinak /* Check if the file exists and might be overwritten. */ 83017Sdinak if (access(filename, F_OK) == 0) { 8313089Swyllys cryptoerror(LOG_STDERR, 8325051Swyllys gettext("Warning: file \"%s\" exists, " 8335051Swyllys "will be overwritten."), filename); 83417Sdinak if (yesno(gettext("Continue with export? "), 83517Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 83617Sdinak return (0); 837*5637Swyllys } else { 838*5637Swyllys /* remove the file */ 839*5637Swyllys (void) unlink(filename); 84017Sdinak } 8413089Swyllys } else { 8423089Swyllys rv = verify_file(filename); 8433089Swyllys if (rv != KMF_OK) { 8443089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 8455051Swyllys "cannot be created.\n"), filename); 8463089Swyllys return (PK_ERR_USAGE); 8473089Swyllys } 84817Sdinak } 84917Sdinak 8503089Swyllys if (serstr != NULL) { 8513089Swyllys uchar_t *bytes = NULL; 8523089Swyllys size_t bytelen; 85317Sdinak 8545051Swyllys rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 8553089Swyllys if (rv != KMF_OK || bytes == NULL) { 8563089Swyllys (void) fprintf(stderr, gettext("serial number " 8575051Swyllys "must be specified as a hex number " 8585051Swyllys "(ex: 0x0102030405ffeeddee)\n")); 8593089Swyllys return (PK_ERR_USAGE); 8603089Swyllys } 8613089Swyllys serial.val = bytes; 8623089Swyllys serial.len = bytelen; 86317Sdinak } 86417Sdinak 8653089Swyllys if ((kstype == KMF_KEYSTORE_PK11TOKEN || 8665051Swyllys kstype == KMF_KEYSTORE_NSS) && 8675051Swyllys (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || 8685051Swyllys kfmt == KMF_FORMAT_PKCS12)) { 8693089Swyllys (void) get_token_password(kstype, token_spec, 8705051Swyllys &tokencred); 87117Sdinak } 87217Sdinak 8735051Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 8743089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing " 8755051Swyllys "KMF: 0x%02x\n"), rv); 8763089Swyllys return (rv); 87717Sdinak } 87817Sdinak 8793089Swyllys switch (kstype) { 8803089Swyllys case KMF_KEYSTORE_PK11TOKEN: 8813089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8825051Swyllys rv = pk_export_pk12_pk11(kmfhandle, 8835051Swyllys token_spec, certlabel, 8845051Swyllys issuer, subject, 8855051Swyllys &serial, &tokencred, 8865051Swyllys filename); 8875051Swyllys else if ((oclass & PK_KEY_OBJ) || 8885051Swyllys kfmt == KMF_FORMAT_RAWKEY) 8895051Swyllys rv = pk_export_pk11_keys(kmfhandle, 8905051Swyllys token_spec, &tokencred, kfmt, 891*5637Swyllys certlabel, filename, oclass); 8923089Swyllys else 8933089Swyllys rv = pk_export_pk11_objects(kmfhandle, 8945051Swyllys token_spec, certlabel, 8955051Swyllys issuer, subject, &serial, kfmt, 8965051Swyllys filename); 8973089Swyllys break; 8983089Swyllys case KMF_KEYSTORE_NSS: 8993089Swyllys if (dir == NULL) 9003089Swyllys dir = PK_DEFAULT_DIRECTORY; 9013089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9023089Swyllys rv = pk_export_pk12_nss(kmfhandle, 9035051Swyllys token_spec, dir, prefix, 9045051Swyllys certlabel, issuer, 9055051Swyllys subject, &serial, 9065051Swyllys &tokencred, filename); 9073089Swyllys else 9083089Swyllys rv = pk_export_nss_objects(kmfhandle, 9095051Swyllys token_spec, 9105051Swyllys oclass, certlabel, issuer, subject, 9115051Swyllys &serial, kfmt, dir, prefix, filename); 9123089Swyllys break; 9133089Swyllys case KMF_KEYSTORE_OPENSSL: 9143089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9153089Swyllys rv = pk_export_pk12_files(kmfhandle, 9165051Swyllys certfile, keyfile, dir, 9175051Swyllys filename); 9183089Swyllys else 9193089Swyllys rv = pk_export_file_objects(kmfhandle, oclass, 9205051Swyllys issuer, subject, &serial, 9215051Swyllys dir, infile, filename); 9223089Swyllys break; 9233089Swyllys default: 9243089Swyllys rv = PK_ERR_USAGE; 9253089Swyllys break; 92617Sdinak } 92717Sdinak 9283089Swyllys if (rv != KMF_OK) { 9293089Swyllys display_error(kmfhandle, rv, 9305051Swyllys gettext("Error exporting objects")); 9313089Swyllys } 93217Sdinak 9333089Swyllys if (serial.val != NULL) 9343089Swyllys free(serial.val); 93517Sdinak 9365051Swyllys (void) kmf_finalize(kmfhandle); 9373089Swyllys 9383089Swyllys return (rv); 93917Sdinak } 940