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 * 22*10241Swyllys.ingersoll@sun.com * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2317Sdinak * Use is subject to license terms. 2417Sdinak */ 2517Sdinak 2617Sdinak /* 2717Sdinak * This file implements the export operation for this tool. 2817Sdinak * The basic flow of the process is to find the soft token, 2917Sdinak * log into it, find the PKCS#11 objects in the soft token 3017Sdinak * to be exported matching keys with their certificates, export 3117Sdinak * them to the PKCS#12 file encrypting them with a file password 3217Sdinak * if desired, and log out. 3317Sdinak */ 3417Sdinak 3517Sdinak #include <stdio.h> 3617Sdinak #include <stdlib.h> 3717Sdinak #include <string.h> 3817Sdinak #include <errno.h> 393089Swyllys #include <fcntl.h> 4017Sdinak #include "common.h" 413089Swyllys 423089Swyllys #include <kmfapi.h> 4317Sdinak 443089Swyllys static KMF_RETURN 455051Swyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist, 465051Swyllys int numattr, KMF_X509_DER_CERT *cert) 4717Sdinak { 483089Swyllys KMF_RETURN rv = KMF_OK; 493089Swyllys uint32_t numcerts = 0; 5017Sdinak 513089Swyllys numcerts = 0; 523089Swyllys (void) memset(cert, 0, sizeof (KMF_X509_DER_CERT)); 535051Swyllys 545051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 555051Swyllys &numcerts, sizeof (uint32_t)); 565051Swyllys numattr++; 575051Swyllys 585051Swyllys rv = kmf_find_cert(kmfhandle, numattr, attrlist); 593089Swyllys if (rv != KMF_OK) { 603089Swyllys return (rv); 6117Sdinak } 623089Swyllys if (numcerts == 0) { 633089Swyllys cryptoerror(LOG_STDERR, 645051Swyllys gettext("No matching certificates found.")); 653089Swyllys return (KMF_ERR_CERT_NOT_FOUND); 6617Sdinak 673089Swyllys } else if (numcerts == 1) { 685051Swyllys kmf_set_attr_at_index(attrlist, numattr, 695051Swyllys KMF_X509_DER_CERT_ATTR, cert, 705051Swyllys sizeof (KMF_X509_DER_CERT)); 715051Swyllys numattr++; 725051Swyllys rv = kmf_find_cert(kmfhandle, numattr, attrlist); 7317Sdinak 743089Swyllys } else if (numcerts > 1) { 753089Swyllys cryptoerror(LOG_STDERR, 765051Swyllys gettext("%d certificates found, refine the " 775051Swyllys "search parameters to eliminate ambiguity\n"), 785051Swyllys numcerts); 793089Swyllys return (KMF_ERR_BAD_PARAMETER); 803089Swyllys } 813089Swyllys return (rv); 823089Swyllys } 8317Sdinak 843089Swyllys static KMF_RETURN 853089Swyllys pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass, 863089Swyllys char *issuer, char *subject, KMF_BIGINT *serial, 876669Swyllys char *infile, char *filename) 883089Swyllys { 893089Swyllys KMF_RETURN rv = KMF_OK; 903089Swyllys KMF_X509_DER_CERT kmfcert; 915051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 925051Swyllys int numattr = 0; 935051Swyllys KMF_ATTRIBUTE attrlist[16]; 9417Sdinak 953089Swyllys /* If searching for public objects or certificates, find certs now */ 963089Swyllys if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 975051Swyllys kmf_set_attr_at_index(attrlist, numattr, 985051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 995051Swyllys sizeof (kstype)); 1005051Swyllys numattr++; 1015051Swyllys 1025051Swyllys if (issuer != NULL) { 1035051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1045051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 1055051Swyllys strlen(issuer)); 1065051Swyllys numattr++; 1075051Swyllys } 1085051Swyllys 1095051Swyllys if (subject != NULL) { 1105051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1115051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 1125051Swyllys strlen(subject)); 1135051Swyllys numattr++; 1145051Swyllys } 1155051Swyllys 1165051Swyllys if (serial != NULL) { 1175051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1185051Swyllys KMF_BIGINT_ATTR, serial, 1195051Swyllys sizeof (KMF_BIGINT)); 1205051Swyllys numattr++; 1215051Swyllys } 12217Sdinak 1235051Swyllys if (infile != NULL) { 1245051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1255051Swyllys KMF_CERT_FILENAME_ATTR, infile, 1265051Swyllys strlen(infile)); 1275051Swyllys numattr++; 1285051Swyllys } 12917Sdinak 1305051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 1315051Swyllys &kmfcert); 1323089Swyllys if (rv == KMF_OK) { 1335051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 1345051Swyllys numattr = 0; 1355051Swyllys 1365051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1375051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1385051Swyllys numattr++; 13917Sdinak 1405051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1415051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 1425051Swyllys sizeof (KMF_DATA)); 1435051Swyllys numattr++; 1445051Swyllys 1455051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1465051Swyllys KMF_CERT_FILENAME_ATTR, filename, 1475051Swyllys strlen(filename)); 1485051Swyllys numattr++; 1495051Swyllys 1505051Swyllys rv = kmf_store_cert(kmfhandle, numattr, 1515051Swyllys attrlist); 1525051Swyllys 1535051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 15417Sdinak } 15517Sdinak } 1563089Swyllys return (rv); 1573089Swyllys } 15817Sdinak 1593089Swyllys static KMF_RETURN 1603089Swyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle, 1613089Swyllys char *token_spec, char *dir, char *prefix, 1623089Swyllys char *certlabel, char *issuer, char *subject, 1633089Swyllys KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, 1643089Swyllys char *filename) 1653089Swyllys { 1663089Swyllys KMF_RETURN rv = KMF_OK; 1675051Swyllys KMF_KEYSTORE_TYPE kstype; 1685051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 1695051Swyllys KMF_ATTRIBUTE attrlist[16]; 1705051Swyllys int numattr = 0; 17117Sdinak 1723089Swyllys rv = configure_nss(kmfhandle, dir, prefix); 1733089Swyllys if (rv != KMF_OK) 1743089Swyllys return (rv); 17517Sdinak 1763089Swyllys if (token_spec == NULL) 1773089Swyllys token_spec = DEFAULT_NSS_TOKEN; 17817Sdinak 1795051Swyllys kstype = KMF_KEYSTORE_NSS; 1805051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1815051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1825051Swyllys numattr++; 1835051Swyllys 1845051Swyllys if (certlabel != NULL) { 1855051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1865051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 1875051Swyllys numattr++; 1885051Swyllys } 1895051Swyllys 1905051Swyllys if (issuer != NULL) { 1915051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1925051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 1935051Swyllys numattr++; 1945051Swyllys } 1955051Swyllys 1965051Swyllys if (subject != NULL) { 1975051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1985051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 1995051Swyllys numattr++; 2005051Swyllys } 20117Sdinak 2025051Swyllys if (serial != NULL) { 2035051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2045051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 2055051Swyllys numattr++; 2065051Swyllys } 2075051Swyllys 2085051Swyllys if (tokencred != NULL) { 2095051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2105051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 2115051Swyllys numattr++; 2125051Swyllys } 21317Sdinak 2145051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 2155051Swyllys token_spec, strlen(token_spec)); 2165051Swyllys numattr++; 2175051Swyllys 2185051Swyllys (void) get_pk12_password(&p12cred); 2195051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2205051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 2215051Swyllys numattr++; 2225051Swyllys 2235051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2245051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 2255051Swyllys numattr++; 2265051Swyllys 2275051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 2285051Swyllys 2295051Swyllys if (p12cred.cred) 2305051Swyllys free(p12cred.cred); 23117Sdinak 2323089Swyllys return (rv); 23317Sdinak } 23417Sdinak 2353089Swyllys static KMF_RETURN 2363089Swyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle, 2376669Swyllys char *certfile, char *keyfile, 2383089Swyllys char *outfile) 23917Sdinak { 2403089Swyllys KMF_RETURN rv; 2415051Swyllys KMF_KEYSTORE_TYPE kstype; 2425051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 2435051Swyllys KMF_ATTRIBUTE attrlist[16]; 2445051Swyllys int numattr = 0; 24517Sdinak 2465051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 2475051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2485051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 2495051Swyllys numattr++; 2505051Swyllys 2515051Swyllys if (certfile != NULL) { 2525051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2535051Swyllys KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile)); 2545051Swyllys numattr++; 2555051Swyllys } 2565051Swyllys 2575051Swyllys if (keyfile != NULL) { 2585051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2595051Swyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 2605051Swyllys numattr++; 2615051Swyllys } 26217Sdinak 2635051Swyllys (void) get_pk12_password(&p12cred); 2645051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2655051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 2665051Swyllys numattr++; 26717Sdinak 2685051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2695051Swyllys KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile)); 2705051Swyllys numattr++; 27117Sdinak 2725051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 2735051Swyllys 2745051Swyllys if (p12cred.cred) 2755051Swyllys free(p12cred.cred); 27617Sdinak 2773089Swyllys return (rv); 27817Sdinak } 27917Sdinak 2803089Swyllys static KMF_RETURN 2813089Swyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 2823089Swyllys int oclass, char *certlabel, char *issuer, char *subject, 2833089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir, 2843089Swyllys char *prefix, char *filename) 28517Sdinak { 2863089Swyllys KMF_RETURN rv = KMF_OK; 2873089Swyllys KMF_X509_DER_CERT kmfcert; 2885051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 2895051Swyllys KMF_ATTRIBUTE attrlist[16]; 2905051Swyllys int numattr = 0; 2913089Swyllys 2923089Swyllys rv = configure_nss(kmfhandle, dir, prefix); 2933089Swyllys if (rv != KMF_OK) 2943089Swyllys return (rv); 2953089Swyllys 2963089Swyllys /* If searching for public objects or certificates, find certs now */ 2973089Swyllys if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 2985051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2995051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 3005051Swyllys sizeof (kstype)); 3015051Swyllys numattr++; 3025051Swyllys 3035051Swyllys if (certlabel != NULL) { 3045051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3055051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 3065051Swyllys strlen(certlabel)); 3075051Swyllys numattr++; 3085051Swyllys } 30917Sdinak 3105051Swyllys if (issuer != NULL) { 3115051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3125051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 3135051Swyllys strlen(issuer)); 3145051Swyllys numattr++; 3155051Swyllys } 3165051Swyllys 3175051Swyllys if (subject != NULL) { 3185051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3195051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 3205051Swyllys strlen(subject)); 3215051Swyllys numattr++; 3225051Swyllys } 3235051Swyllys 3245051Swyllys if (serial != NULL) { 3255051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3265051Swyllys KMF_BIGINT_ATTR, serial, 3275051Swyllys sizeof (KMF_BIGINT)); 3285051Swyllys numattr++; 3295051Swyllys } 33017Sdinak 3315051Swyllys if (token_spec != NULL) { 3325051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3335051Swyllys KMF_TOKEN_LABEL_ATTR, token_spec, 3345051Swyllys strlen(token_spec)); 3355051Swyllys numattr++; 3365051Swyllys } 3375051Swyllys 3385051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 3395051Swyllys &kmfcert); 3403089Swyllys if (rv == KMF_OK) { 3415051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 3425051Swyllys numattr = 0; 3435051Swyllys 3445051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3455051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 3465051Swyllys numattr++; 3475051Swyllys 3485051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3495051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 3505051Swyllys sizeof (KMF_DATA)); 3515051Swyllys numattr++; 35217Sdinak 3535051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3545051Swyllys KMF_CERT_FILENAME_ATTR, filename, 3555051Swyllys strlen(filename)); 3565051Swyllys numattr++; 3573089Swyllys 3585051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3595051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 3605051Swyllys numattr++; 3615051Swyllys 3625051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 3635051Swyllys 3645051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 3653089Swyllys } 3663089Swyllys } 3673089Swyllys return (rv); 36817Sdinak } 36917Sdinak 3703089Swyllys static KMF_RETURN 3713089Swyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec, 3723089Swyllys char *certlabel, char *issuer, char *subject, 3733089Swyllys KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename) 37417Sdinak { 3753089Swyllys KMF_RETURN rv = KMF_OK; 3765051Swyllys KMF_KEYSTORE_TYPE kstype; 3775051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 3785051Swyllys KMF_ATTRIBUTE attrlist[16]; 3795051Swyllys int numattr = 0; 38017Sdinak 3813089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 3823089Swyllys if (rv != KMF_OK) { 38317Sdinak return (rv); 38417Sdinak } 38517Sdinak 3865051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 3875051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3885051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 3895051Swyllys numattr++; 3905051Swyllys 3915051Swyllys if (certlabel != NULL) { 3925051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3935051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 3945051Swyllys numattr++; 3955051Swyllys } 3965051Swyllys 3975051Swyllys if (issuer != NULL) { 3985051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3995051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 4005051Swyllys numattr++; 4015051Swyllys } 4025051Swyllys 4035051Swyllys if (subject != NULL) { 4045051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4055051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 4065051Swyllys numattr++; 4075051Swyllys } 4085051Swyllys 4095051Swyllys if (serial != NULL) { 4105051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4115051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 4125051Swyllys numattr++; 4135051Swyllys } 4145051Swyllys 4155051Swyllys if (tokencred != NULL) { 4165051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4175051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 4185051Swyllys numattr++; 4195051Swyllys } 4205051Swyllys 4215051Swyllys (void) get_pk12_password(&p12cred); 4225051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4235051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 4245051Swyllys numattr++; 4255051Swyllys 4265051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4275051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 4285051Swyllys numattr++; 4295051Swyllys 4305051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 4315051Swyllys 4325051Swyllys if (p12cred.cred) 4335051Swyllys free(p12cred.cred); 4345051Swyllys 4355051Swyllys return (rv); 4365051Swyllys } 4375051Swyllys 4385051Swyllys static KMF_RETURN 4395051Swyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token, 4405051Swyllys KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format, 4415637Swyllys char *label, char *filename, int oclass) 4425051Swyllys { 4435051Swyllys KMF_RETURN rv = KMF_OK; 4445051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 4455637Swyllys KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE; 4465051Swyllys int numattr = 0; 4475051Swyllys uint32_t numkeys = 1; 4485051Swyllys KMF_ATTRIBUTE attrlist[16]; 4495051Swyllys KMF_KEY_HANDLE key; 4505051Swyllys boolean_t is_token = B_TRUE; 4515051Swyllys 4525051Swyllys if (EMPTYSTRING(label)) { 4535051Swyllys cryptoerror(LOG_STDERR, gettext("A label " 4545051Swyllys "must be specified to export a key.")); 4555051Swyllys return (KMF_ERR_BAD_PARAMETER); 4565051Swyllys } 4575051Swyllys 4585051Swyllys rv = select_token(kmfhandle, token, TRUE); 4595051Swyllys if (rv != KMF_OK) { 4605051Swyllys return (rv); 4615051Swyllys } 4625051Swyllys 4635051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 4645051Swyllys &kstype, sizeof (kstype)); 4655051Swyllys numattr++; 46617Sdinak 4675051Swyllys if (cred != NULL) { 4685051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 4695051Swyllys cred, sizeof (KMF_CREDENTIAL)); 4705051Swyllys numattr++; 4715051Swyllys } 4725051Swyllys 4735051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 4745051Swyllys label, strlen(label)); 4755051Swyllys numattr++; 4765051Swyllys 4775051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 4785051Swyllys &numkeys, sizeof (numkeys)); 4795051Swyllys numattr++; 4805051Swyllys 4815051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 4825051Swyllys &key, sizeof (key)); 4835051Swyllys numattr++; 4845051Swyllys 4855051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 4865051Swyllys &is_token, sizeof (is_token)); 4875051Swyllys numattr++; 4885051Swyllys 4895051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 4905051Swyllys &format, sizeof (format)); 4915051Swyllys numattr++; 4925051Swyllys 4935637Swyllys /* Check to see if we are exporting private or public only */ 4945637Swyllys if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ) 4955637Swyllys kclass = KMF_ASYM_PRI; 4965637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ) 4975637Swyllys kclass = KMF_ASYM_PUB; 4985637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ) 4995637Swyllys kclass = KMF_SYMMETRIC; 5005637Swyllys else /* only 1 key at a time can be exported here, so default to pri */ 5015637Swyllys kclass = KMF_ASYM_PRI; 5025637Swyllys 5035637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 5045637Swyllys &kclass, sizeof (kclass)); 5055637Swyllys numattr++; 5065637Swyllys 5075051Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5085740Swyllys /* 5095740Swyllys * If nothing found but caller wanted ALL keys, try symmetric 5105740Swyllys * this time. 5115740Swyllys */ 5125740Swyllys if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 5135740Swyllys kclass = KMF_SYMMETRIC; 5145740Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5155740Swyllys } 5165740Swyllys /* 5175740Swyllys * If nothing found but caller wanted ALL keys, try asymmetric 5185740Swyllys * public this time. 5195740Swyllys */ 5205740Swyllys if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 5215740Swyllys kclass = KMF_ASYM_PUB; 5225740Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5235740Swyllys } 5245051Swyllys if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 5255051Swyllys KMF_RAW_SYM_KEY rkey; 5265051Swyllys 5275051Swyllys (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 5285051Swyllys rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 5295051Swyllys if (rv == KMF_OK) { 5305051Swyllys int fd, n, total = 0; 53117Sdinak 5325051Swyllys fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 5335051Swyllys if (fd == -1) { 5345051Swyllys rv = KMF_ERR_OPEN_FILE; 5355051Swyllys goto done; 5365051Swyllys } 5375051Swyllys do { 5385051Swyllys n = write(fd, rkey.keydata.val + total, 5395051Swyllys rkey.keydata.len - total); 5405051Swyllys if (n < 0) { 5415051Swyllys if (errno == EINTR) 5425051Swyllys continue; 5435069Swyllys (void) close(fd); 5445051Swyllys rv = KMF_ERR_WRITE_FILE; 5455051Swyllys goto done; 5465051Swyllys } 5475051Swyllys total += n; 54817Sdinak 5495051Swyllys } while (total < rkey.keydata.len); 5505069Swyllys (void) close(fd); 5515051Swyllys } 5525051Swyllys done: 5535051Swyllys kmf_free_bigint(&rkey.keydata); 5545051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5555051Swyllys } else if (rv == KMF_OK) { 5565051Swyllys KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 5575069Swyllys (void) printf(gettext("Found %d asymmetric keys\n"), numkeys); 5585051Swyllys 5595051Swyllys numattr = 0; 5605051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 5615051Swyllys &sslks, sizeof (sslks)); 5625051Swyllys numattr++; 5635051Swyllys 5645051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 5655051Swyllys key.keyp, sizeof (KMF_RAW_KEY_DATA)); 5665051Swyllys numattr++; 5675051Swyllys 5685051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5695051Swyllys &format, sizeof (format)); 5705051Swyllys numattr++; 5715051Swyllys 5725051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 5735051Swyllys filename, strlen(filename)); 5745051Swyllys numattr++; 5755051Swyllys 5765637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 5775637Swyllys &key.keyclass, sizeof (KMF_KEY_CLASS)); 5785637Swyllys numattr++; 5795637Swyllys 5805051Swyllys rv = kmf_store_key(kmfhandle, numattr, attrlist); 5815051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5825051Swyllys } 58317Sdinak 5843089Swyllys return (rv); 58517Sdinak } 58617Sdinak 5873089Swyllys static KMF_RETURN 5883089Swyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 589*10241Swyllys.ingersoll@sun.com KMF_CREDENTIAL *cred, char *certlabel, char *issuer, char *subject, 5903089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 5913089Swyllys char *filename) 59217Sdinak { 5933089Swyllys KMF_RETURN rv = KMF_OK; 5943089Swyllys KMF_X509_DER_CERT kmfcert; 5955051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 5965051Swyllys int numattr = 0; 5975051Swyllys KMF_ATTRIBUTE attrlist[16]; 59817Sdinak 5993089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 60017Sdinak 601*10241Swyllys.ingersoll@sun.com if (rv != KMF_OK) 60217Sdinak return (rv); 60317Sdinak 6045051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 6055051Swyllys &kstype, sizeof (kstype)); 6065051Swyllys numattr++; 6075051Swyllys 608*10241Swyllys.ingersoll@sun.com if (cred != NULL) { 609*10241Swyllys.ingersoll@sun.com kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 610*10241Swyllys.ingersoll@sun.com cred, sizeof (KMF_CREDENTIAL)); 611*10241Swyllys.ingersoll@sun.com numattr++; 612*10241Swyllys.ingersoll@sun.com } 6135051Swyllys if (certlabel != NULL) { 6145051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6155051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 6165051Swyllys strlen(certlabel)); 6175051Swyllys numattr++; 6185051Swyllys } 61917Sdinak 6205051Swyllys if (issuer != NULL) { 6215051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6225051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 6235051Swyllys strlen(issuer)); 6245051Swyllys numattr++; 6255051Swyllys } 6265051Swyllys 6275051Swyllys if (subject != NULL) { 6285051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6295051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 6305051Swyllys strlen(subject)); 6315051Swyllys numattr++; 6325051Swyllys } 6335051Swyllys 6345051Swyllys if (serial != NULL) { 6355051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6365051Swyllys KMF_BIGINT_ATTR, serial, 6375051Swyllys sizeof (KMF_BIGINT)); 6385051Swyllys numattr++; 6395051Swyllys } 6405051Swyllys 6415051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert); 64217Sdinak 6433089Swyllys if (rv == KMF_OK) { 6445051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 6455051Swyllys numattr = 0; 6465051Swyllys 6475051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6485051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 6495051Swyllys numattr++; 6505051Swyllys 6515051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6525051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 6535051Swyllys sizeof (KMF_DATA)); 6545051Swyllys numattr++; 65517Sdinak 6565051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6575051Swyllys KMF_CERT_FILENAME_ATTR, filename, strlen(filename)); 6585051Swyllys numattr++; 65917Sdinak 6605051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6615051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 6625051Swyllys numattr++; 6635051Swyllys 6645051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 6655051Swyllys 6665051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 66717Sdinak } 6683089Swyllys return (rv); 66917Sdinak } 67017Sdinak 67117Sdinak /* 6723089Swyllys * Export objects from one keystore to a file. 67317Sdinak */ 67417Sdinak int 67517Sdinak pk_export(int argc, char *argv[]) 67617Sdinak { 677864Sdinak int opt; 678864Sdinak extern int optind_av; 679864Sdinak extern char *optarg_av; 680864Sdinak char *token_spec = NULL; 68117Sdinak char *filename = NULL; 6823089Swyllys char *dir = NULL; 6833089Swyllys char *prefix = NULL; 6843089Swyllys char *certlabel = NULL; 6853089Swyllys char *subject = NULL; 6863089Swyllys char *issuer = NULL; 6873089Swyllys char *infile = NULL; 6883089Swyllys char *keyfile = NULL; 6893089Swyllys char *certfile = NULL; 6903089Swyllys char *serstr = NULL; 6913089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 6923089Swyllys KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; 6933089Swyllys KMF_RETURN rv = KMF_OK; 6943089Swyllys int oclass = PK_CERT_OBJ; 6953089Swyllys KMF_BIGINT serial = { NULL, 0 }; 6963089Swyllys KMF_HANDLE_T kmfhandle = NULL; 6973089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 69817Sdinak 699864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 7003089Swyllys while ((opt = getopt_av(argc, argv, 7015051Swyllys "k:(keystore)y:(objtype)T:(token)" 7025051Swyllys "d:(dir)p:(prefix)" 7035051Swyllys "l:(label)n:(nickname)s:(subject)" 7045051Swyllys "i:(issuer)S:(serial)" 7055051Swyllys "K:(keyfile)c:(certfile)" 7065051Swyllys "F:(outformat)" 7075051Swyllys "I:(infile)o:(outfile)")) != EOF) { 7083089Swyllys if (EMPTYSTRING(optarg_av)) 7093089Swyllys return (PK_ERR_USAGE); 710864Sdinak switch (opt) { 7113089Swyllys case 'k': 7123089Swyllys kstype = KS2Int(optarg_av); 7133089Swyllys if (kstype == 0) 7143089Swyllys return (PK_ERR_USAGE); 7153089Swyllys break; 7163089Swyllys case 'y': 7173089Swyllys oclass = OT2Int(optarg_av); 7183089Swyllys if (oclass == -1) 7193089Swyllys return (PK_ERR_USAGE); 7203089Swyllys break; 721864Sdinak case 'T': /* token specifier */ 722864Sdinak if (token_spec) 723864Sdinak return (PK_ERR_USAGE); 724864Sdinak token_spec = optarg_av; 725864Sdinak break; 7263089Swyllys case 'd': 7273089Swyllys if (dir) 7283089Swyllys return (PK_ERR_USAGE); 7293089Swyllys dir = optarg_av; 7303089Swyllys break; 7313089Swyllys case 'p': 7323089Swyllys if (prefix) 7333089Swyllys return (PK_ERR_USAGE); 7343089Swyllys prefix = optarg_av; 7353089Swyllys break; 7363089Swyllys case 'n': 7373089Swyllys case 'l': 7383089Swyllys if (certlabel) 7393089Swyllys return (PK_ERR_USAGE); 7403089Swyllys certlabel = optarg_av; 7413089Swyllys break; 7423089Swyllys case 's': 7433089Swyllys if (subject) 7443089Swyllys return (PK_ERR_USAGE); 7453089Swyllys subject = optarg_av; 7463089Swyllys break; 7473089Swyllys case 'i': 7483089Swyllys if (issuer) 7493089Swyllys return (PK_ERR_USAGE); 7503089Swyllys issuer = optarg_av; 7513089Swyllys break; 7523089Swyllys case 'S': 7533089Swyllys serstr = optarg_av; 7543089Swyllys break; 7553089Swyllys case 'F': 7563089Swyllys kfmt = Str2Format(optarg_av); 7573089Swyllys if (kfmt == KMF_FORMAT_UNDEF) 7583089Swyllys return (PK_ERR_USAGE); 7593089Swyllys break; 7603089Swyllys case 'I': /* output file name */ 7613089Swyllys if (infile) 7623089Swyllys return (PK_ERR_USAGE); 7633089Swyllys infile = optarg_av; 7643089Swyllys break; 765864Sdinak case 'o': /* output file name */ 766864Sdinak if (filename) 767864Sdinak return (PK_ERR_USAGE); 768864Sdinak filename = optarg_av; 769864Sdinak break; 7703089Swyllys case 'c': /* input cert file name */ 7713089Swyllys if (certfile) 7723089Swyllys return (PK_ERR_USAGE); 7733089Swyllys certfile = optarg_av; 7743089Swyllys break; 7753089Swyllys case 'K': /* input key file name */ 7763089Swyllys if (keyfile) 7773089Swyllys return (PK_ERR_USAGE); 7783089Swyllys keyfile = optarg_av; 7793089Swyllys break; 780864Sdinak default: 781864Sdinak return (PK_ERR_USAGE); 782864Sdinak break; 783864Sdinak } 784864Sdinak } 78517Sdinak 7863089Swyllys /* Assume keystore = PKCS#11 if not specified */ 7873089Swyllys if (kstype == 0) 7883089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 789864Sdinak 790864Sdinak /* Filename arg is required. */ 7913089Swyllys if (EMPTYSTRING(filename)) { 7923089Swyllys cryptoerror(LOG_STDERR, gettext("You must specify " 7935051Swyllys "an 'outfile' parameter when exporting.\n")); 79417Sdinak return (PK_ERR_USAGE); 7953089Swyllys } 79617Sdinak 797864Sdinak /* No additional args allowed. */ 798864Sdinak argc -= optind_av; 799864Sdinak argv += optind_av; 800864Sdinak if (argc) 801864Sdinak return (PK_ERR_USAGE); 8023089Swyllys 8036884Swyllys DIR_OPTION_CHECK(kstype, dir); 8046884Swyllys 8053089Swyllys /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 8063089Swyllys if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 8075051Swyllys kstype != KMF_KEYSTORE_PK11TOKEN) { 8083089Swyllys 8093089Swyllys (void) fprintf(stderr, gettext("The objtype parameter " 8105051Swyllys "is only relevant if keystore=pkcs11\n")); 8113089Swyllys return (PK_ERR_USAGE); 8123089Swyllys } 8133089Swyllys 8143089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 8153089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 8163089Swyllys else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 8173089Swyllys token_spec = DEFAULT_NSS_TOKEN; 8183089Swyllys 8193089Swyllys if (kstype == KMF_KEYSTORE_OPENSSL) { 8203089Swyllys if (kfmt != KMF_FORMAT_PKCS12) { 8213089Swyllys cryptoerror(LOG_STDERR, gettext("PKCS12 " 8225051Swyllys "is the only export format " 8235051Swyllys "supported for the 'file' " 8245051Swyllys "keystore.\n")); 8253089Swyllys return (PK_ERR_USAGE); 8263089Swyllys } 8273089Swyllys if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 8283089Swyllys cryptoerror(LOG_STDERR, gettext("A cert file" 8295051Swyllys "and a key file must be specified " 8305051Swyllys "when exporting to PKCS12 from the " 8315051Swyllys "'file' keystore.\n")); 8323089Swyllys return (PK_ERR_USAGE); 8333089Swyllys } 8343089Swyllys } 83517Sdinak 83617Sdinak /* Check if the file exists and might be overwritten. */ 83717Sdinak if (access(filename, F_OK) == 0) { 8383089Swyllys cryptoerror(LOG_STDERR, 8395051Swyllys gettext("Warning: file \"%s\" exists, " 8405051Swyllys "will be overwritten."), filename); 84117Sdinak if (yesno(gettext("Continue with export? "), 84217Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 84317Sdinak return (0); 8445637Swyllys } else { 8455637Swyllys /* remove the file */ 8465637Swyllys (void) unlink(filename); 84717Sdinak } 8483089Swyllys } else { 8493089Swyllys rv = verify_file(filename); 8503089Swyllys if (rv != KMF_OK) { 8513089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 8525051Swyllys "cannot be created.\n"), filename); 8533089Swyllys return (PK_ERR_USAGE); 8543089Swyllys } 85517Sdinak } 85617Sdinak 8573089Swyllys if (serstr != NULL) { 8583089Swyllys uchar_t *bytes = NULL; 8593089Swyllys size_t bytelen; 86017Sdinak 8615051Swyllys rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 8623089Swyllys if (rv != KMF_OK || bytes == NULL) { 8633089Swyllys (void) fprintf(stderr, gettext("serial number " 8645051Swyllys "must be specified as a hex number " 8655051Swyllys "(ex: 0x0102030405ffeeddee)\n")); 8663089Swyllys return (PK_ERR_USAGE); 8673089Swyllys } 8683089Swyllys serial.val = bytes; 8693089Swyllys serial.len = bytelen; 87017Sdinak } 87117Sdinak 872*10241Swyllys.ingersoll@sun.com if (kstype == KMF_KEYSTORE_PK11TOKEN || 873*10241Swyllys.ingersoll@sun.com ((kstype == KMF_KEYSTORE_NSS) && 874*10241Swyllys.ingersoll@sun.com (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ))) || 875*10241Swyllys.ingersoll@sun.com kfmt == KMF_FORMAT_PKCS12) { 8763089Swyllys (void) get_token_password(kstype, token_spec, 8775051Swyllys &tokencred); 87817Sdinak } 87917Sdinak 8805051Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 8813089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing " 8825051Swyllys "KMF: 0x%02x\n"), rv); 8833089Swyllys return (rv); 88417Sdinak } 88517Sdinak 8863089Swyllys switch (kstype) { 8873089Swyllys case KMF_KEYSTORE_PK11TOKEN: 8883089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8895051Swyllys rv = pk_export_pk12_pk11(kmfhandle, 8905051Swyllys token_spec, certlabel, 8915051Swyllys issuer, subject, 8925051Swyllys &serial, &tokencred, 8935051Swyllys filename); 8945051Swyllys else if ((oclass & PK_KEY_OBJ) || 8955051Swyllys kfmt == KMF_FORMAT_RAWKEY) 8965051Swyllys rv = pk_export_pk11_keys(kmfhandle, 8975051Swyllys token_spec, &tokencred, kfmt, 8985637Swyllys certlabel, filename, oclass); 8993089Swyllys else 9003089Swyllys rv = pk_export_pk11_objects(kmfhandle, 901*10241Swyllys.ingersoll@sun.com token_spec, &tokencred, certlabel, 9025051Swyllys issuer, subject, &serial, kfmt, 9035051Swyllys filename); 9043089Swyllys break; 9053089Swyllys case KMF_KEYSTORE_NSS: 9063089Swyllys if (dir == NULL) 9073089Swyllys dir = PK_DEFAULT_DIRECTORY; 9083089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9093089Swyllys rv = pk_export_pk12_nss(kmfhandle, 9105051Swyllys token_spec, dir, prefix, 9115051Swyllys certlabel, issuer, 9125051Swyllys subject, &serial, 9135051Swyllys &tokencred, filename); 9143089Swyllys else 9153089Swyllys rv = pk_export_nss_objects(kmfhandle, 9165051Swyllys token_spec, 9175051Swyllys oclass, certlabel, issuer, subject, 9185051Swyllys &serial, kfmt, dir, prefix, filename); 9193089Swyllys break; 9203089Swyllys case KMF_KEYSTORE_OPENSSL: 9213089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9223089Swyllys rv = pk_export_pk12_files(kmfhandle, 9236669Swyllys certfile, keyfile, filename); 9243089Swyllys else 9253089Swyllys rv = pk_export_file_objects(kmfhandle, oclass, 9265051Swyllys issuer, subject, &serial, 9276669Swyllys infile, filename); 9283089Swyllys break; 9293089Swyllys default: 9303089Swyllys rv = PK_ERR_USAGE; 9313089Swyllys break; 93217Sdinak } 93317Sdinak 9343089Swyllys if (rv != KMF_OK) { 9353089Swyllys display_error(kmfhandle, rv, 9365051Swyllys gettext("Error exporting objects")); 9373089Swyllys } 93817Sdinak 9393089Swyllys if (serial.val != NULL) 9403089Swyllys free(serial.val); 94117Sdinak 9425051Swyllys (void) kmf_finalize(kmfhandle); 9433089Swyllys 9443089Swyllys return (rv); 94517Sdinak } 946