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, 4565051Swyllys char *label, char *filename) 4575051Swyllys { 4585051Swyllys KMF_RETURN rv = KMF_OK; 4595051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 4605051Swyllys int numattr = 0; 4615051Swyllys uint32_t numkeys = 1; 4625051Swyllys KMF_ATTRIBUTE attrlist[16]; 4635051Swyllys KMF_KEY_HANDLE key; 4645051Swyllys boolean_t is_token = B_TRUE; 4655051Swyllys 4665051Swyllys if (EMPTYSTRING(label)) { 4675051Swyllys cryptoerror(LOG_STDERR, gettext("A label " 4685051Swyllys "must be specified to export a key.")); 4695051Swyllys return (KMF_ERR_BAD_PARAMETER); 4705051Swyllys } 4715051Swyllys 4725051Swyllys rv = select_token(kmfhandle, token, TRUE); 4735051Swyllys if (rv != KMF_OK) { 4745051Swyllys return (rv); 4755051Swyllys } 4765051Swyllys 4775051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 4785051Swyllys &kstype, sizeof (kstype)); 4795051Swyllys numattr++; 48017Sdinak 4815051Swyllys if (cred != NULL) { 4825051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 4835051Swyllys cred, sizeof (KMF_CREDENTIAL)); 4845051Swyllys numattr++; 4855051Swyllys } 4865051Swyllys 4875051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 4885051Swyllys label, strlen(label)); 4895051Swyllys numattr++; 4905051Swyllys 4915051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 4925051Swyllys &numkeys, sizeof (numkeys)); 4935051Swyllys numattr++; 4945051Swyllys 4955051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 4965051Swyllys &key, sizeof (key)); 4975051Swyllys numattr++; 4985051Swyllys 4995051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 5005051Swyllys &is_token, sizeof (is_token)); 5015051Swyllys numattr++; 5025051Swyllys 5035051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5045051Swyllys &format, sizeof (format)); 5055051Swyllys numattr++; 5065051Swyllys 5075051Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5085051Swyllys if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 5095051Swyllys KMF_RAW_SYM_KEY rkey; 5105051Swyllys 5115051Swyllys (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 5125051Swyllys rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 5135051Swyllys if (rv == KMF_OK) { 5145051Swyllys int fd, n, total = 0; 51517Sdinak 5165051Swyllys fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 5175051Swyllys if (fd == -1) { 5185051Swyllys rv = KMF_ERR_OPEN_FILE; 5195051Swyllys goto done; 5205051Swyllys } 5215051Swyllys do { 5225051Swyllys n = write(fd, rkey.keydata.val + total, 5235051Swyllys rkey.keydata.len - total); 5245051Swyllys if (n < 0) { 5255051Swyllys if (errno == EINTR) 5265051Swyllys continue; 527*5069Swyllys (void) close(fd); 5285051Swyllys rv = KMF_ERR_WRITE_FILE; 5295051Swyllys goto done; 5305051Swyllys } 5315051Swyllys total += n; 53217Sdinak 5335051Swyllys } while (total < rkey.keydata.len); 534*5069Swyllys (void) close(fd); 5355051Swyllys } 5365051Swyllys done: 5375051Swyllys kmf_free_bigint(&rkey.keydata); 5385051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5395051Swyllys } else if (rv == KMF_OK) { 5405051Swyllys KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 541*5069Swyllys (void) printf(gettext("Found %d asymmetric keys\n"), numkeys); 5425051Swyllys 5435051Swyllys numattr = 0; 5445051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 5455051Swyllys &sslks, sizeof (sslks)); 5465051Swyllys numattr++; 5475051Swyllys 5485051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 5495051Swyllys key.keyp, sizeof (KMF_RAW_KEY_DATA)); 5505051Swyllys numattr++; 5515051Swyllys 5525051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5535051Swyllys &format, sizeof (format)); 5545051Swyllys numattr++; 5555051Swyllys 5565051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 5575051Swyllys filename, strlen(filename)); 5585051Swyllys numattr++; 5595051Swyllys 5605051Swyllys rv = kmf_store_key(kmfhandle, numattr, attrlist); 5615051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5625051Swyllys } 56317Sdinak 5643089Swyllys return (rv); 56517Sdinak } 56617Sdinak 5673089Swyllys static KMF_RETURN 5683089Swyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 5693089Swyllys char *certlabel, char *issuer, char *subject, 5703089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 5713089Swyllys char *filename) 57217Sdinak { 5733089Swyllys KMF_RETURN rv = KMF_OK; 5743089Swyllys KMF_X509_DER_CERT kmfcert; 5755051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 5765051Swyllys int numattr = 0; 5775051Swyllys KMF_ATTRIBUTE attrlist[16]; 57817Sdinak 5793089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 58017Sdinak 5813089Swyllys if (rv != KMF_OK) { 58217Sdinak return (rv); 58317Sdinak } 58417Sdinak 5855051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 5865051Swyllys &kstype, sizeof (kstype)); 5875051Swyllys numattr++; 5885051Swyllys 5895051Swyllys if (certlabel != NULL) { 5905051Swyllys kmf_set_attr_at_index(attrlist, numattr, 5915051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 5925051Swyllys strlen(certlabel)); 5935051Swyllys numattr++; 5945051Swyllys } 59517Sdinak 5965051Swyllys if (issuer != NULL) { 5975051Swyllys kmf_set_attr_at_index(attrlist, numattr, 5985051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 5995051Swyllys strlen(issuer)); 6005051Swyllys numattr++; 6015051Swyllys } 6025051Swyllys 6035051Swyllys if (subject != NULL) { 6045051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6055051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 6065051Swyllys strlen(subject)); 6075051Swyllys numattr++; 6085051Swyllys } 6095051Swyllys 6105051Swyllys if (serial != NULL) { 6115051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6125051Swyllys KMF_BIGINT_ATTR, serial, 6135051Swyllys sizeof (KMF_BIGINT)); 6145051Swyllys numattr++; 6155051Swyllys } 6165051Swyllys 6175051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert); 61817Sdinak 6193089Swyllys if (rv == KMF_OK) { 6205051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 6215051Swyllys numattr = 0; 6225051Swyllys 6235051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6245051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 6255051Swyllys numattr++; 6265051Swyllys 6275051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6285051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 6295051Swyllys sizeof (KMF_DATA)); 6305051Swyllys numattr++; 63117Sdinak 6325051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6335051Swyllys KMF_CERT_FILENAME_ATTR, filename, strlen(filename)); 6345051Swyllys numattr++; 63517Sdinak 6365051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6375051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 6385051Swyllys numattr++; 6395051Swyllys 6405051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 6415051Swyllys 6425051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 64317Sdinak } 6443089Swyllys return (rv); 64517Sdinak } 64617Sdinak 64717Sdinak /* 6483089Swyllys * Export objects from one keystore to a file. 64917Sdinak */ 65017Sdinak int 65117Sdinak pk_export(int argc, char *argv[]) 65217Sdinak { 653864Sdinak int opt; 654864Sdinak extern int optind_av; 655864Sdinak extern char *optarg_av; 656864Sdinak char *token_spec = NULL; 65717Sdinak char *filename = NULL; 6583089Swyllys char *dir = NULL; 6593089Swyllys char *prefix = NULL; 6603089Swyllys char *certlabel = NULL; 6613089Swyllys char *subject = NULL; 6623089Swyllys char *issuer = NULL; 6633089Swyllys char *infile = NULL; 6643089Swyllys char *keyfile = NULL; 6653089Swyllys char *certfile = NULL; 6663089Swyllys char *serstr = NULL; 6673089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 6683089Swyllys KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; 6693089Swyllys KMF_RETURN rv = KMF_OK; 6703089Swyllys int oclass = PK_CERT_OBJ; 6713089Swyllys KMF_BIGINT serial = { NULL, 0 }; 6723089Swyllys KMF_HANDLE_T kmfhandle = NULL; 6733089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 67417Sdinak 675864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 6763089Swyllys while ((opt = getopt_av(argc, argv, 6775051Swyllys "k:(keystore)y:(objtype)T:(token)" 6785051Swyllys "d:(dir)p:(prefix)" 6795051Swyllys "l:(label)n:(nickname)s:(subject)" 6805051Swyllys "i:(issuer)S:(serial)" 6815051Swyllys "K:(keyfile)c:(certfile)" 6825051Swyllys "F:(outformat)" 6835051Swyllys "I:(infile)o:(outfile)")) != EOF) { 6843089Swyllys if (EMPTYSTRING(optarg_av)) 6853089Swyllys return (PK_ERR_USAGE); 686864Sdinak switch (opt) { 6873089Swyllys case 'k': 6883089Swyllys kstype = KS2Int(optarg_av); 6893089Swyllys if (kstype == 0) 6903089Swyllys return (PK_ERR_USAGE); 6913089Swyllys break; 6923089Swyllys case 'y': 6933089Swyllys oclass = OT2Int(optarg_av); 6943089Swyllys if (oclass == -1) 6953089Swyllys return (PK_ERR_USAGE); 6963089Swyllys break; 697864Sdinak case 'T': /* token specifier */ 698864Sdinak if (token_spec) 699864Sdinak return (PK_ERR_USAGE); 700864Sdinak token_spec = optarg_av; 701864Sdinak break; 7023089Swyllys case 'd': 7033089Swyllys if (dir) 7043089Swyllys return (PK_ERR_USAGE); 7053089Swyllys dir = optarg_av; 7063089Swyllys break; 7073089Swyllys case 'p': 7083089Swyllys if (prefix) 7093089Swyllys return (PK_ERR_USAGE); 7103089Swyllys prefix = optarg_av; 7113089Swyllys break; 7123089Swyllys case 'n': 7133089Swyllys case 'l': 7143089Swyllys if (certlabel) 7153089Swyllys return (PK_ERR_USAGE); 7163089Swyllys certlabel = optarg_av; 7173089Swyllys break; 7183089Swyllys case 's': 7193089Swyllys if (subject) 7203089Swyllys return (PK_ERR_USAGE); 7213089Swyllys subject = optarg_av; 7223089Swyllys break; 7233089Swyllys case 'i': 7243089Swyllys if (issuer) 7253089Swyllys return (PK_ERR_USAGE); 7263089Swyllys issuer = optarg_av; 7273089Swyllys break; 7283089Swyllys case 'S': 7293089Swyllys serstr = optarg_av; 7303089Swyllys break; 7313089Swyllys case 'F': 7323089Swyllys kfmt = Str2Format(optarg_av); 7333089Swyllys if (kfmt == KMF_FORMAT_UNDEF) 7343089Swyllys return (PK_ERR_USAGE); 7353089Swyllys break; 7363089Swyllys case 'I': /* output file name */ 7373089Swyllys if (infile) 7383089Swyllys return (PK_ERR_USAGE); 7393089Swyllys infile = optarg_av; 7403089Swyllys break; 741864Sdinak case 'o': /* output file name */ 742864Sdinak if (filename) 743864Sdinak return (PK_ERR_USAGE); 744864Sdinak filename = optarg_av; 745864Sdinak break; 7463089Swyllys case 'c': /* input cert file name */ 7473089Swyllys if (certfile) 7483089Swyllys return (PK_ERR_USAGE); 7493089Swyllys certfile = optarg_av; 7503089Swyllys break; 7513089Swyllys case 'K': /* input key file name */ 7523089Swyllys if (keyfile) 7533089Swyllys return (PK_ERR_USAGE); 7543089Swyllys keyfile = optarg_av; 7553089Swyllys break; 756864Sdinak default: 757864Sdinak return (PK_ERR_USAGE); 758864Sdinak break; 759864Sdinak } 760864Sdinak } 76117Sdinak 7623089Swyllys /* Assume keystore = PKCS#11 if not specified */ 7633089Swyllys if (kstype == 0) 7643089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 765864Sdinak 766864Sdinak /* Filename arg is required. */ 7673089Swyllys if (EMPTYSTRING(filename)) { 7683089Swyllys cryptoerror(LOG_STDERR, gettext("You must specify " 7695051Swyllys "an 'outfile' parameter when exporting.\n")); 77017Sdinak return (PK_ERR_USAGE); 7713089Swyllys } 77217Sdinak 773864Sdinak /* No additional args allowed. */ 774864Sdinak argc -= optind_av; 775864Sdinak argv += optind_av; 776864Sdinak if (argc) 777864Sdinak return (PK_ERR_USAGE); 7783089Swyllys 7793089Swyllys /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 7803089Swyllys if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 7815051Swyllys kstype != KMF_KEYSTORE_PK11TOKEN) { 7823089Swyllys 7833089Swyllys (void) fprintf(stderr, gettext("The objtype parameter " 7845051Swyllys "is only relevant if keystore=pkcs11\n")); 7853089Swyllys return (PK_ERR_USAGE); 7863089Swyllys } 7873089Swyllys 7883089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 7893089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 7903089Swyllys else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 7913089Swyllys token_spec = DEFAULT_NSS_TOKEN; 7923089Swyllys 7933089Swyllys if (kstype == KMF_KEYSTORE_OPENSSL) { 7943089Swyllys if (kfmt != KMF_FORMAT_PKCS12) { 7953089Swyllys cryptoerror(LOG_STDERR, gettext("PKCS12 " 7965051Swyllys "is the only export format " 7975051Swyllys "supported for the 'file' " 7985051Swyllys "keystore.\n")); 7993089Swyllys return (PK_ERR_USAGE); 8003089Swyllys } 8013089Swyllys if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 8023089Swyllys cryptoerror(LOG_STDERR, gettext("A cert file" 8035051Swyllys "and a key file must be specified " 8045051Swyllys "when exporting to PKCS12 from the " 8055051Swyllys "'file' keystore.\n")); 8063089Swyllys return (PK_ERR_USAGE); 8073089Swyllys } 8083089Swyllys } 80917Sdinak 81017Sdinak /* Check if the file exists and might be overwritten. */ 81117Sdinak if (access(filename, F_OK) == 0) { 8123089Swyllys cryptoerror(LOG_STDERR, 8135051Swyllys gettext("Warning: file \"%s\" exists, " 8145051Swyllys "will be overwritten."), filename); 81517Sdinak if (yesno(gettext("Continue with export? "), 81617Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 81717Sdinak return (0); 81817Sdinak } 8193089Swyllys } else { 8203089Swyllys rv = verify_file(filename); 8213089Swyllys if (rv != KMF_OK) { 8223089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 8235051Swyllys "cannot be created.\n"), filename); 8243089Swyllys return (PK_ERR_USAGE); 8253089Swyllys } 82617Sdinak } 82717Sdinak 8283089Swyllys if (serstr != NULL) { 8293089Swyllys uchar_t *bytes = NULL; 8303089Swyllys size_t bytelen; 83117Sdinak 8325051Swyllys rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 8333089Swyllys if (rv != KMF_OK || bytes == NULL) { 8343089Swyllys (void) fprintf(stderr, gettext("serial number " 8355051Swyllys "must be specified as a hex number " 8365051Swyllys "(ex: 0x0102030405ffeeddee)\n")); 8373089Swyllys return (PK_ERR_USAGE); 8383089Swyllys } 8393089Swyllys serial.val = bytes; 8403089Swyllys serial.len = bytelen; 84117Sdinak } 84217Sdinak 8433089Swyllys if ((kstype == KMF_KEYSTORE_PK11TOKEN || 8445051Swyllys kstype == KMF_KEYSTORE_NSS) && 8455051Swyllys (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || 8465051Swyllys kfmt == KMF_FORMAT_PKCS12)) { 8473089Swyllys (void) get_token_password(kstype, token_spec, 8485051Swyllys &tokencred); 84917Sdinak } 85017Sdinak 8515051Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 8523089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing " 8535051Swyllys "KMF: 0x%02x\n"), rv); 8543089Swyllys return (rv); 85517Sdinak } 85617Sdinak 8573089Swyllys switch (kstype) { 8583089Swyllys case KMF_KEYSTORE_PK11TOKEN: 8593089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8605051Swyllys rv = pk_export_pk12_pk11(kmfhandle, 8615051Swyllys token_spec, certlabel, 8625051Swyllys issuer, subject, 8635051Swyllys &serial, &tokencred, 8645051Swyllys filename); 8655051Swyllys else if ((oclass & PK_KEY_OBJ) || 8665051Swyllys kfmt == KMF_FORMAT_RAWKEY) 8675051Swyllys rv = pk_export_pk11_keys(kmfhandle, 8685051Swyllys token_spec, &tokencred, kfmt, 8695051Swyllys certlabel, filename); 8703089Swyllys else 8713089Swyllys rv = pk_export_pk11_objects(kmfhandle, 8725051Swyllys token_spec, certlabel, 8735051Swyllys issuer, subject, &serial, kfmt, 8745051Swyllys filename); 8753089Swyllys break; 8763089Swyllys case KMF_KEYSTORE_NSS: 8773089Swyllys if (dir == NULL) 8783089Swyllys dir = PK_DEFAULT_DIRECTORY; 8793089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8803089Swyllys rv = pk_export_pk12_nss(kmfhandle, 8815051Swyllys token_spec, dir, prefix, 8825051Swyllys certlabel, issuer, 8835051Swyllys subject, &serial, 8845051Swyllys &tokencred, filename); 8853089Swyllys else 8863089Swyllys rv = pk_export_nss_objects(kmfhandle, 8875051Swyllys token_spec, 8885051Swyllys oclass, certlabel, issuer, subject, 8895051Swyllys &serial, kfmt, dir, prefix, filename); 8903089Swyllys break; 8913089Swyllys case KMF_KEYSTORE_OPENSSL: 8923089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8933089Swyllys rv = pk_export_pk12_files(kmfhandle, 8945051Swyllys certfile, keyfile, dir, 8955051Swyllys filename); 8963089Swyllys else 8973089Swyllys rv = pk_export_file_objects(kmfhandle, oclass, 8985051Swyllys issuer, subject, &serial, 8995051Swyllys dir, infile, filename); 9003089Swyllys break; 9013089Swyllys default: 9023089Swyllys rv = PK_ERR_USAGE; 9033089Swyllys break; 90417Sdinak } 90517Sdinak 9063089Swyllys if (rv != KMF_OK) { 9073089Swyllys display_error(kmfhandle, rv, 9085051Swyllys gettext("Error exporting objects")); 9093089Swyllys } 91017Sdinak 9113089Swyllys if (serial.val != NULL) 9123089Swyllys free(serial.val); 91317Sdinak 9145051Swyllys (void) kmf_finalize(kmfhandle); 9153089Swyllys 9163089Swyllys return (rv); 91717Sdinak } 918