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*5051Swyllys * 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 47*5051Swyllys pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_ATTRIBUTE *attrlist, 48*5051Swyllys 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)); 55*5051Swyllys 56*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 57*5051Swyllys &numcerts, sizeof (uint32_t)); 58*5051Swyllys numattr++; 59*5051Swyllys 60*5051Swyllys rv = kmf_find_cert(kmfhandle, numattr, attrlist); 613089Swyllys if (rv != KMF_OK) { 623089Swyllys return (rv); 6317Sdinak } 643089Swyllys if (numcerts == 0) { 653089Swyllys cryptoerror(LOG_STDERR, 66*5051Swyllys gettext("No matching certificates found.")); 673089Swyllys return (KMF_ERR_CERT_NOT_FOUND); 6817Sdinak 693089Swyllys } else if (numcerts == 1) { 70*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 71*5051Swyllys KMF_X509_DER_CERT_ATTR, cert, 72*5051Swyllys sizeof (KMF_X509_DER_CERT)); 73*5051Swyllys numattr++; 74*5051Swyllys rv = kmf_find_cert(kmfhandle, numattr, attrlist); 7517Sdinak 763089Swyllys } else if (numcerts > 1) { 773089Swyllys cryptoerror(LOG_STDERR, 78*5051Swyllys gettext("%d certificates found, refine the " 79*5051Swyllys "search parameters to eliminate ambiguity\n"), 80*5051Swyllys 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; 93*5051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL; 94*5051Swyllys int numattr = 0; 95*5051Swyllys 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)) { 99*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 100*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 101*5051Swyllys sizeof (kstype)); 102*5051Swyllys numattr++; 103*5051Swyllys 104*5051Swyllys if (issuer != NULL) { 105*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 106*5051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 107*5051Swyllys strlen(issuer)); 108*5051Swyllys numattr++; 109*5051Swyllys } 110*5051Swyllys 111*5051Swyllys if (subject != NULL) { 112*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 113*5051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 114*5051Swyllys strlen(subject)); 115*5051Swyllys numattr++; 116*5051Swyllys } 117*5051Swyllys 118*5051Swyllys if (serial != NULL) { 119*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 120*5051Swyllys KMF_BIGINT_ATTR, serial, 121*5051Swyllys sizeof (KMF_BIGINT)); 122*5051Swyllys numattr++; 123*5051Swyllys } 12417Sdinak 125*5051Swyllys if (dir != NULL) { 126*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 127*5051Swyllys KMF_DIRPATH_ATTR, dir, 128*5051Swyllys strlen(dir)); 129*5051Swyllys numattr++; 130*5051Swyllys } 131*5051Swyllys 132*5051Swyllys if (infile != NULL) { 133*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 134*5051Swyllys KMF_CERT_FILENAME_ATTR, infile, 135*5051Swyllys strlen(infile)); 136*5051Swyllys numattr++; 137*5051Swyllys } 13817Sdinak 139*5051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 140*5051Swyllys &kmfcert); 1413089Swyllys if (rv == KMF_OK) { 142*5051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 143*5051Swyllys numattr = 0; 144*5051Swyllys 145*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 146*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 147*5051Swyllys numattr++; 14817Sdinak 149*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 150*5051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 151*5051Swyllys sizeof (KMF_DATA)); 152*5051Swyllys numattr++; 153*5051Swyllys 154*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 155*5051Swyllys KMF_CERT_FILENAME_ATTR, filename, 156*5051Swyllys strlen(filename)); 157*5051Swyllys numattr++; 158*5051Swyllys 159*5051Swyllys rv = kmf_store_cert(kmfhandle, numattr, 160*5051Swyllys attrlist); 161*5051Swyllys 162*5051Swyllys 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; 176*5051Swyllys KMF_KEYSTORE_TYPE kstype; 177*5051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 178*5051Swyllys KMF_ATTRIBUTE attrlist[16]; 179*5051Swyllys 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 188*5051Swyllys kstype = KMF_KEYSTORE_NSS; 189*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 190*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 191*5051Swyllys numattr++; 192*5051Swyllys 193*5051Swyllys if (certlabel != NULL) { 194*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 195*5051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 196*5051Swyllys numattr++; 197*5051Swyllys } 198*5051Swyllys 199*5051Swyllys if (issuer != NULL) { 200*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 201*5051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 202*5051Swyllys numattr++; 203*5051Swyllys } 204*5051Swyllys 205*5051Swyllys if (subject != NULL) { 206*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 207*5051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 208*5051Swyllys numattr++; 209*5051Swyllys } 21017Sdinak 211*5051Swyllys if (serial != NULL) { 212*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 213*5051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 214*5051Swyllys numattr++; 215*5051Swyllys } 216*5051Swyllys 217*5051Swyllys if (tokencred != NULL) { 218*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 219*5051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 220*5051Swyllys numattr++; 221*5051Swyllys } 22217Sdinak 223*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_LABEL_ATTR, 224*5051Swyllys token_spec, strlen(token_spec)); 225*5051Swyllys numattr++; 226*5051Swyllys 227*5051Swyllys (void) get_pk12_password(&p12cred); 228*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 229*5051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 230*5051Swyllys numattr++; 231*5051Swyllys 232*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 233*5051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 234*5051Swyllys numattr++; 235*5051Swyllys 236*5051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 237*5051Swyllys 238*5051Swyllys if (p12cred.cred) 239*5051Swyllys 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; 250*5051Swyllys KMF_KEYSTORE_TYPE kstype; 251*5051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 252*5051Swyllys KMF_ATTRIBUTE attrlist[16]; 253*5051Swyllys int numattr = 0; 25417Sdinak 255*5051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 256*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 257*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 258*5051Swyllys numattr++; 259*5051Swyllys 260*5051Swyllys if (dir != NULL) { 261*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 262*5051Swyllys KMF_DIRPATH_ATTR, dir, strlen(dir)); 263*5051Swyllys numattr++; 264*5051Swyllys } 26517Sdinak 266*5051Swyllys if (certfile != NULL) { 267*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 268*5051Swyllys KMF_CERT_FILENAME_ATTR, certfile, strlen(certfile)); 269*5051Swyllys numattr++; 270*5051Swyllys } 271*5051Swyllys 272*5051Swyllys if (keyfile != NULL) { 273*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 274*5051Swyllys KMF_KEY_FILENAME_ATTR, keyfile, strlen(keyfile)); 275*5051Swyllys numattr++; 276*5051Swyllys } 27717Sdinak 278*5051Swyllys (void) get_pk12_password(&p12cred); 279*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 280*5051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 281*5051Swyllys numattr++; 28217Sdinak 283*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 284*5051Swyllys KMF_OUTPUT_FILENAME_ATTR, outfile, strlen(outfile)); 285*5051Swyllys numattr++; 28617Sdinak 287*5051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 288*5051Swyllys 289*5051Swyllys if (p12cred.cred) 290*5051Swyllys 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; 303*5051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_NSS; 304*5051Swyllys KMF_ATTRIBUTE attrlist[16]; 305*5051Swyllys 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)) { 313*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 314*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, 315*5051Swyllys sizeof (kstype)); 316*5051Swyllys numattr++; 317*5051Swyllys 318*5051Swyllys if (certlabel != NULL) { 319*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 320*5051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 321*5051Swyllys strlen(certlabel)); 322*5051Swyllys numattr++; 323*5051Swyllys } 32417Sdinak 325*5051Swyllys if (issuer != NULL) { 326*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 327*5051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 328*5051Swyllys strlen(issuer)); 329*5051Swyllys numattr++; 330*5051Swyllys } 331*5051Swyllys 332*5051Swyllys if (subject != NULL) { 333*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 334*5051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 335*5051Swyllys strlen(subject)); 336*5051Swyllys numattr++; 337*5051Swyllys } 338*5051Swyllys 339*5051Swyllys if (serial != NULL) { 340*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 341*5051Swyllys KMF_BIGINT_ATTR, serial, 342*5051Swyllys sizeof (KMF_BIGINT)); 343*5051Swyllys numattr++; 344*5051Swyllys } 34517Sdinak 346*5051Swyllys if (token_spec != NULL) { 347*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 348*5051Swyllys KMF_TOKEN_LABEL_ATTR, token_spec, 349*5051Swyllys strlen(token_spec)); 350*5051Swyllys numattr++; 351*5051Swyllys } 352*5051Swyllys 353*5051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, 354*5051Swyllys &kmfcert); 3553089Swyllys if (rv == KMF_OK) { 356*5051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 357*5051Swyllys numattr = 0; 358*5051Swyllys 359*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 360*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 361*5051Swyllys numattr++; 362*5051Swyllys 363*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 364*5051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 365*5051Swyllys sizeof (KMF_DATA)); 366*5051Swyllys numattr++; 36717Sdinak 368*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 369*5051Swyllys KMF_CERT_FILENAME_ATTR, filename, 370*5051Swyllys strlen(filename)); 371*5051Swyllys numattr++; 3723089Swyllys 373*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 374*5051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 375*5051Swyllys numattr++; 376*5051Swyllys 377*5051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 378*5051Swyllys 379*5051Swyllys 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; 391*5051Swyllys KMF_KEYSTORE_TYPE kstype; 392*5051Swyllys KMF_CREDENTIAL p12cred = { NULL, 0}; 393*5051Swyllys KMF_ATTRIBUTE attrlist[16]; 394*5051Swyllys int numattr = 0; 39517Sdinak 3963089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 3973089Swyllys if (rv != KMF_OK) { 39817Sdinak return (rv); 39917Sdinak } 40017Sdinak 401*5051Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 402*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 403*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 404*5051Swyllys numattr++; 405*5051Swyllys 406*5051Swyllys if (certlabel != NULL) { 407*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 408*5051Swyllys KMF_CERT_LABEL_ATTR, certlabel, strlen(certlabel)); 409*5051Swyllys numattr++; 410*5051Swyllys } 411*5051Swyllys 412*5051Swyllys if (issuer != NULL) { 413*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 414*5051Swyllys KMF_ISSUER_NAME_ATTR, issuer, strlen(issuer)); 415*5051Swyllys numattr++; 416*5051Swyllys } 417*5051Swyllys 418*5051Swyllys if (subject != NULL) { 419*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 420*5051Swyllys KMF_SUBJECT_NAME_ATTR, subject, strlen(subject)); 421*5051Swyllys numattr++; 422*5051Swyllys } 423*5051Swyllys 424*5051Swyllys if (serial != NULL) { 425*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 426*5051Swyllys KMF_BIGINT_ATTR, serial, sizeof (KMF_BIGINT)); 427*5051Swyllys numattr++; 428*5051Swyllys } 429*5051Swyllys 430*5051Swyllys if (tokencred != NULL) { 431*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 432*5051Swyllys KMF_CREDENTIAL_ATTR, tokencred, sizeof (KMF_CREDENTIAL)); 433*5051Swyllys numattr++; 434*5051Swyllys } 435*5051Swyllys 436*5051Swyllys (void) get_pk12_password(&p12cred); 437*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 438*5051Swyllys KMF_PK12CRED_ATTR, &p12cred, sizeof (KMF_CREDENTIAL)); 439*5051Swyllys numattr++; 440*5051Swyllys 441*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 442*5051Swyllys KMF_OUTPUT_FILENAME_ATTR, filename, strlen(filename)); 443*5051Swyllys numattr++; 444*5051Swyllys 445*5051Swyllys rv = kmf_export_pk12(kmfhandle, numattr, attrlist); 446*5051Swyllys 447*5051Swyllys if (p12cred.cred) 448*5051Swyllys free(p12cred.cred); 449*5051Swyllys 450*5051Swyllys return (rv); 451*5051Swyllys } 452*5051Swyllys 453*5051Swyllys static KMF_RETURN 454*5051Swyllys pk_export_pk11_keys(KMF_HANDLE_T kmfhandle, char *token, 455*5051Swyllys KMF_CREDENTIAL *cred, KMF_ENCODE_FORMAT format, 456*5051Swyllys char *label, char *filename) 457*5051Swyllys { 458*5051Swyllys KMF_RETURN rv = KMF_OK; 459*5051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 460*5051Swyllys int numattr = 0; 461*5051Swyllys uint32_t numkeys = 1; 462*5051Swyllys KMF_ATTRIBUTE attrlist[16]; 463*5051Swyllys KMF_KEY_HANDLE key; 464*5051Swyllys KMF_KEY_CLASS keyclass = KMF_SYMMETRIC; 465*5051Swyllys boolean_t is_token = B_TRUE; 466*5051Swyllys 467*5051Swyllys if (EMPTYSTRING(label)) { 468*5051Swyllys cryptoerror(LOG_STDERR, gettext("A label " 469*5051Swyllys "must be specified to export a key.")); 470*5051Swyllys return (KMF_ERR_BAD_PARAMETER); 471*5051Swyllys } 472*5051Swyllys 473*5051Swyllys rv = select_token(kmfhandle, token, TRUE); 474*5051Swyllys if (rv != KMF_OK) { 475*5051Swyllys return (rv); 476*5051Swyllys } 477*5051Swyllys 478*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 479*5051Swyllys &kstype, sizeof (kstype)); 480*5051Swyllys numattr++; 48117Sdinak 482*5051Swyllys if (cred != NULL) { 483*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR, 484*5051Swyllys cred, sizeof (KMF_CREDENTIAL)); 485*5051Swyllys numattr++; 486*5051Swyllys } 487*5051Swyllys 488*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR, 489*5051Swyllys label, strlen(label)); 490*5051Swyllys numattr++; 491*5051Swyllys 492*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR, 493*5051Swyllys &numkeys, sizeof (numkeys)); 494*5051Swyllys numattr++; 495*5051Swyllys 496*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR, 497*5051Swyllys &key, sizeof (key)); 498*5051Swyllys numattr++; 499*5051Swyllys 500*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR, 501*5051Swyllys &is_token, sizeof (is_token)); 502*5051Swyllys numattr++; 503*5051Swyllys 504*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 505*5051Swyllys &format, sizeof (format)); 506*5051Swyllys numattr++; 507*5051Swyllys 508*5051Swyllys rv = kmf_find_key(kmfhandle, numattr, attrlist); 509*5051Swyllys if (rv == KMF_OK && key.keyclass == KMF_SYMMETRIC) { 510*5051Swyllys KMF_RAW_SYM_KEY rkey; 511*5051Swyllys 512*5051Swyllys (void) memset(&rkey, 0, sizeof (KMF_RAW_SYM_KEY)); 513*5051Swyllys rv = kmf_get_sym_key_value(kmfhandle, &key, &rkey); 514*5051Swyllys if (rv == KMF_OK) { 515*5051Swyllys int fd, n, total = 0; 51617Sdinak 517*5051Swyllys fd = open(filename, O_CREAT | O_RDWR |O_TRUNC, 0600); 518*5051Swyllys if (fd == -1) { 519*5051Swyllys rv = KMF_ERR_OPEN_FILE; 520*5051Swyllys goto done; 521*5051Swyllys } 522*5051Swyllys do { 523*5051Swyllys n = write(fd, rkey.keydata.val + total, 524*5051Swyllys rkey.keydata.len - total); 525*5051Swyllys if (n < 0) { 526*5051Swyllys if (errno == EINTR) 527*5051Swyllys continue; 528*5051Swyllys close(fd); 529*5051Swyllys rv = KMF_ERR_WRITE_FILE; 530*5051Swyllys goto done; 531*5051Swyllys } 532*5051Swyllys total += n; 53317Sdinak 534*5051Swyllys } while (total < rkey.keydata.len); 535*5051Swyllys close(fd); 536*5051Swyllys } 537*5051Swyllys done: 538*5051Swyllys kmf_free_bigint(&rkey.keydata); 539*5051Swyllys kmf_free_kmf_key(kmfhandle, &key); 540*5051Swyllys } else if (rv == KMF_OK) { 541*5051Swyllys KMF_KEYSTORE_TYPE sslks = KMF_KEYSTORE_OPENSSL; 542*5051Swyllys printf(gettext("Found %d asymmetric keys\n"), numkeys); 543*5051Swyllys 544*5051Swyllys numattr = 0; 545*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 546*5051Swyllys &sslks, sizeof (sslks)); 547*5051Swyllys numattr++; 548*5051Swyllys 549*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_RAW_KEY_ATTR, 550*5051Swyllys key.keyp, sizeof (KMF_RAW_KEY_DATA)); 551*5051Swyllys numattr++; 552*5051Swyllys 553*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR, 554*5051Swyllys &format, sizeof (format)); 555*5051Swyllys numattr++; 556*5051Swyllys 557*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_FILENAME_ATTR, 558*5051Swyllys filename, strlen(filename)); 559*5051Swyllys numattr++; 560*5051Swyllys 561*5051Swyllys rv = kmf_store_key(kmfhandle, numattr, attrlist); 562*5051Swyllys kmf_free_kmf_key(kmfhandle, &key); 563*5051Swyllys } 56417Sdinak 5653089Swyllys return (rv); 56617Sdinak } 56717Sdinak 5683089Swyllys static KMF_RETURN 5693089Swyllys pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, 5703089Swyllys char *certlabel, char *issuer, char *subject, 5713089Swyllys KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, 5723089Swyllys char *filename) 57317Sdinak { 5743089Swyllys KMF_RETURN rv = KMF_OK; 5753089Swyllys KMF_X509_DER_CERT kmfcert; 576*5051Swyllys KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_PK11TOKEN; 577*5051Swyllys int numattr = 0; 578*5051Swyllys KMF_ATTRIBUTE attrlist[16]; 57917Sdinak 5803089Swyllys rv = select_token(kmfhandle, token_spec, TRUE); 58117Sdinak 5823089Swyllys if (rv != KMF_OK) { 58317Sdinak return (rv); 58417Sdinak } 58517Sdinak 586*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR, 587*5051Swyllys &kstype, sizeof (kstype)); 588*5051Swyllys numattr++; 589*5051Swyllys 590*5051Swyllys if (certlabel != NULL) { 591*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 592*5051Swyllys KMF_CERT_LABEL_ATTR, certlabel, 593*5051Swyllys strlen(certlabel)); 594*5051Swyllys numattr++; 595*5051Swyllys } 59617Sdinak 597*5051Swyllys if (issuer != NULL) { 598*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 599*5051Swyllys KMF_ISSUER_NAME_ATTR, issuer, 600*5051Swyllys strlen(issuer)); 601*5051Swyllys numattr++; 602*5051Swyllys } 603*5051Swyllys 604*5051Swyllys if (subject != NULL) { 605*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 606*5051Swyllys KMF_SUBJECT_NAME_ATTR, subject, 607*5051Swyllys strlen(subject)); 608*5051Swyllys numattr++; 609*5051Swyllys } 610*5051Swyllys 611*5051Swyllys if (serial != NULL) { 612*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 613*5051Swyllys KMF_BIGINT_ATTR, serial, 614*5051Swyllys sizeof (KMF_BIGINT)); 615*5051Swyllys numattr++; 616*5051Swyllys } 617*5051Swyllys 618*5051Swyllys rv = pk_find_export_cert(kmfhandle, attrlist, numattr, &kmfcert); 61917Sdinak 6203089Swyllys if (rv == KMF_OK) { 621*5051Swyllys kstype = KMF_KEYSTORE_OPENSSL; 622*5051Swyllys numattr = 0; 623*5051Swyllys 624*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 625*5051Swyllys KMF_KEYSTORE_TYPE_ATTR, &kstype, sizeof (kstype)); 626*5051Swyllys numattr++; 627*5051Swyllys 628*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 629*5051Swyllys KMF_CERT_DATA_ATTR, &kmfcert.certificate, 630*5051Swyllys sizeof (KMF_DATA)); 631*5051Swyllys numattr++; 63217Sdinak 633*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 634*5051Swyllys KMF_CERT_FILENAME_ATTR, filename, strlen(filename)); 635*5051Swyllys numattr++; 63617Sdinak 637*5051Swyllys kmf_set_attr_at_index(attrlist, numattr, 638*5051Swyllys KMF_ENCODE_FORMAT_ATTR, &kfmt, sizeof (kfmt)); 639*5051Swyllys numattr++; 640*5051Swyllys 641*5051Swyllys rv = kmf_store_cert(kmfhandle, numattr, attrlist); 642*5051Swyllys 643*5051Swyllys kmf_free_kmf_cert(kmfhandle, &kmfcert); 64417Sdinak } 6453089Swyllys return (rv); 64617Sdinak } 64717Sdinak 64817Sdinak /* 6493089Swyllys * Export objects from one keystore to a file. 65017Sdinak */ 65117Sdinak int 65217Sdinak pk_export(int argc, char *argv[]) 65317Sdinak { 654864Sdinak int opt; 655864Sdinak extern int optind_av; 656864Sdinak extern char *optarg_av; 657864Sdinak char *token_spec = NULL; 65817Sdinak char *filename = NULL; 6593089Swyllys char *dir = NULL; 6603089Swyllys char *prefix = NULL; 6613089Swyllys char *certlabel = NULL; 6623089Swyllys char *subject = NULL; 6633089Swyllys char *issuer = NULL; 6643089Swyllys char *infile = NULL; 6653089Swyllys char *keyfile = NULL; 6663089Swyllys char *certfile = NULL; 6673089Swyllys char *serstr = NULL; 6683089Swyllys KMF_KEYSTORE_TYPE kstype = 0; 6693089Swyllys KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; 6703089Swyllys KMF_RETURN rv = KMF_OK; 6713089Swyllys int oclass = PK_CERT_OBJ; 6723089Swyllys KMF_BIGINT serial = { NULL, 0 }; 6733089Swyllys KMF_HANDLE_T kmfhandle = NULL; 6743089Swyllys KMF_CREDENTIAL tokencred = {NULL, 0}; 67517Sdinak 676864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 6773089Swyllys while ((opt = getopt_av(argc, argv, 678*5051Swyllys "k:(keystore)y:(objtype)T:(token)" 679*5051Swyllys "d:(dir)p:(prefix)" 680*5051Swyllys "l:(label)n:(nickname)s:(subject)" 681*5051Swyllys "i:(issuer)S:(serial)" 682*5051Swyllys "K:(keyfile)c:(certfile)" 683*5051Swyllys "F:(outformat)" 684*5051Swyllys "I:(infile)o:(outfile)")) != EOF) { 6853089Swyllys if (EMPTYSTRING(optarg_av)) 6863089Swyllys return (PK_ERR_USAGE); 687864Sdinak switch (opt) { 6883089Swyllys case 'k': 6893089Swyllys kstype = KS2Int(optarg_av); 6903089Swyllys if (kstype == 0) 6913089Swyllys return (PK_ERR_USAGE); 6923089Swyllys break; 6933089Swyllys case 'y': 6943089Swyllys oclass = OT2Int(optarg_av); 6953089Swyllys if (oclass == -1) 6963089Swyllys return (PK_ERR_USAGE); 6973089Swyllys break; 698864Sdinak case 'T': /* token specifier */ 699864Sdinak if (token_spec) 700864Sdinak return (PK_ERR_USAGE); 701864Sdinak token_spec = optarg_av; 702864Sdinak break; 7033089Swyllys case 'd': 7043089Swyllys if (dir) 7053089Swyllys return (PK_ERR_USAGE); 7063089Swyllys dir = optarg_av; 7073089Swyllys break; 7083089Swyllys case 'p': 7093089Swyllys if (prefix) 7103089Swyllys return (PK_ERR_USAGE); 7113089Swyllys prefix = optarg_av; 7123089Swyllys break; 7133089Swyllys case 'n': 7143089Swyllys case 'l': 7153089Swyllys if (certlabel) 7163089Swyllys return (PK_ERR_USAGE); 7173089Swyllys certlabel = optarg_av; 7183089Swyllys break; 7193089Swyllys case 's': 7203089Swyllys if (subject) 7213089Swyllys return (PK_ERR_USAGE); 7223089Swyllys subject = optarg_av; 7233089Swyllys break; 7243089Swyllys case 'i': 7253089Swyllys if (issuer) 7263089Swyllys return (PK_ERR_USAGE); 7273089Swyllys issuer = optarg_av; 7283089Swyllys break; 7293089Swyllys case 'S': 7303089Swyllys serstr = optarg_av; 7313089Swyllys break; 7323089Swyllys case 'F': 7333089Swyllys kfmt = Str2Format(optarg_av); 7343089Swyllys if (kfmt == KMF_FORMAT_UNDEF) 7353089Swyllys return (PK_ERR_USAGE); 7363089Swyllys break; 7373089Swyllys case 'I': /* output file name */ 7383089Swyllys if (infile) 7393089Swyllys return (PK_ERR_USAGE); 7403089Swyllys infile = optarg_av; 7413089Swyllys break; 742864Sdinak case 'o': /* output file name */ 743864Sdinak if (filename) 744864Sdinak return (PK_ERR_USAGE); 745864Sdinak filename = optarg_av; 746864Sdinak break; 7473089Swyllys case 'c': /* input cert file name */ 7483089Swyllys if (certfile) 7493089Swyllys return (PK_ERR_USAGE); 7503089Swyllys certfile = optarg_av; 7513089Swyllys break; 7523089Swyllys case 'K': /* input key file name */ 7533089Swyllys if (keyfile) 7543089Swyllys return (PK_ERR_USAGE); 7553089Swyllys keyfile = optarg_av; 7563089Swyllys break; 757864Sdinak default: 758864Sdinak return (PK_ERR_USAGE); 759864Sdinak break; 760864Sdinak } 761864Sdinak } 76217Sdinak 7633089Swyllys /* Assume keystore = PKCS#11 if not specified */ 7643089Swyllys if (kstype == 0) 7653089Swyllys kstype = KMF_KEYSTORE_PK11TOKEN; 766864Sdinak 767864Sdinak /* Filename arg is required. */ 7683089Swyllys if (EMPTYSTRING(filename)) { 7693089Swyllys cryptoerror(LOG_STDERR, gettext("You must specify " 770*5051Swyllys "an 'outfile' parameter when exporting.\n")); 77117Sdinak return (PK_ERR_USAGE); 7723089Swyllys } 77317Sdinak 774864Sdinak /* No additional args allowed. */ 775864Sdinak argc -= optind_av; 776864Sdinak argv += optind_av; 777864Sdinak if (argc) 778864Sdinak return (PK_ERR_USAGE); 7793089Swyllys 7803089Swyllys /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ 7813089Swyllys if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && 782*5051Swyllys kstype != KMF_KEYSTORE_PK11TOKEN) { 7833089Swyllys 7843089Swyllys (void) fprintf(stderr, gettext("The objtype parameter " 785*5051Swyllys "is only relevant if keystore=pkcs11\n")); 7863089Swyllys return (PK_ERR_USAGE); 7873089Swyllys } 7883089Swyllys 7893089Swyllys if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) 7903089Swyllys token_spec = PK_DEFAULT_PK11TOKEN; 7913089Swyllys else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) 7923089Swyllys token_spec = DEFAULT_NSS_TOKEN; 7933089Swyllys 7943089Swyllys if (kstype == KMF_KEYSTORE_OPENSSL) { 7953089Swyllys if (kfmt != KMF_FORMAT_PKCS12) { 7963089Swyllys cryptoerror(LOG_STDERR, gettext("PKCS12 " 797*5051Swyllys "is the only export format " 798*5051Swyllys "supported for the 'file' " 799*5051Swyllys "keystore.\n")); 8003089Swyllys return (PK_ERR_USAGE); 8013089Swyllys } 8023089Swyllys if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { 8033089Swyllys cryptoerror(LOG_STDERR, gettext("A cert file" 804*5051Swyllys "and a key file must be specified " 805*5051Swyllys "when exporting to PKCS12 from the " 806*5051Swyllys "'file' keystore.\n")); 8073089Swyllys return (PK_ERR_USAGE); 8083089Swyllys } 8093089Swyllys } 81017Sdinak 81117Sdinak /* Check if the file exists and might be overwritten. */ 81217Sdinak if (access(filename, F_OK) == 0) { 8133089Swyllys cryptoerror(LOG_STDERR, 814*5051Swyllys gettext("Warning: file \"%s\" exists, " 815*5051Swyllys "will be overwritten."), filename); 81617Sdinak if (yesno(gettext("Continue with export? "), 81717Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 81817Sdinak return (0); 81917Sdinak } 8203089Swyllys } else { 8213089Swyllys rv = verify_file(filename); 8223089Swyllys if (rv != KMF_OK) { 8233089Swyllys cryptoerror(LOG_STDERR, gettext("The file (%s) " 824*5051Swyllys "cannot be created.\n"), filename); 8253089Swyllys return (PK_ERR_USAGE); 8263089Swyllys } 82717Sdinak } 82817Sdinak 8293089Swyllys if (serstr != NULL) { 8303089Swyllys uchar_t *bytes = NULL; 8313089Swyllys size_t bytelen; 83217Sdinak 833*5051Swyllys rv = kmf_hexstr_to_bytes((uchar_t *)serstr, &bytes, &bytelen); 8343089Swyllys if (rv != KMF_OK || bytes == NULL) { 8353089Swyllys (void) fprintf(stderr, gettext("serial number " 836*5051Swyllys "must be specified as a hex number " 837*5051Swyllys "(ex: 0x0102030405ffeeddee)\n")); 8383089Swyllys return (PK_ERR_USAGE); 8393089Swyllys } 8403089Swyllys serial.val = bytes; 8413089Swyllys serial.len = bytelen; 84217Sdinak } 84317Sdinak 8443089Swyllys if ((kstype == KMF_KEYSTORE_PK11TOKEN || 845*5051Swyllys kstype == KMF_KEYSTORE_NSS) && 846*5051Swyllys (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || 847*5051Swyllys kfmt == KMF_FORMAT_PKCS12)) { 8483089Swyllys (void) get_token_password(kstype, token_spec, 849*5051Swyllys &tokencred); 85017Sdinak } 85117Sdinak 852*5051Swyllys if ((rv = kmf_initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { 8533089Swyllys cryptoerror(LOG_STDERR, gettext("Error initializing " 854*5051Swyllys "KMF: 0x%02x\n"), rv); 8553089Swyllys return (rv); 85617Sdinak } 85717Sdinak 8583089Swyllys switch (kstype) { 8593089Swyllys case KMF_KEYSTORE_PK11TOKEN: 8603089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 861*5051Swyllys rv = pk_export_pk12_pk11(kmfhandle, 862*5051Swyllys token_spec, certlabel, 863*5051Swyllys issuer, subject, 864*5051Swyllys &serial, &tokencred, 865*5051Swyllys filename); 866*5051Swyllys else if ((oclass & PK_KEY_OBJ) || 867*5051Swyllys kfmt == KMF_FORMAT_RAWKEY) 868*5051Swyllys rv = pk_export_pk11_keys(kmfhandle, 869*5051Swyllys token_spec, &tokencred, kfmt, 870*5051Swyllys certlabel, filename); 8713089Swyllys else 8723089Swyllys rv = pk_export_pk11_objects(kmfhandle, 873*5051Swyllys token_spec, certlabel, 874*5051Swyllys issuer, subject, &serial, kfmt, 875*5051Swyllys filename); 8763089Swyllys break; 8773089Swyllys case KMF_KEYSTORE_NSS: 8783089Swyllys if (dir == NULL) 8793089Swyllys dir = PK_DEFAULT_DIRECTORY; 8803089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8813089Swyllys rv = pk_export_pk12_nss(kmfhandle, 882*5051Swyllys token_spec, dir, prefix, 883*5051Swyllys certlabel, issuer, 884*5051Swyllys subject, &serial, 885*5051Swyllys &tokencred, filename); 8863089Swyllys else 8873089Swyllys rv = pk_export_nss_objects(kmfhandle, 888*5051Swyllys token_spec, 889*5051Swyllys oclass, certlabel, issuer, subject, 890*5051Swyllys &serial, kfmt, dir, prefix, filename); 8913089Swyllys break; 8923089Swyllys case KMF_KEYSTORE_OPENSSL: 8933089Swyllys if (kfmt == KMF_FORMAT_PKCS12) 8943089Swyllys rv = pk_export_pk12_files(kmfhandle, 895*5051Swyllys certfile, keyfile, dir, 896*5051Swyllys filename); 8973089Swyllys else 8983089Swyllys rv = pk_export_file_objects(kmfhandle, oclass, 899*5051Swyllys issuer, subject, &serial, 900*5051Swyllys dir, infile, filename); 9013089Swyllys break; 9023089Swyllys default: 9033089Swyllys rv = PK_ERR_USAGE; 9043089Swyllys break; 90517Sdinak } 90617Sdinak 9073089Swyllys if (rv != KMF_OK) { 9083089Swyllys display_error(kmfhandle, rv, 909*5051Swyllys gettext("Error exporting objects")); 9103089Swyllys } 91117Sdinak 9123089Swyllys if (serial.val != NULL) 9133089Swyllys free(serial.val); 91417Sdinak 915*5051Swyllys (void) kmf_finalize(kmfhandle); 9163089Swyllys 9173089Swyllys return (rv); 91817Sdinak } 919