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 * 226669Swyllys * Copyright 2008 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, 896669Swyllys 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 (infile != NULL) { 1265051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1275051Swyllys KMF_CERT_FILENAME_ATTR, infile, 1285051Swyllys strlen(infile)); 1295051Swyllys numattr++; 1305051Swyllys } 13117Sdinak 1325051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 1335051Swyllys &kmfcert); 1343089Swyllys if (rv == KMF_OK) { 1355051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 1365051Swyllys numattr = 0; 1375051Swyllys 1385051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1395051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1405051Swyllys numattr++; 14117Sdinak 1425051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1435051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 1445051Swyllys sizeof (KMF_DATA)); 1455051Swyllys numattr++; 1465051Swyllys 1475051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1485051Swyllys KMF_CERT_FILENAME_ATTR, filename, 1495051Swyllys strlen(filename)); 1505051Swyllys numattr++; 1515051Swyllys 1525051Swyllys rv = kmf_store_cert(kmfhandle, numattr, 1535051Swyllys attrlist); 1545051Swyllys 1555051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 15617Sdinak } 15717Sdinak } 1583089Swyllys return (rv); 1593089Swyllys } 16017Sdinak 1613089Swyllys static KMF_RETURN 1623089Swyllys pk_export_pk12_nss(KMF_HANDLE_T kmfhandle, 1633089Swyllys char *token_spec, char *dir, char *prefix, 1643089Swyllys char *certlabel, char *issuer, char *subject, 1653089Swyllys KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, 1663089Swyllys char *filename) 1673089Swyllys { 1683089Swyllys KMF_RETURN rv = KMF_OK; 1695051Swyllys KMF_KEYSTORE_TYPE kstype; 1705051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 1715051Swyllys KMF_ATTRIBUTE attrlist[16]; 1725051Swyllys int numattr = 0; 17317Sdinak 1743089Swyllys rv = configure_nss(kmfhandle, dir, prefix); 1753089Swyllys if (rv != KMF_OK) 1763089Swyllys return (rv); 17717Sdinak 1783089Swyllys if (token_spec == NULL) 1793089Swyllys token_spec = DEFAULT_NSS_TOKEN; 18017Sdinak 1815051Swyllys kstype = KMF_KEYSTORE_NSS; 1825051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1835051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 1845051Swyllys numattr++; 1855051Swyllys 1865051Swyllys if (certlabel != NULL) { 1875051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1885051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 1895051Swyllys numattr++; 1905051Swyllys } 1915051Swyllys 1925051Swyllys if (issuer != NULL) { 1935051Swyllys kmf_set_attr_at_index(attrlist, numattr, 1945051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 1955051Swyllys numattr++; 1965051Swyllys } 1975051Swyllys 1985051Swyllys if (subject != NULL) { 1995051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2005051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 2015051Swyllys numattr++; 2025051Swyllys } 20317Sdinak 2045051Swyllys if (serial != NULL) { 2055051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2065051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 2075051Swyllys numattr++; 2085051Swyllys } 2095051Swyllys 2105051Swyllys if (tokencred != NULL) { 2115051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2125051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 2135051Swyllys numattr++; 2145051Swyllys } 21517Sdinak 2165051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 2175051Swyllys token_spec, strlen(token_spec)); 2185051Swyllys numattr++; 2195051Swyllys 2205051Swyllys (void) get_pk12_password(&p12cred); 2215051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2225051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 2235051Swyllys numattr++; 2245051Swyllys 2255051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2265051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 2275051Swyllys numattr++; 2285051Swyllys 2295051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 2305051Swyllys 2315051Swyllys if (p12cred.cred) 2325051Swyllys free(p12cred.cred); 23317Sdinak 2343089Swyllys return (rv); 23517Sdinak } 23617Sdinak 2373089Swyllys static KMF_RETURN 2383089Swyllys pk_export_pk12_files(KMF_HANDLE_T kmfhandle, 2396669Swyllys char *certfile, char *keyfile, 2403089Swyllys char *outfile) 24117Sdinak { 2423089Swyllys KMF_RETURN rv; 2435051Swyllys KMF_KEYSTORE_TYPE kstype; 2445051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 2455051Swyllys KMF_ATTRIBUTE attrlist[16]; 2465051Swyllys int numattr = 0; 24717Sdinak 2485051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 2495051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2505051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 2515051Swyllys numattr++; 2525051Swyllys 2535051Swyllys if (certfile != NULL) { 2545051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2555051Swyllys KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile)); 2565051Swyllys numattr++; 2575051Swyllys } 2585051Swyllys 2595051Swyllys if (keyfile != NULL) { 2605051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2615051Swyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 2625051Swyllys numattr++; 2635051Swyllys } 26417Sdinak 2655051Swyllys (void) get_pk12_password(&p12cred); 2665051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2675051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 2685051Swyllys numattr++; 26917Sdinak 2705051Swyllys kmf_set_attr_at_index(attrlist, numattr, 2715051Swyllys KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile)); 2725051Swyllys numattr++; 27317Sdinak 2745051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 2755051Swyllys 2765051Swyllys if (p12cred.cred) 2775051Swyllys free(p12cred.cred); 27817Sdinak 2793089Swyllys return (rv); 28017Sdinak } 28117Sdinak 2823089Swyllys static KMF_RETURN 2833089Swyllys pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 2843089Swyllys int oclass, char *certlabel, char *issuer, char *subject, 2853089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir, 2863089Swyllys char *prefix, char *filename) 28717Sdinak { 2883089Swyllys KMF_RETURN rv = KMF_OK; 2893089Swyllys KMF_X509_DER_CERT kmfcert; 2905051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 2915051Swyllys KMF_ATTRIBUTE attrlist[16]; 2925051Swyllys int numattr = 0; 2933089Swyllys 2943089Swyllys rv = configure_nss(kmfhandle, dir, prefix); 2953089Swyllys if (rv != KMF_OK) 2963089Swyllys return (rv); 2973089Swyllys 2983089Swyllys /* If searching for public objects or certificates, find certs now */ 2993089Swyllys if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { 3005051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3015051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 3025051Swyllys sizeof (kstype)); 3035051Swyllys numattr++; 3045051Swyllys 3055051Swyllys if (certlabel != NULL) { 3065051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3075051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 3085051Swyllys strlen(certlabel)); 3095051Swyllys numattr++; 3105051Swyllys } 31117Sdinak 3125051Swyllys if (issuer != NULL) { 3135051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3145051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 3155051Swyllys strlen(issuer)); 3165051Swyllys numattr++; 3175051Swyllys } 3185051Swyllys 3195051Swyllys if (subject != NULL) { 3205051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3215051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 3225051Swyllys strlen(subject)); 3235051Swyllys numattr++; 3245051Swyllys } 3255051Swyllys 3265051Swyllys if (serial != NULL) { 3275051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3285051Swyllys KMF_BIGINT_ATTR, serial, 3295051Swyllys sizeof (KMF_BIGINT)); 3305051Swyllys numattr++; 3315051Swyllys } 33217Sdinak 3335051Swyllys if (token_spec != NULL) { 3345051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3355051Swyllys KMF_TOKEN_LABEL_ATTR, token_spec, 3365051Swyllys strlen(token_spec)); 3375051Swyllys numattr++; 3385051Swyllys } 3395051Swyllys 3405051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 3415051Swyllys &kmfcert); 3423089Swyllys if (rv == KMF_OK) { 3435051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 3445051Swyllys numattr = 0; 3455051Swyllys 3465051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3475051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 3485051Swyllys numattr++; 3495051Swyllys 3505051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3515051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 3525051Swyllys sizeof (KMF_DATA)); 3535051Swyllys numattr++; 35417Sdinak 3555051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3565051Swyllys KMF_CERT_FILENAME_ATTR, filename, 3575051Swyllys strlen(filename)); 3585051Swyllys numattr++; 3593089Swyllys 3605051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3615051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 3625051Swyllys numattr++; 3635051Swyllys 3645051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 3655051Swyllys 3665051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 3673089Swyllys } 3683089Swyllys } 3693089Swyllys return (rv); 37017Sdinak } 37117Sdinak 3723089Swyllys static KMF_RETURN 3733089Swyllys pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec, 3743089Swyllys char *certlabel, char *issuer, char *subject, 3753089Swyllys KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename) 37617Sdinak { 3773089Swyllys KMF_RETURN rv = KMF_OK; 3785051Swyllys KMF_KEYSTORE_TYPE kstype; 3795051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 3805051Swyllys KMF_ATTRIBUTE attrlist[16]; 3815051Swyllys int numattr = 0; 38217Sdinak 3833089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 3843089Swyllys if (rv != KMF_OK) { 38517Sdinak return (rv); 38617Sdinak } 38717Sdinak 3885051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 3895051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3905051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 3915051Swyllys numattr++; 3925051Swyllys 3935051Swyllys if (certlabel != NULL) { 3945051Swyllys kmf_set_attr_at_index(attrlist, numattr, 3955051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 3965051Swyllys numattr++; 3975051Swyllys } 3985051Swyllys 3995051Swyllys if (issuer != NULL) { 4005051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4015051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 4025051Swyllys numattr++; 4035051Swyllys } 4045051Swyllys 4055051Swyllys if (subject != NULL) { 4065051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4075051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 4085051Swyllys numattr++; 4095051Swyllys } 4105051Swyllys 4115051Swyllys if (serial != NULL) { 4125051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4135051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 4145051Swyllys numattr++; 4155051Swyllys } 4165051Swyllys 4175051Swyllys if (tokencred != NULL) { 4185051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4195051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 4205051Swyllys numattr++; 4215051Swyllys } 4225051Swyllys 4235051Swyllys (void) get_pk12_password(&p12cred); 4245051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4255051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 4265051Swyllys numattr++; 4275051Swyllys 4285051Swyllys kmf_set_attr_at_index(attrlist, numattr, 4295051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 4305051Swyllys numattr++; 4315051Swyllys 4325051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 4335051Swyllys 4345051Swyllys if (p12cred.cred) 4355051Swyllys free(p12cred.cred); 4365051Swyllys 4375051Swyllys return (rv); 4385051Swyllys } 4395051Swyllys 4405051Swyllys static KMF_RETURN 4415051Swyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token, 4425051Swyllys KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format, 4435637Swyllys char *label, char *filename, int oclass) 4445051Swyllys { 4455051Swyllys KMF_RETURN rv = KMF_OK; 4465051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 4475637Swyllys KMF_KEY_CLASS kclass = KMF_KEYCLASS_NONE; 4485051Swyllys int numattr = 0; 4495051Swyllys uint32_t numkeys = 1; 4505051Swyllys KMF_ATTRIBUTE attrlist[16]; 4515051Swyllys KMF_KEY_HANDLE key; 4525051Swyllys boolean_t is_token = B_TRUE; 4535051Swyllys 4545051Swyllys if (EMPTYSTRING(label)) { 4555051Swyllys cryptoerror(LOG_STDERR, gettext("A label " 4565051Swyllys "must be specified to export a key.")); 4575051Swyllys return (KMF_ERR_BAD_PARAMETER); 4585051Swyllys } 4595051Swyllys 4605051Swyllys rv = select_token(kmfhandle, token, TRUE); 4615051Swyllys if (rv != KMF_OK) { 4625051Swyllys return (rv); 4635051Swyllys } 4645051Swyllys 4655051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 4665051Swyllys &kstype, sizeof (kstype)); 4675051Swyllys numattr++; 46817Sdinak 4695051Swyllys if (cred != NULL) { 4705051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 4715051Swyllys cred, sizeof (KMF_CREDENTIAL)); 4725051Swyllys numattr++; 4735051Swyllys } 4745051Swyllys 4755051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 4765051Swyllys label, strlen(label)); 4775051Swyllys numattr++; 4785051Swyllys 4795051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 4805051Swyllys &numkeys, sizeof (numkeys)); 4815051Swyllys numattr++; 4825051Swyllys 4835051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 4845051Swyllys &key, sizeof (key)); 4855051Swyllys numattr++; 4865051Swyllys 4875051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 4885051Swyllys &is_token, sizeof (is_token)); 4895051Swyllys numattr++; 4905051Swyllys 4915051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 4925051Swyllys &format, sizeof (format)); 4935051Swyllys numattr++; 4945051Swyllys 4955637Swyllys /* Check to see if we are exporting private or public only */ 4965637Swyllys if ((oclass & PK_KEY_OBJ) == PK_PRIKEY_OBJ) 4975637Swyllys kclass = KMF_ASYM_PRI; 4985637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_PUBKEY_OBJ) 4995637Swyllys kclass = KMF_ASYM_PUB; 5005637Swyllys else if ((oclass & PK_KEY_OBJ) == PK_SYMKEY_OBJ) 5015637Swyllys kclass = KMF_SYMMETRIC; 5025637Swyllys else /* only 1 key at a time can be exported here, so default to pri */ 5035637Swyllys kclass = KMF_ASYM_PRI; 5045637Swyllys 5055637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 5065637Swyllys &kclass, sizeof (kclass)); 5075637Swyllys numattr++; 5085637Swyllys 5095051Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5105740Swyllys /* 5115740Swyllys * If nothing found but caller wanted ALL keys, try symmetric 5125740Swyllys * this time. 5135740Swyllys */ 5145740Swyllys if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 5155740Swyllys kclass = KMF_SYMMETRIC; 5165740Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5175740Swyllys } 5185740Swyllys /* 5195740Swyllys * If nothing found but caller wanted ALL keys, try asymmetric 5205740Swyllys * public this time. 5215740Swyllys */ 5225740Swyllys if (rv == KMF_ERR_KEY_NOT_FOUND && (oclass == PK_KEY_OBJ)) { 5235740Swyllys kclass = KMF_ASYM_PUB; 5245740Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 5255740Swyllys } 5265051Swyllys if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 5275051Swyllys KMF_RAW_SYM_KEY rkey; 5285051Swyllys 5295051Swyllys (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 5305051Swyllys rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 5315051Swyllys if (rv == KMF_OK) { 5325051Swyllys int fd, n, total = 0; 53317Sdinak 5345051Swyllys fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 5355051Swyllys if (fd == -1) { 5365051Swyllys rv = KMF_ERR_OPEN_FILE; 5375051Swyllys goto done; 5385051Swyllys } 5395051Swyllys do { 5405051Swyllys n = write(fd, rkey.keydata.val + total, 5415051Swyllys rkey.keydata.len - total); 5425051Swyllys if (n < 0) { 5435051Swyllys if (errno == EINTR) 5445051Swyllys continue; 5455069Swyllys (void) close(fd); 5465051Swyllys rv = KMF_ERR_WRITE_FILE; 5475051Swyllys goto done; 5485051Swyllys } 5495051Swyllys total += n; 55017Sdinak 5515051Swyllys } while (total < rkey.keydata.len); 5525069Swyllys (void) close(fd); 5535051Swyllys } 5545051Swyllys done: 5555051Swyllys kmf_free_bigint(&rkey.keydata); 5565051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5575051Swyllys } else if (rv == KMF_OK) { 5585051Swyllys KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 5595069Swyllys (void) printf(gettext("Found %d asymmetric keys\n"), numkeys); 5605051Swyllys 5615051Swyllys numattr = 0; 5625051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 5635051Swyllys &sslks, sizeof (sslks)); 5645051Swyllys numattr++; 5655051Swyllys 5665051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 5675051Swyllys key.keyp, sizeof (KMF_RAW_KEY_DATA)); 5685051Swyllys numattr++; 5695051Swyllys 5705051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 5715051Swyllys &format, sizeof (format)); 5725051Swyllys numattr++; 5735051Swyllys 5745051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 5755051Swyllys filename, strlen(filename)); 5765051Swyllys numattr++; 5775051Swyllys 5785637Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR, 5795637Swyllys &key.keyclass, sizeof (KMF_KEY_CLASS)); 5805637Swyllys numattr++; 5815637Swyllys 5825051Swyllys rv = kmf_store_key(kmfhandle, numattr, attrlist); 5835051Swyllys kmf_free_kmf_key(kmfhandle, &key); 5845051Swyllys } 58517Sdinak 5863089Swyllys return (rv); 58717Sdinak } 58817Sdinak 5893089Swyllys static KMF_RETURN 5903089Swyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 5913089Swyllys char *certlabel, char *issuer, char *subject, 5923089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 5933089Swyllys char *filename) 59417Sdinak { 5953089Swyllys KMF_RETURN rv = KMF_OK; 5963089Swyllys KMF_X509_DER_CERT kmfcert; 5975051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 5985051Swyllys int numattr = 0; 5995051Swyllys KMF_ATTRIBUTE attrlist[16]; 60017Sdinak 6013089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 60217Sdinak 6033089Swyllys if (rv != KMF_OK) { 60417Sdinak return (rv); 60517Sdinak } 60617Sdinak 6075051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 6085051Swyllys &kstype, sizeof (kstype)); 6095051Swyllys numattr++; 6105051Swyllys 6115051Swyllys if (certlabel != NULL) { 6125051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6135051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 6145051Swyllys strlen(certlabel)); 6155051Swyllys numattr++; 6165051Swyllys } 61717Sdinak 6185051Swyllys if (issuer != NULL) { 6195051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6205051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 6215051Swyllys strlen(issuer)); 6225051Swyllys numattr++; 6235051Swyllys } 6245051Swyllys 6255051Swyllys if (subject != NULL) { 6265051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6275051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 6285051Swyllys strlen(subject)); 6295051Swyllys numattr++; 6305051Swyllys } 6315051Swyllys 6325051Swyllys if (serial != NULL) { 6335051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6345051Swyllys KMF_BIGINT_ATTR, serial, 6355051Swyllys sizeof (KMF_BIGINT)); 6365051Swyllys numattr++; 6375051Swyllys } 6385051Swyllys 6395051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert); 64017Sdinak 6413089Swyllys if (rv == KMF_OK) { 6425051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 6435051Swyllys numattr = 0; 6445051Swyllys 6455051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6465051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 6475051Swyllys numattr++; 6485051Swyllys 6495051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6505051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 6515051Swyllys sizeof (KMF_DATA)); 6525051Swyllys numattr++; 65317Sdinak 6545051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6555051Swyllys KMF_CERT_FILENAME_ATTR, filename, strlen(filename)); 6565051Swyllys numattr++; 65717Sdinak 6585051Swyllys kmf_set_attr_at_index(attrlist, numattr, 6595051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 6605051Swyllys numattr++; 6615051Swyllys 6625051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 6635051Swyllys 6645051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 66517Sdinak } 6663089Swyllys return (rv); 66717Sdinak } 66817Sdinak 66917Sdinak /* 6703089Swyllys * Export objects from one keystore to a file. 67117Sdinak */ 67217Sdinak int 67317Sdinak pk_export(int argc, char *argv[]) 67417Sdinak { 675864Sdinak int opt; 676864Sdinak extern int optind_av; 677864Sdinak extern char *optarg_av; 678864Sdinak char *token_spec = NULL; 67917Sdinak char *filename = NULL; 6803089Swyllys char *dir = NULL; 6813089Swyllys char *prefix = NULL; 6823089Swyllys char *certlabel = NULL; 6833089Swyllys char *subject = NULL; 6843089Swyllys char *issuer = NULL; 6853089Swyllys char *infile = NULL; 6863089Swyllys char *keyfile = NULL; 6873089Swyllys char *certfile = NULL; 6883089Swyllys char *serstr = NULL; 6893089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 6903089Swyllys KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; 6913089Swyllys KMF_RETURN rv = KMF_OK; 6923089Swyllys int oclass = PK_CERT_OBJ; 6933089Swyllys KMF_BIGINT serial = { NULL, 0 }; 6943089Swyllys KMF_HANDLE_T kmfhandle = NULL; 6953089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 69617Sdinak 697864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 6983089Swyllys while ((opt = getopt_av(argc, argv, 6995051Swyllys "k:(keystore)y:(objtype)T:(token)" 7005051Swyllys "d:(dir)p:(prefix)" 7015051Swyllys "l:(label)n:(nickname)s:(subject)" 7025051Swyllys "i:(issuer)S:(serial)" 7035051Swyllys "K:(keyfile)c:(certfile)" 7045051Swyllys "F:(outformat)" 7055051Swyllys "I:(infile)o:(outfile)")) != EOF) { 7063089Swyllys if (EMPTYSTRING(optarg_av)) 7073089Swyllys return (PK_ERR_USAGE); 708864Sdinak switch (opt) { 7093089Swyllys case 'k': 7103089Swyllys kstype = KS2Int(optarg_av); 7113089Swyllys if (kstype == 0) 7123089Swyllys return (PK_ERR_USAGE); 7133089Swyllys break; 7143089Swyllys case 'y': 7153089Swyllys oclass = OT2Int(optarg_av); 7163089Swyllys if (oclass == -1) 7173089Swyllys return (PK_ERR_USAGE); 7183089Swyllys break; 719864Sdinak case 'T': /* token specifier */ 720864Sdinak if (token_spec) 721864Sdinak return (PK_ERR_USAGE); 722864Sdinak token_spec = optarg_av; 723864Sdinak break; 7243089Swyllys case 'd': 7253089Swyllys if (dir) 7263089Swyllys return (PK_ERR_USAGE); 7273089Swyllys dir = optarg_av; 7283089Swyllys break; 7293089Swyllys case 'p': 7303089Swyllys if (prefix) 7313089Swyllys return (PK_ERR_USAGE); 7323089Swyllys prefix = optarg_av; 7333089Swyllys break; 7343089Swyllys case 'n': 7353089Swyllys case 'l': 7363089Swyllys if (certlabel) 7373089Swyllys return (PK_ERR_USAGE); 7383089Swyllys certlabel = optarg_av; 7393089Swyllys break; 7403089Swyllys case 's': 7413089Swyllys if (subject) 7423089Swyllys return (PK_ERR_USAGE); 7433089Swyllys subject = optarg_av; 7443089Swyllys break; 7453089Swyllys case 'i': 7463089Swyllys if (issuer) 7473089Swyllys return (PK_ERR_USAGE); 7483089Swyllys issuer = optarg_av; 7493089Swyllys break; 7503089Swyllys case 'S': 7513089Swyllys serstr = optarg_av; 7523089Swyllys break; 7533089Swyllys case 'F': 7543089Swyllys kfmt = Str2Format(optarg_av); 7553089Swyllys if (kfmt == KMF_FORMAT_UNDEF) 7563089Swyllys return (PK_ERR_USAGE); 7573089Swyllys break; 7583089Swyllys case 'I': /* output file name */ 7593089Swyllys if (infile) 7603089Swyllys return (PK_ERR_USAGE); 7613089Swyllys infile = optarg_av; 7623089Swyllys break; 763864Sdinak case 'o': /* output file name */ 764864Sdinak if (filename) 765864Sdinak return (PK_ERR_USAGE); 766864Sdinak filename = optarg_av; 767864Sdinak break; 7683089Swyllys case 'c': /* input cert file name */ 7693089Swyllys if (certfile) 7703089Swyllys return (PK_ERR_USAGE); 7713089Swyllys certfile = optarg_av; 7723089Swyllys break; 7733089Swyllys case 'K': /* input key file name */ 7743089Swyllys if (keyfile) 7753089Swyllys return (PK_ERR_USAGE); 7763089Swyllys keyfile = optarg_av; 7773089Swyllys break; 778864Sdinak default: 779864Sdinak return (PK_ERR_USAGE); 780864Sdinak break; 781864Sdinak } 782864Sdinak } 78317Sdinak 7843089Swyllys /* Assume keystore = PKCS#11 if not specified */ 7853089Swyllys if (kstype == 0) 7863089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 787864Sdinak 788864Sdinak /* Filename arg is required. */ 7893089Swyllys if (EMPTYSTRING(filename)) { 7903089Swyllys cryptoerror(LOG_STDERR, gettext("You must specify " 7915051Swyllys "an 'outfile' parameter when exporting.\n")); 79217Sdinak return (PK_ERR_USAGE); 7933089Swyllys } 79417Sdinak 795864Sdinak /* No additional args allowed. */ 796864Sdinak argc -= optind_av; 797864Sdinak argv += optind_av; 798864Sdinak if (argc) 799864Sdinak return (PK_ERR_USAGE); 8003089Swyllys 801*6884Swyllys DIR_OPTION_CHECK(kstype, dir); 802*6884Swyllys 8033089Swyllys /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 8043089Swyllys if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 8055051Swyllys kstype != KMF_KEYSTORE_PK11TOKEN) { 8063089Swyllys 8073089Swyllys (void) fprintf(stderr, gettext("The objtype parameter " 8085051Swyllys "is only relevant if keystore=pkcs11\n")); 8093089Swyllys return (PK_ERR_USAGE); 8103089Swyllys } 8113089Swyllys 8123089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 8133089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 8143089Swyllys else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 8153089Swyllys token_spec = DEFAULT_NSS_TOKEN; 8163089Swyllys 8173089Swyllys if (kstype == KMF_KEYSTORE_OPENSSL) { 8183089Swyllys if (kfmt != KMF_FORMAT_PKCS12) { 8193089Swyllys cryptoerror(LOG_STDERR, gettext("PKCS12 " 8205051Swyllys "is the only export format " 8215051Swyllys "supported for the 'file' " 8225051Swyllys "keystore.\n")); 8233089Swyllys return (PK_ERR_USAGE); 8243089Swyllys } 8253089Swyllys if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 8263089Swyllys cryptoerror(LOG_STDERR, gettext("A cert file" 8275051Swyllys "and a key file must be specified " 8285051Swyllys "when exporting to PKCS12 from the " 8295051Swyllys "'file' keystore.\n")); 8303089Swyllys return (PK_ERR_USAGE); 8313089Swyllys } 8323089Swyllys } 83317Sdinak 83417Sdinak /* Check if the file exists and might be overwritten. */ 83517Sdinak if (access(filename, F_OK) == 0) { 8363089Swyllys cryptoerror(LOG_STDERR, 8375051Swyllys gettext("Warning: file \"%s\" exists, " 8385051Swyllys "will be overwritten."), filename); 83917Sdinak if (yesno(gettext("Continue with export? "), 84017Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 84117Sdinak return (0); 8425637Swyllys } else { 8435637Swyllys /* remove the file */ 8445637Swyllys (void) unlink(filename); 84517Sdinak } 8463089Swyllys } else { 8473089Swyllys rv = verify_file(filename); 8483089Swyllys if (rv != KMF_OK) { 8493089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 8505051Swyllys "cannot be created.\n"), filename); 8513089Swyllys return (PK_ERR_USAGE); 8523089Swyllys } 85317Sdinak } 85417Sdinak 8553089Swyllys if (serstr != NULL) { 8563089Swyllys uchar_t *bytes = NULL; 8573089Swyllys size_t bytelen; 85817Sdinak 8595051Swyllys rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 8603089Swyllys if (rv != KMF_OK || bytes == NULL) { 8613089Swyllys (void) fprintf(stderr, gettext("serial number " 8625051Swyllys "must be specified as a hex number " 8635051Swyllys "(ex: 0x0102030405ffeeddee)\n")); 8643089Swyllys return (PK_ERR_USAGE); 8653089Swyllys } 8663089Swyllys serial.val = bytes; 8673089Swyllys serial.len = bytelen; 86817Sdinak } 86917Sdinak 8703089Swyllys if ((kstype == KMF_KEYSTORE_PK11TOKEN || 8715051Swyllys kstype == KMF_KEYSTORE_NSS) && 8725051Swyllys (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || 8735051Swyllys kfmt == KMF_FORMAT_PKCS12)) { 8743089Swyllys (void) get_token_password(kstype, token_spec, 8755051Swyllys &tokencred); 87617Sdinak } 87717Sdinak 8785051Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 8793089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing " 8805051Swyllys "KMF: 0x%02x\n"), rv); 8813089Swyllys return (rv); 88217Sdinak } 88317Sdinak 8843089Swyllys switch (kstype) { 8853089Swyllys case KMF_KEYSTORE_PK11TOKEN: 8863089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8875051Swyllys rv = pk_export_pk12_pk11(kmfhandle, 8885051Swyllys token_spec, certlabel, 8895051Swyllys issuer, subject, 8905051Swyllys &serial, &tokencred, 8915051Swyllys filename); 8925051Swyllys else if ((oclass & PK_KEY_OBJ) || 8935051Swyllys kfmt == KMF_FORMAT_RAWKEY) 8945051Swyllys rv = pk_export_pk11_keys(kmfhandle, 8955051Swyllys token_spec, &tokencred, kfmt, 8965637Swyllys certlabel, filename, oclass); 8973089Swyllys else 8983089Swyllys rv = pk_export_pk11_objects(kmfhandle, 8995051Swyllys token_spec, certlabel, 9005051Swyllys issuer, subject, &serial, kfmt, 9015051Swyllys filename); 9023089Swyllys break; 9033089Swyllys case KMF_KEYSTORE_NSS: 9043089Swyllys if (dir == NULL) 9053089Swyllys dir = PK_DEFAULT_DIRECTORY; 9063089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9073089Swyllys rv = pk_export_pk12_nss(kmfhandle, 9085051Swyllys token_spec, dir, prefix, 9095051Swyllys certlabel, issuer, 9105051Swyllys subject, &serial, 9115051Swyllys &tokencred, filename); 9123089Swyllys else 9133089Swyllys rv = pk_export_nss_objects(kmfhandle, 9145051Swyllys token_spec, 9155051Swyllys oclass, certlabel, issuer, subject, 9165051Swyllys &serial, kfmt, dir, prefix, filename); 9173089Swyllys break; 9183089Swyllys case KMF_KEYSTORE_OPENSSL: 9193089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 9203089Swyllys rv = pk_export_pk12_files(kmfhandle, 9216669Swyllys certfile, keyfile, filename); 9223089Swyllys else 9233089Swyllys rv = pk_export_file_objects(kmfhandle, oclass, 9245051Swyllys issuer, subject, &serial, 9256669Swyllys infile, filename); 9263089Swyllys break; 9273089Swyllys default: 9283089Swyllys rv = PK_ERR_USAGE; 9293089Swyllys break; 93017Sdinak } 93117Sdinak 9323089Swyllys if (rv != KMF_OK) { 9333089Swyllys display_error(kmfhandle, rv, 9345051Swyllys gettext("Error exporting objects")); 9353089Swyllys } 93617Sdinak 9373089Swyllys if (serial.val != NULL) 9383089Swyllys free(serial.val); 93917Sdinak 9405051Swyllys (void) kmf_finalize(kmfhandle); 9413089Swyllys 9423089Swyllys return (rv); 94317Sdinak } 944