17711facfSdinak /* 27711facfSdinak * CDDL HEADER START 37711facfSdinak * 47711facfSdinak * The contents of this file are subject to the terms of the 57711facfSdinak * Common Development and Distribution License, Version 1.0 only 67711facfSdinak * (the "License"). You may not use this file except in compliance 77711facfSdinak * with the License. 87711facfSdinak * 97711facfSdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107711facfSdinak * or http://www.opensolaris.org/os/licensing. 117711facfSdinak * See the License for the specific language governing permissions 127711facfSdinak * and limitations under the License. 137711facfSdinak * 147711facfSdinak * When distributing Covered Code, include this CDDL HEADER in each 157711facfSdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167711facfSdinak * If applicable, add the following below this CDDL HEADER, with the 177711facfSdinak * fields enclosed by brackets "[]" replaced with your own identifying 187711facfSdinak * information: Portions Copyright [yyyy] [name of copyright owner] 197711facfSdinak * 207711facfSdinak * CDDL HEADER END 217711facfSdinak */ 227711facfSdinak /* 237711facfSdinak * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 247711facfSdinak * Use is subject to license terms. 257711facfSdinak */ 267711facfSdinak 277711facfSdinak #pragma ident "%Z%%M% %I% %E% SMI" 287711facfSdinak 297711facfSdinak /* 307711facfSdinak * This file implements the export operation for this tool. 317711facfSdinak * The basic flow of the process is to find the soft token, 327711facfSdinak * log into it, find the PKCS#11 objects in the soft token 337711facfSdinak * to be exported matching keys with their certificates, export 347711facfSdinak * them to the PKCS#12 file encrypting them with a file password 357711facfSdinak * if desired, and log out. 367711facfSdinak */ 377711facfSdinak 387711facfSdinak #include <stdio.h> 397711facfSdinak #include <stdlib.h> 407711facfSdinak #include <string.h> 417711facfSdinak #include <errno.h> 427711facfSdinak #include <cryptoutil.h> 437711facfSdinak #include <security/cryptoki.h> 447711facfSdinak #include "common.h" 457711facfSdinak #include "biginteger.h" 467711facfSdinak #include "osslcommon.h" 477711facfSdinak #include "p12common.h" 487711facfSdinak #include <openssl/pkcs12.h> 497711facfSdinak 507711facfSdinak /* 517711facfSdinak * Writes OpenSSL objects to PKCS#12 file. The PKCS#11 objects from 527711facfSdinak * the soft token need to be converted to OpenSSL structures prior 537711facfSdinak * to this call, since the PKCS#12 routines depend on that format. 547711facfSdinak * This code is patterned from OpenSSL apps that write PKCS#12 files. 557711facfSdinak * 567711facfSdinak * Note: it's not clear from the usage of all the functions here by 577711facfSdinak * OpenSSL apps whether these functions have return values or error 587711facfSdinak * conditions that can be checked. This function may benefit from 597711facfSdinak * a closer review at a later time. 607711facfSdinak */ 617711facfSdinak static int 627711facfSdinak write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 637711facfSdinak CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert, 647711facfSdinak STACK_OF(X509) *ca_certs, int *successes, int *failures) 657711facfSdinak /* ARGSUSED */ 667711facfSdinak { 677711facfSdinak STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 687711facfSdinak PKCS12_SAFEBAG *bag = NULL; 697711facfSdinak X509 *ca = NULL; 707711facfSdinak PKCS7 *cert_authsafe = NULL; 717711facfSdinak PKCS8_PRIV_KEY_INFO *p8 = NULL; 727711facfSdinak PKCS7 *key_authsafe = NULL; 737711facfSdinak STACK_OF(PKCS7) *authsafe_stack = NULL; 747711facfSdinak PKCS12 *p12_elem = NULL; 757711facfSdinak unsigned char *lab = NULL; 767711facfSdinak int lab_len = 0; 777711facfSdinak int i; 787711facfSdinak int n_writes = 0; 797711facfSdinak 807711facfSdinak cryptodebug("inside write_objs_pkcs12"); 817711facfSdinak 827711facfSdinak /* Do not reset *successes or *failures -- keep running totals. */ 837711facfSdinak 847711facfSdinak /* If there is nothing to write to the PKCS#12 file, leave. */ 857711facfSdinak if (cert == NULL && ca_certs == NULL && priv_key == NULL) { 867711facfSdinak cryptodebug("nothing to write to export file"); 877711facfSdinak return (0); 887711facfSdinak } 897711facfSdinak 907711facfSdinak /* 917711facfSdinak * Section 1: 927711facfSdinak * 937711facfSdinak * The first PKCS#12 container (safebag) will hold the certificates 947711facfSdinak * associated with this key. The result of this section is a 957711facfSdinak * PIN-encrypted PKCS#7 container (authsafe). If there are no 967711facfSdinak * certificates, there is no point in creating the "safebag" or the 977711facfSdinak * "authsafe" so we go to the next section. 987711facfSdinak */ 997711facfSdinak if (cert != NULL || ca_certs != NULL) { 1007711facfSdinak /* Start a PKCS#12 safebag container for the certificates. */ 1017711facfSdinak cryptodebug("creating certificate PKCS#12 safebag"); 1027711facfSdinak bag_stack = sk_PKCS12_SAFEBAG_new_null(); 1037711facfSdinak if (bag_stack == NULL) { 1047711facfSdinak cryptoerror(LOG_STDERR, gettext( 1057711facfSdinak "Unable to create PKCS#12 certificate bag.")); 1067711facfSdinak (*failures)++; 1077711facfSdinak return (-1); 1087711facfSdinak } 1097711facfSdinak 1107711facfSdinak /* Add the cert corresponding to private key to bag_stack. */ 1117711facfSdinak if (cert) { 1127711facfSdinak /* Convert cert from X509 struct to PKCS#12 bag */ 1137711facfSdinak cryptodebug("adding certificate to PKCS#12 safebag"); 1147711facfSdinak bag = PKCS12_x5092certbag(cert); 1157711facfSdinak if (bag == NULL) { 1167711facfSdinak cryptoerror(LOG_STDERR, gettext( 1177711facfSdinak "Unable to convert certificate to " 1187711facfSdinak "PKCS#12 bag.")); 1197711facfSdinak /* Cleanup the safebag. */ 1207711facfSdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, 1217711facfSdinak PKCS12_SAFEBAG_free); 1227711facfSdinak (*failures)++; 1237711facfSdinak return (-1); 1247711facfSdinak } 1257711facfSdinak 1267711facfSdinak /* Add the key id to the certificate bag. */ 1277711facfSdinak cryptodebug("add key id to PKCS#12 safebag"); 1287711facfSdinak if (!PKCS12_add_localkeyid(bag, id, id_len)) 1297711facfSdinak cryptodebug("error not caught"); 1307711facfSdinak 1317711facfSdinak /* Add the friendly name to the certificate bag. */ 1327711facfSdinak if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) { 1337711facfSdinak cryptodebug( 1347711facfSdinak "label PKCS#12 safebag with friendly name"); 1357711facfSdinak if (!PKCS12_add_friendlyname(bag, (char *)lab, 1367711facfSdinak lab_len)) 1377711facfSdinak cryptodebug("error not caught"); 1387711facfSdinak } 1397711facfSdinak 1407711facfSdinak /* Pile it on the bag_stack. */ 1417711facfSdinak if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 1427711facfSdinak cryptodebug("error not caught"); 1437711facfSdinak 1447711facfSdinak n_writes++; 1457711facfSdinak } 1467711facfSdinak 1477711facfSdinak /* Add all the CA chain certs to the bag_stack. */ 1487711facfSdinak if (ca_certs) { 1497711facfSdinak cryptodebug("adding CA certificate chain to PKCS#12 " 1507711facfSdinak "safebag"); 1517711facfSdinak /* 1527711facfSdinak * Go through the stack of CA certs, converting each 1537711facfSdinak * one to a PKCS#12 bag and piling them onto the 1547711facfSdinak * bag_stack. 1557711facfSdinak */ 1567711facfSdinak for (i = 0; i < sk_X509_num(ca_certs); i++) { 1577711facfSdinak /* 1587711facfSdinak * sk_X509_value() is macro that embeds a 1597711facfSdinak * cast to (X509 *). Here it translates 1607711facfSdinak * into ((X509 *)sk_value((ca_certs), (i))). 1617711facfSdinak * Lint is complaining about the embedded 1627711facfSdinak * casting, and to fix it, you need to fix 1637711facfSdinak * openssl header files. 1647711facfSdinak */ 1657711facfSdinak /* LINTED E_BAD_PTR_CAST_ALIGN */ 1667711facfSdinak ca = sk_X509_value(ca_certs, i); 1677711facfSdinak 1687711facfSdinak /* Convert CA cert to PKCS#12 bag. */ 1697711facfSdinak cryptodebug("adding CA certificate #%d " 1707711facfSdinak "to PKCS#12 safebag", i+1); 1717711facfSdinak bag = PKCS12_x5092certbag(ca); 1727711facfSdinak if (bag == NULL) { 1737711facfSdinak cryptoerror(LOG_STDERR, gettext( 1747711facfSdinak "Unable to convert CA certificate " 1757711facfSdinak "#%d to PKCS#12 bag."), i+1); 1767711facfSdinak /* Cleanup the safebag. */ 1777711facfSdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, 1787711facfSdinak PKCS12_SAFEBAG_free); 1797711facfSdinak (*failures)++; 1807711facfSdinak return (-1); 1817711facfSdinak } 1827711facfSdinak 1837711facfSdinak /* Note CA certs do not have friendly name. */ 1847711facfSdinak 1857711facfSdinak /* Pile it onto the bag_stack. */ 1867711facfSdinak if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 1877711facfSdinak cryptodebug("error not caught"); 1887711facfSdinak 1897711facfSdinak n_writes++; 1907711facfSdinak } 1917711facfSdinak } 1927711facfSdinak 1937711facfSdinak /* Turn bag_stack of certs into encrypted authsafe. */ 1947711facfSdinak cryptodebug("encrypt certificate PKCS#12 bag into " 1957711facfSdinak "PKCS#7 authsafe"); 1967711facfSdinak cert_authsafe = PKCS12_pack_p7encdata( 1977711facfSdinak NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL, 1987711facfSdinak 0, PKCS12_DEFAULT_ITER, bag_stack); 1997711facfSdinak 2007711facfSdinak /* Clear away this bag_stack, we're done with it. */ 2017711facfSdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 2027711facfSdinak bag_stack = NULL; 2037711facfSdinak 2047711facfSdinak if (cert_authsafe == NULL) { 2057711facfSdinak cryptoerror(LOG_STDERR, gettext( 2067711facfSdinak "Unable to PKCS#7-encrypt certificate bag.")); 2077711facfSdinak (*failures)++; 2087711facfSdinak return (-1); 2097711facfSdinak } 2107711facfSdinak } 2117711facfSdinak 2127711facfSdinak /* 2137711facfSdinak * Section 2: 2147711facfSdinak * 2157711facfSdinak * The second PKCS#12 container (safebag) will hold the private key 2167711facfSdinak * that goes with the certificates above. The results of this section 2177711facfSdinak * is an unencrypted PKCS#7 container (authsafe). If there is no 2187711facfSdinak * private key, there is no point in creating the "safebag" or the 2197711facfSdinak * "authsafe" so we go to the next section. 2207711facfSdinak */ 2217711facfSdinak if (priv_key != NULL) { 2227711facfSdinak /* Make a PKCS#8 shrouded key bag. */ 2237711facfSdinak cryptodebug("create PKCS#8 shrouded key out of private key"); 2247711facfSdinak p8 = EVP_PKEY2PKCS8(priv_key); 2257711facfSdinak if (p8 == NULL) { 2267711facfSdinak cryptoerror(LOG_STDERR, gettext( 2277711facfSdinak "Unable to create PKCS#8 shrouded key for " 2287711facfSdinak "private key.")); 2297711facfSdinak (*failures)++; 2307711facfSdinak return (-1); 2317711facfSdinak } 2327711facfSdinak 2337711facfSdinak /* Put the shrouded key into a PKCS#12 bag. */ 2347711facfSdinak cryptodebug("convert shrouded key to PKCS#12 bag"); 2357711facfSdinak bag = PKCS12_MAKE_SHKEYBAG( 2367711facfSdinak NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin, 2377711facfSdinak -1, NULL, 0, PKCS12_DEFAULT_ITER, p8); 2387711facfSdinak 2397711facfSdinak /* Clean up the PKCS#8 shrouded key, don't need it now. */ 2407711facfSdinak PKCS8_PRIV_KEY_INFO_free(p8); 2417711facfSdinak p8 = NULL; 2427711facfSdinak 2437711facfSdinak if (bag == NULL) { 2447711facfSdinak cryptoerror(LOG_STDERR, gettext( 2457711facfSdinak "Unable to convert private key to PKCS#12 bag.")); 2467711facfSdinak (*failures)++; 2477711facfSdinak return (-1); 2487711facfSdinak } 2497711facfSdinak 2507711facfSdinak /* Add the key id to the certificate bag. */ 2517711facfSdinak cryptodebug("add key id to PKCS#12 safebag"); 2527711facfSdinak if (!PKCS12_add_localkeyid(bag, id, id_len)) 2537711facfSdinak cryptodebug("error not caught"); 2547711facfSdinak 2557711facfSdinak /* Add the cert friendly name to the private key bag. */ 2567711facfSdinak if (lab != NULL) { 2577711facfSdinak cryptodebug("label PKCS#12 safebag with friendly name"); 2587711facfSdinak if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len)) 2597711facfSdinak cryptodebug("error not caught"); 2607711facfSdinak } 2617711facfSdinak 2627711facfSdinak /* Start a PKCS#12 safebag container for the private key. */ 2637711facfSdinak cryptodebug("creating private key PKCS#12 safebag"); 2647711facfSdinak bag_stack = sk_PKCS12_SAFEBAG_new_null(); 2657711facfSdinak if (bag_stack == NULL) { 2667711facfSdinak cryptoerror(LOG_STDERR, gettext( 2677711facfSdinak "Unable to create PKCS#12 private key bag.")); 2687711facfSdinak (*failures)++; 2697711facfSdinak return (-1); 2707711facfSdinak } 2717711facfSdinak 2727711facfSdinak /* Pile on the private key on the bag_stack. */ 2737711facfSdinak if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 2747711facfSdinak cryptodebug("error not caught"); 2757711facfSdinak 2767711facfSdinak /* Turn bag_stack with private key into unencrypted authsafe. */ 2777711facfSdinak cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe"); 2787711facfSdinak key_authsafe = PKCS12_pack_p7data(bag_stack); 2797711facfSdinak 2807711facfSdinak /* Clear away this bag_stack, we're done with it. */ 2817711facfSdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 2827711facfSdinak bag_stack = NULL; 2837711facfSdinak 2847711facfSdinak if (key_authsafe == NULL) { 2857711facfSdinak cryptoerror(LOG_STDERR, gettext( 2867711facfSdinak "Unable to PKCS#7-convert private key bag.")); 2877711facfSdinak (*failures)++; 2887711facfSdinak return (-1); 2897711facfSdinak } 2907711facfSdinak 2917711facfSdinak n_writes++; 2927711facfSdinak } 2937711facfSdinak 2947711facfSdinak /* 2957711facfSdinak * Section 3: 2967711facfSdinak * 2977711facfSdinak * This is where the two PKCS#7 containers, one for the certificates 2987711facfSdinak * and one for the private key, are put together into a PKCS#12 2997711facfSdinak * element. This final PKCS#12 element is written to the export file. 3007711facfSdinak */ 3017711facfSdinak /* Start a PKCS#7 stack. */ 3027711facfSdinak cryptodebug("create PKCS#7 authsafe for private key and certificates"); 3037711facfSdinak authsafe_stack = sk_PKCS7_new_null(); 3047711facfSdinak if (authsafe_stack == NULL) { 3057711facfSdinak cryptoerror(LOG_STDERR, gettext( 3067711facfSdinak "Unable to create PKCS#7 container for private key " 3077711facfSdinak "and certificates.")); 3087711facfSdinak (*failures)++; 3097711facfSdinak return (-1); 3107711facfSdinak } 3117711facfSdinak 3127711facfSdinak /* Put certificates and private key into PKCS#7 stack. */ 3137711facfSdinak if (key_authsafe != NULL) { 3147711facfSdinak cryptodebug("put private key authsafe into PKCS#7 container"); 3157711facfSdinak if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) 3167711facfSdinak cryptodebug("error not caught"); 3177711facfSdinak } 3187711facfSdinak if (cert_authsafe != NULL) { 3197711facfSdinak cryptodebug("put certificate authsafe into PKCS#7 container"); 3207711facfSdinak if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) 3217711facfSdinak cryptodebug("error not caught"); 3227711facfSdinak } 3237711facfSdinak 3247711facfSdinak /* Create PKCS#12 element out of PKCS#7 stack. */ 3257711facfSdinak cryptodebug("create PKCS#12 element for export file"); 3267711facfSdinak p12_elem = PKCS12_init(NID_pkcs7_data); 3277711facfSdinak if (p12_elem == NULL) { 3287711facfSdinak cryptoerror(LOG_STDERR, gettext( 3297711facfSdinak "Unable to create PKCS#12 element for export file.")); 3307711facfSdinak sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 3317711facfSdinak (*failures)++; 3327711facfSdinak return (-1); 3337711facfSdinak } 3347711facfSdinak 3357711facfSdinak /* Put the PKCS#7 stack into the PKCS#12 element. */ 3367711facfSdinak if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) 3377711facfSdinak cryptodebug("error not caught"); 3387711facfSdinak 3397711facfSdinak /* Clear away the PKCS#7 stack, we're done with it. */ 3407711facfSdinak sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 3417711facfSdinak authsafe_stack = NULL; 3427711facfSdinak 3437711facfSdinak /* Set the integrity MAC on the PKCS#12 element. */ 3447711facfSdinak cryptodebug("setting MAC for PKCS#12 element"); 3457711facfSdinak if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0, 3467711facfSdinak PKCS12_DEFAULT_ITER, NULL)) 3477711facfSdinak cryptodebug("error not caught"); 3487711facfSdinak 3497711facfSdinak /* Write the PKCS#12 element to the export file. */ 3507711facfSdinak cryptodebug("writing PKCS#12 element to export file"); 3517711facfSdinak if (!i2d_PKCS12_bio(fbio, p12_elem)) 3527711facfSdinak cryptodebug("error not caught"); 3537711facfSdinak 3547711facfSdinak (*successes) += n_writes; 3557711facfSdinak 3567711facfSdinak /* Clear away the PKCS#12 element. */ 3577711facfSdinak PKCS12_free(p12_elem); 3587711facfSdinak return (0); 3597711facfSdinak } 3607711facfSdinak 3617711facfSdinak /* 3627711facfSdinak * Get token objects: private key, its cert, and its cert chain. 3637711facfSdinak */ 3647711facfSdinak static CK_RV 3657711facfSdinak get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, 3667711facfSdinak CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain, 3677711facfSdinak CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len) 3687711facfSdinak { 3697711facfSdinak CK_RV rv = CKR_OK; 3707711facfSdinak CK_ATTRIBUTE keyid_attr[1] = { 3717711facfSdinak { CKA_ID, NULL, 0 } 3727711facfSdinak }; 3737711facfSdinak static CK_OBJECT_CLASS class = CKO_CERTIFICATE; 3747711facfSdinak static CK_CERTIFICATE_TYPE certtype = CKC_X_509; 3757711facfSdinak CK_ATTRIBUTE cert_attr[4] = { 3767711facfSdinak { CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) }, 3777711facfSdinak { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) }, 3787711facfSdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 3797711facfSdinak { CKA_ID, NULL, 0 } 3807711facfSdinak }; 3817711facfSdinak CK_ULONG num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE); 3827711facfSdinak CK_OBJECT_HANDLE cert = ~0UL; 3837711facfSdinak CK_ULONG num = 0; 3847711facfSdinak 3857711facfSdinak cryptodebug("inside get_token_objs"); 3867711facfSdinak 3877711facfSdinak /* Get the size of the object's CKA_ID field first. */ 3887711facfSdinak cryptodebug("getting CKA_ID size for object 0x%x", obj); 3897711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) { 3907711facfSdinak cryptoerror(LOG_STDERR, gettext("Unable to get size of object" 3917711facfSdinak " key id (%s)."), pkcs11_strerror(rv)); 3927711facfSdinak return (rv); 3937711facfSdinak } 3947711facfSdinak 3957711facfSdinak /* Allocate the space needed for the key id. */ 3967711facfSdinak if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) { 3977711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 3987711facfSdinak return (CKR_HOST_MEMORY); 3997711facfSdinak } 4007711facfSdinak 4017711facfSdinak /* Get the CKA_ID field to match obj with its cert. */ 4027711facfSdinak cryptodebug("getting CKA_ID attribute for object 0x%x", obj); 4037711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) { 4047711facfSdinak cryptoerror(LOG_STDERR, gettext("Unable to get object " 4057711facfSdinak "key id (%s)."), pkcs11_strerror(rv)); 4067711facfSdinak free(keyid_attr[0].pValue); 4077711facfSdinak return (rv); 4087711facfSdinak } 4097711facfSdinak 4107711facfSdinak /* Now try to find any certs that have the same id. */ 4117711facfSdinak cryptodebug("searching for certificates with same CKA_ID"); 4127711facfSdinak cert_attr[3].pValue = keyid_attr[0].pValue; 4137711facfSdinak cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen; 4147711facfSdinak if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) { 4157711facfSdinak cryptoerror(LOG_STDERR, gettext("Unable to initialize " 4167711facfSdinak "certificate search (%s)."), pkcs11_strerror(rv)); 4177711facfSdinak free(keyid_attr[0].pValue); 4187711facfSdinak return (rv); 4197711facfSdinak } 4207711facfSdinak 4217711facfSdinak /* Find the first cert that matches the key id. */ 4227711facfSdinak if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) { 4237711facfSdinak cryptoerror(LOG_STDERR, gettext("Certificate search failed " 4247711facfSdinak "(%s)."), pkcs11_strerror(rv)); 4257711facfSdinak free(keyid_attr[0].pValue); 4267711facfSdinak return (rv); 4277711facfSdinak } 4287711facfSdinak 4297711facfSdinak (void) C_FindObjectsFinal(sess); 4307711facfSdinak 4317711facfSdinak *id = keyid_attr[0].pValue; 4327711facfSdinak *id_len = keyid_attr[0].ulValueLen; 4337711facfSdinak 4347711facfSdinak *mate = (num == 1) ? cert : ~0UL; 4357711facfSdinak 4367711facfSdinak /* We currently do not find all the certs in the chain. */ 4377711facfSdinak *chain_len = 0; 4387711facfSdinak *chain = NULL; 4397711facfSdinak 4407711facfSdinak return (CKR_OK); 4417711facfSdinak } 4427711facfSdinak 4437711facfSdinak /* 4447711facfSdinak * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM. 4457711facfSdinak * "to" should be the address of a ptr init'ed to NULL to 4467711facfSdinak * receive the BIGNUM, e.g., 4477711facfSdinak * biginteger_t from; 4487711facfSdinak * BIGNUM *foo = NULL; 4497711facfSdinak * cvt_bigint2bn(&from, &foo); 4507711facfSdinak */ 4517711facfSdinak static int 4527711facfSdinak cvt_bigint2bn(biginteger_t *from, BIGNUM **to) 4537711facfSdinak { 4547711facfSdinak BIGNUM *temp = NULL; 4557711facfSdinak 4567711facfSdinak cryptodebug("inside cvt_bigint2bn"); 4577711facfSdinak 4587711facfSdinak if (from == NULL || to == NULL) 4597711facfSdinak return (-1); 4607711facfSdinak 4617711facfSdinak cryptodebug("calling BN_bin2bn"); 4627711facfSdinak if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) == 4637711facfSdinak NULL) 4647711facfSdinak return (-1); 4657711facfSdinak 4667711facfSdinak *to = temp; 4677711facfSdinak return (0); 4687711facfSdinak } 4697711facfSdinak 4707711facfSdinak /* 4717711facfSdinak * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure. 4727711facfSdinak */ 4737711facfSdinak static CK_RV 4747711facfSdinak cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 4757711facfSdinak { 4767711facfSdinak CK_RV rv = CKR_OK; 4777711facfSdinak EVP_PKEY *key = NULL; /* OpenSSL representation */ 4787711facfSdinak RSA *rsa = NULL; /* OpenSSL representation */ 4797711facfSdinak biginteger_t mod = { NULL, 0 }; /* required */ 4807711facfSdinak biginteger_t pubexp = { NULL, 0 }; /* required */ 4817711facfSdinak biginteger_t priexp = { NULL, 0 }; /* optional */ 4827711facfSdinak biginteger_t prime1 = { NULL, 0 }; /* optional */ 4837711facfSdinak biginteger_t prime2 = { NULL, 0 }; /* optional */ 4847711facfSdinak biginteger_t exp1 = { NULL, 0 }; /* optional */ 4857711facfSdinak biginteger_t exp2 = { NULL, 0 }; /* optional */ 4867711facfSdinak biginteger_t coef = { NULL, 0 }; /* optional */ 4877711facfSdinak CK_ATTRIBUTE rsa_pri_attrs[8] = { 4887711facfSdinak { CKA_MODULUS, NULL, 0 }, 4897711facfSdinak { CKA_PUBLIC_EXPONENT, NULL, 0 }, 4907711facfSdinak { CKA_PRIVATE_EXPONENT, NULL, 0 }, /* optional */ 4917711facfSdinak { CKA_PRIME_1, NULL, 0 }, /* | */ 4927711facfSdinak { CKA_PRIME_2, NULL, 0 }, /* | */ 4937711facfSdinak { CKA_EXPONENT_1, NULL, 0 }, /* | */ 4947711facfSdinak { CKA_EXPONENT_2, NULL, 0 }, /* | */ 4957711facfSdinak { CKA_COEFFICIENT, NULL, 0 } /* V */ 4967711facfSdinak }; 4977711facfSdinak CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE); 4987711facfSdinak int i; 4997711facfSdinak 5007711facfSdinak cryptodebug("inside cvt_rsa2evp_pkey"); 5017711facfSdinak 5027711facfSdinak cryptodebug("calling RSA_new"); 5037711facfSdinak if ((rsa = RSA_new()) == NULL) { 5047711facfSdinak cryptoerror(LOG_STDERR, gettext( 5057711facfSdinak "Unable to allocate internal RSA structure.")); 5067711facfSdinak return (CKR_HOST_MEMORY); 5077711facfSdinak } 5087711facfSdinak 5097711facfSdinak /* Get the sizes of the attributes we need. */ 5107711facfSdinak cryptodebug("calling C_GetAttributeValue for size info"); 5117711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != 5127711facfSdinak CKR_OK) { 5137711facfSdinak cryptoerror(LOG_STDERR, gettext( 5147711facfSdinak "Unable to get RSA private key attribute sizes (%s)."), 5157711facfSdinak pkcs11_strerror(rv)); 5167711facfSdinak return (rv); 5177711facfSdinak } 5187711facfSdinak 5197711facfSdinak /* Allocate memory for each attribute. */ 5207711facfSdinak for (i = 0; i < count; i++) { 5217711facfSdinak if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || 5227711facfSdinak rsa_pri_attrs[i].ulValueLen == 0) { 5237711facfSdinak cryptodebug("cvt_rsa2evp_pkey: *** should not happen"); 5247711facfSdinak rsa_pri_attrs[i].ulValueLen = 0; 5257711facfSdinak continue; 5267711facfSdinak } 5277711facfSdinak if ((rsa_pri_attrs[i].pValue = 5287711facfSdinak malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) { 5297711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 5307711facfSdinak return (CKR_HOST_MEMORY); 5317711facfSdinak } 5327711facfSdinak } 5337711facfSdinak 5347711facfSdinak /* Now really get the attributes. */ 5357711facfSdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 5367711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != 5377711facfSdinak CKR_OK) { 5387711facfSdinak cryptoerror(LOG_STDERR, gettext( 5397711facfSdinak "Unable to get RSA private key attributes (%s)."), 5407711facfSdinak pkcs11_strerror(rv)); 5417711facfSdinak return (rv); 5427711facfSdinak } 5437711facfSdinak 5447711facfSdinak /* 5457711facfSdinak * Fill in all the temp variables. Modulus and public exponent 5467711facfSdinak * are required. The rest are optional. 5477711facfSdinak */ 5487711facfSdinak i = 0; 5497711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod); 5507711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp); 5517711facfSdinak 5527711facfSdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 5537711facfSdinak rsa_pri_attrs[i].ulValueLen != 0) 5547711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp); 5557711facfSdinak i++; 5567711facfSdinak 5577711facfSdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 5587711facfSdinak rsa_pri_attrs[i].ulValueLen != 0) 5597711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1); 5607711facfSdinak i++; 5617711facfSdinak 5627711facfSdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 5637711facfSdinak rsa_pri_attrs[i].ulValueLen != 0) 5647711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2); 5657711facfSdinak i++; 5667711facfSdinak 5677711facfSdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 5687711facfSdinak rsa_pri_attrs[i].ulValueLen != 0) 5697711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1); 5707711facfSdinak i++; 5717711facfSdinak 5727711facfSdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 5737711facfSdinak rsa_pri_attrs[i].ulValueLen != 0) 5747711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2); 5757711facfSdinak i++; 5767711facfSdinak 5777711facfSdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 5787711facfSdinak rsa_pri_attrs[i].ulValueLen != 0) 5797711facfSdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef); 5807711facfSdinak i++; 5817711facfSdinak 5827711facfSdinak /* Start the conversion to internal OpenSSL RSA structure. */ 5837711facfSdinak 5847711facfSdinak /* Modulus n */ 5857711facfSdinak if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) { 5867711facfSdinak cryptoerror(LOG_STDERR, gettext( 5877711facfSdinak "Unable to convert RSA private key modulus.")); 5887711facfSdinak return (CKR_GENERAL_ERROR); 5897711facfSdinak } 5907711facfSdinak 5917711facfSdinak /* Public exponent e */ 5927711facfSdinak if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) { 5937711facfSdinak cryptoerror(LOG_STDERR, gettext( 5947711facfSdinak "Unable to convert RSA private key public exponent.")); 5957711facfSdinak return (CKR_GENERAL_ERROR); 5967711facfSdinak } 5977711facfSdinak 5987711facfSdinak /* Private exponent e */ 5997711facfSdinak if (priexp.big_value != NULL) { 6007711facfSdinak if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) { 6017711facfSdinak cryptoerror(LOG_STDERR, gettext("Unable to convert " 6027711facfSdinak "RSA private key private exponent.")); 6037711facfSdinak return (CKR_GENERAL_ERROR); 6047711facfSdinak } 6057711facfSdinak } else 6067711facfSdinak cryptodebug("no RSA private key private exponent"); 6077711facfSdinak 6087711facfSdinak /* Prime p */ 6097711facfSdinak if (prime1.big_value != NULL) { 6107711facfSdinak if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) { 6117711facfSdinak cryptoerror(LOG_STDERR, gettext( 6127711facfSdinak "Unable to convert RSA private key prime 1.")); 6137711facfSdinak return (CKR_GENERAL_ERROR); 6147711facfSdinak } 6157711facfSdinak } else 6167711facfSdinak cryptodebug("no RSA private key prime 1"); 6177711facfSdinak 6187711facfSdinak /* Prime q */ 6197711facfSdinak if (prime2.big_value != NULL) { 6207711facfSdinak if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) { 6217711facfSdinak cryptoerror(LOG_STDERR, gettext( 6227711facfSdinak "Unable to convert RSA private key prime 2.")); 6237711facfSdinak return (CKR_GENERAL_ERROR); 6247711facfSdinak } 6257711facfSdinak } else 6267711facfSdinak cryptodebug("no RSA private key prime 2"); 6277711facfSdinak 6287711facfSdinak /* Private exponent d modulo p-1 */ 6297711facfSdinak if (exp1.big_value != NULL) { 6307711facfSdinak if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) { 6317711facfSdinak cryptoerror(LOG_STDERR, gettext( 6327711facfSdinak "Unable to convert RSA private key exponent 1.")); 6337711facfSdinak return (CKR_GENERAL_ERROR); 6347711facfSdinak } 6357711facfSdinak } else 6367711facfSdinak cryptodebug("no RSA private key exponent 1"); 6377711facfSdinak 6387711facfSdinak /* Private exponent d modulo q-1 */ 6397711facfSdinak if (exp2.big_value != NULL) { 6407711facfSdinak if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) { 6417711facfSdinak cryptoerror(LOG_STDERR, gettext( 6427711facfSdinak "Unable to convert RSA private key exponent 2.")); 6437711facfSdinak return (CKR_GENERAL_ERROR); 6447711facfSdinak } 6457711facfSdinak } else 6467711facfSdinak cryptodebug("no RSA private key exponent 2"); 6477711facfSdinak 6487711facfSdinak /* CRT coefficient q-inverse mod p */ 6497711facfSdinak if (coef.big_value != NULL) { 6507711facfSdinak if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) { 6517711facfSdinak cryptoerror(LOG_STDERR, gettext( 6527711facfSdinak "Unable to convert RSA private key coefficient.")); 6537711facfSdinak return (CKR_GENERAL_ERROR); 6547711facfSdinak } 6557711facfSdinak } else 6567711facfSdinak cryptodebug("no RSA private key coefficient"); 6577711facfSdinak 6587711facfSdinak /* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */ 6597711facfSdinak cryptodebug("calling EVP_PKEY_new"); 6607711facfSdinak if ((key = EVP_PKEY_new()) == NULL) { 6617711facfSdinak cryptoerror(LOG_STDERR, gettext( 6627711facfSdinak "Unable to allocate internal EVP_PKEY structure.")); 6637711facfSdinak return (CKR_HOST_MEMORY); 6647711facfSdinak } 6657711facfSdinak 6667711facfSdinak /* Put the RSA struct into the EVP_PKEY struct and return it. */ 6677711facfSdinak cryptodebug("calling EVP_PKEY_set1_RSA"); 6687711facfSdinak (void) EVP_PKEY_set1_RSA(key, rsa); 6697711facfSdinak 6707711facfSdinak *pk = key; 6717711facfSdinak return (CKR_OK); 6727711facfSdinak } 6737711facfSdinak 6747711facfSdinak /* 6757711facfSdinak * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure. 6767711facfSdinak */ 6777711facfSdinak static CK_RV 6787711facfSdinak cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 6797711facfSdinak { 6807711facfSdinak CK_RV rv = CKR_OK; 6817711facfSdinak EVP_PKEY *key = NULL; /* OpenSSL representation */ 6827711facfSdinak DSA *dsa = NULL; /* OpenSSL representation */ 6837711facfSdinak biginteger_t prime = { NULL, 0 }; /* required */ 6847711facfSdinak biginteger_t subprime = { NULL, 0 }; /* required */ 6857711facfSdinak biginteger_t base = { NULL, 0 }; /* required */ 6867711facfSdinak biginteger_t value = { NULL, 0 }; /* required */ 6877711facfSdinak CK_ATTRIBUTE dsa_pri_attrs[4] = { 6887711facfSdinak { CKA_PRIME, NULL, 0 }, 6897711facfSdinak { CKA_SUBPRIME, NULL, 0 }, 6907711facfSdinak { CKA_BASE, NULL, 0 }, 6917711facfSdinak { CKA_VALUE, NULL, 0 } 6927711facfSdinak }; 6937711facfSdinak CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE); 6947711facfSdinak int i; 6957711facfSdinak 6967711facfSdinak cryptodebug("inside cvt_dsa2evp_pkey"); 6977711facfSdinak 6987711facfSdinak cryptodebug("calling DSA_new"); 6997711facfSdinak if ((dsa = DSA_new()) == NULL) { 7007711facfSdinak cryptoerror(LOG_STDERR, gettext( 7017711facfSdinak "Unable to allocate internal DSA structure.")); 7027711facfSdinak return (CKR_HOST_MEMORY); 7037711facfSdinak } 7047711facfSdinak 7057711facfSdinak /* Get the sizes of the attributes we need. */ 7067711facfSdinak cryptodebug("calling C_GetAttributeValue for size info"); 7077711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) != 7087711facfSdinak CKR_OK) { 7097711facfSdinak cryptoerror(LOG_STDERR, gettext( 7107711facfSdinak "Unable to get DSA private key object attributes (%s)."), 7117711facfSdinak pkcs11_strerror(rv)); 7127711facfSdinak return (rv); 7137711facfSdinak } 7147711facfSdinak 7157711facfSdinak /* Allocate memory for each attribute. */ 7167711facfSdinak for (i = 0; i < count; i++) { 7177711facfSdinak if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || 7187711facfSdinak dsa_pri_attrs[i].ulValueLen == 0) { 7197711facfSdinak cryptodebug("cvt_dsa2evp_pkey: *** should not happen"); 7207711facfSdinak dsa_pri_attrs[i].ulValueLen = 0; 7217711facfSdinak continue; 7227711facfSdinak } 7237711facfSdinak if ((dsa_pri_attrs[i].pValue = 7247711facfSdinak malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) { 7257711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 7267711facfSdinak return (CKR_HOST_MEMORY); 7277711facfSdinak } 7287711facfSdinak } 7297711facfSdinak 7307711facfSdinak /* Now really get the attributes. */ 7317711facfSdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 7327711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) != 7337711facfSdinak CKR_OK) { 7347711facfSdinak cryptoerror(LOG_STDERR, gettext( 7357711facfSdinak "Unable to get DSA private key attributes (%s)."), 7367711facfSdinak pkcs11_strerror(rv)); 7377711facfSdinak return (rv); 7387711facfSdinak } 7397711facfSdinak 7407711facfSdinak /* Fill in all the temp variables. They are all required. */ 7417711facfSdinak i = 0; 7427711facfSdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime); 7437711facfSdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime); 7447711facfSdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base); 7457711facfSdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value); 7467711facfSdinak 7477711facfSdinak /* Start the conversion to internal OpenSSL DSA structure. */ 7487711facfSdinak 7497711facfSdinak /* Prime p */ 7507711facfSdinak if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) { 7517711facfSdinak cryptoerror(LOG_STDERR, gettext( 7527711facfSdinak "Unable to convert DSA private key prime.")); 7537711facfSdinak return (CKR_GENERAL_ERROR); 7547711facfSdinak } 7557711facfSdinak 7567711facfSdinak /* Subprime q */ 7577711facfSdinak if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) { 7587711facfSdinak cryptoerror(LOG_STDERR, gettext( 7597711facfSdinak "Unable to convert DSA private key subprime.")); 7607711facfSdinak return (CKR_GENERAL_ERROR); 7617711facfSdinak } 7627711facfSdinak 7637711facfSdinak /* Base g */ 7647711facfSdinak if (cvt_bigint2bn(&base, &(dsa->g)) < 0) { 7657711facfSdinak cryptoerror(LOG_STDERR, gettext( 7667711facfSdinak "Unable to convert DSA private key base.")); 7677711facfSdinak return (CKR_GENERAL_ERROR); 7687711facfSdinak } 7697711facfSdinak 7707711facfSdinak /* Private key x */ 7717711facfSdinak if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) { 7727711facfSdinak cryptoerror(LOG_STDERR, gettext( 7737711facfSdinak "Unable to convert DSA private key value.")); 7747711facfSdinak return (CKR_GENERAL_ERROR); 7757711facfSdinak } 7767711facfSdinak 7777711facfSdinak /* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */ 7787711facfSdinak cryptodebug("calling EVP_PKEY_new"); 7797711facfSdinak if ((key = EVP_PKEY_new()) == NULL) { 7807711facfSdinak cryptoerror(LOG_STDERR, gettext( 7817711facfSdinak "Unable to allocate internal EVP_PKEY structure.")); 7827711facfSdinak return (CKR_HOST_MEMORY); 7837711facfSdinak } 7847711facfSdinak 7857711facfSdinak /* Put the DSA struct into the EVP_PKEY struct and return it. */ 7867711facfSdinak cryptodebug("calling EVP_PKEY_set1_DSA"); 7877711facfSdinak (void) EVP_PKEY_set1_DSA(key, dsa); 7887711facfSdinak 7897711facfSdinak *pk = key; 7907711facfSdinak return (CKR_OK); 7917711facfSdinak } 7927711facfSdinak 7937711facfSdinak /* 7947711facfSdinak * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure. 7957711facfSdinak */ 7967711facfSdinak static CK_RV 7977711facfSdinak cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 7987711facfSdinak { 7997711facfSdinak CK_RV rv = CKR_OK; 8007711facfSdinak EVP_PKEY *key = NULL; /* OpenSSL representation */ 8017711facfSdinak DH *dh = NULL; /* OpenSSL representation */ 8027711facfSdinak biginteger_t prime = { NULL, 0 }; /* required */ 8037711facfSdinak biginteger_t base = { NULL, 0 }; /* required */ 8047711facfSdinak biginteger_t value = { NULL, 0 }; /* required */ 8057711facfSdinak CK_ATTRIBUTE dh_pri_attrs[3] = { 8067711facfSdinak { CKA_PRIME, NULL, 0 }, 8077711facfSdinak { CKA_BASE, NULL, 0 }, 8087711facfSdinak { CKA_VALUE, NULL, 0 } 8097711facfSdinak }; 8107711facfSdinak CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE); 8117711facfSdinak int i; 8127711facfSdinak 8137711facfSdinak cryptodebug("inside cvt_dh2evp_pkey"); 8147711facfSdinak 8157711facfSdinak cryptodebug("calling DH_new"); 8167711facfSdinak if ((dh = DH_new()) == NULL) { 8177711facfSdinak cryptoerror(LOG_STDERR, gettext( 8187711facfSdinak "Unable to allocate internal DH structure.")); 8197711facfSdinak return (CKR_HOST_MEMORY); 8207711facfSdinak } 8217711facfSdinak 8227711facfSdinak /* Get the sizes of the attributes we need. */ 8237711facfSdinak cryptodebug("calling C_GetAttributeValue for size info"); 8247711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) != 8257711facfSdinak CKR_OK) { 8267711facfSdinak cryptoerror(LOG_STDERR, gettext( 8277711facfSdinak "Unable to get DH private key object attributes (%s)."), 8287711facfSdinak pkcs11_strerror(rv)); 8297711facfSdinak return (rv); 8307711facfSdinak } 8317711facfSdinak 8327711facfSdinak /* Allocate memory for each attribute. */ 8337711facfSdinak for (i = 0; i < count; i++) { 8347711facfSdinak if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || 8357711facfSdinak dh_pri_attrs[i].ulValueLen == 0) { 8367711facfSdinak cryptodebug("cvt_dh2evp_pkey: ***should not happen"); 8377711facfSdinak dh_pri_attrs[i].ulValueLen = 0; 8387711facfSdinak continue; 8397711facfSdinak } 8407711facfSdinak if ((dh_pri_attrs[i].pValue = 8417711facfSdinak malloc(dh_pri_attrs[i].ulValueLen)) == NULL) { 8427711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 8437711facfSdinak return (CKR_HOST_MEMORY); 8447711facfSdinak } 8457711facfSdinak } 8467711facfSdinak 8477711facfSdinak /* Now really get the attributes. */ 8487711facfSdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 8497711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) != 8507711facfSdinak CKR_OK) { 8517711facfSdinak cryptoerror(LOG_STDERR, gettext( 8527711facfSdinak "Unable to get DH private key attributes (%s)."), 8537711facfSdinak pkcs11_strerror(rv)); 8547711facfSdinak return (rv); 8557711facfSdinak } 8567711facfSdinak 8577711facfSdinak /* Fill in all the temp variables. They are all required. */ 8587711facfSdinak i = 0; 8597711facfSdinak copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime); 8607711facfSdinak copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base); 8617711facfSdinak copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value); 8627711facfSdinak 8637711facfSdinak /* Start the conversion to internal OpenSSL DH structure. */ 8647711facfSdinak 8657711facfSdinak /* Prime p */ 8667711facfSdinak if (cvt_bigint2bn(&prime, &(dh->p)) < 0) { 8677711facfSdinak cryptoerror(LOG_STDERR, gettext( 8687711facfSdinak "Unable to convert DH private key prime.")); 8697711facfSdinak return (CKR_GENERAL_ERROR); 8707711facfSdinak } 8717711facfSdinak 8727711facfSdinak /* Base g */ 8737711facfSdinak if (cvt_bigint2bn(&base, &(dh->g)) < 0) { 8747711facfSdinak cryptoerror(LOG_STDERR, gettext( 8757711facfSdinak "Unable to convert DH private key base.")); 8767711facfSdinak return (CKR_GENERAL_ERROR); 8777711facfSdinak } 8787711facfSdinak 8797711facfSdinak /* Private value x */ 8807711facfSdinak if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) { 8817711facfSdinak cryptoerror(LOG_STDERR, gettext( 8827711facfSdinak "Unable to convert DH private key value.")); 8837711facfSdinak return (CKR_GENERAL_ERROR); 8847711facfSdinak } 8857711facfSdinak 8867711facfSdinak /* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */ 8877711facfSdinak cryptodebug("calling EVP_PKEY_new"); 8887711facfSdinak if ((key = EVP_PKEY_new()) == NULL) { 8897711facfSdinak cryptoerror(LOG_STDERR, gettext( 8907711facfSdinak "Unable to allocate internal EVP_PKEY structure.")); 8917711facfSdinak return (CKR_HOST_MEMORY); 8927711facfSdinak } 8937711facfSdinak 8947711facfSdinak /* Put the DH struct into the EVP_PKEY struct and return it. */ 8957711facfSdinak cryptodebug("calling EVP_PKEY_set1_DH"); 8967711facfSdinak (void) EVP_PKEY_set1_DH(key, dh); 8977711facfSdinak 8987711facfSdinak *pk = key; 8997711facfSdinak return (CKR_OK); 9007711facfSdinak } 9017711facfSdinak 9027711facfSdinak /* 9037711facfSdinak * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure. 9047711facfSdinak */ 9057711facfSdinak static CK_RV 9067711facfSdinak cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 9077711facfSdinak { 9087711facfSdinak CK_RV rv = CKR_OK; 9097711facfSdinak static CK_KEY_TYPE keytype = 0; 9107711facfSdinak CK_ATTRIBUTE keytype_attr[1] = { 9117711facfSdinak { CKA_KEY_TYPE, &keytype, sizeof (keytype) } 9127711facfSdinak }; 9137711facfSdinak 9147711facfSdinak cryptodebug("inside cvt_obj2evp_pkey"); 9157711facfSdinak 9167711facfSdinak /* Find out the key type to do the right conversion. */ 9177711facfSdinak cryptodebug("calling C_GetAttributeValue"); 9187711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) != 9197711facfSdinak CKR_OK) { 9207711facfSdinak cryptoerror(LOG_STDERR, gettext( 9217711facfSdinak "Unable to get token object key type (%s)."), 9227711facfSdinak pkcs11_strerror(rv)); 9237711facfSdinak return (rv); 9247711facfSdinak } 9257711facfSdinak 9267711facfSdinak switch (keytype) { 9277711facfSdinak case CKK_RSA: 9287711facfSdinak cryptodebug("converting RSA key"); 9297711facfSdinak return (cvt_rsa2evp_pkey(sess, obj, pk)); 9307711facfSdinak case CKK_DSA: 9317711facfSdinak cryptodebug("converting DSA key"); 9327711facfSdinak return (cvt_dsa2evp_pkey(sess, obj, pk)); 9337711facfSdinak case CKK_DH: 9347711facfSdinak cryptodebug("converting DH key"); 9357711facfSdinak return (cvt_dh2evp_pkey(sess, obj, pk)); 9367711facfSdinak default: 9377711facfSdinak cryptoerror(LOG_STDERR, gettext( 9387711facfSdinak "Private key type 0x%02x conversion not supported."), 9397711facfSdinak keytype); 9407711facfSdinak return (CKR_GENERAL_ERROR); 9417711facfSdinak } 9427711facfSdinak } 9437711facfSdinak 9447711facfSdinak /* 9457711facfSdinak * Convert PKCS#11 certificate object to OpenSSL X509 structure. 9467711facfSdinak */ 9477711facfSdinak static CK_RV 9487711facfSdinak cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c) 9497711facfSdinak { 9507711facfSdinak CK_RV rv = CKR_OK; 9517711facfSdinak X509 *cert = NULL; /* OpenSSL representation */ 9527711facfSdinak X509 *temp_cert = NULL; 9537711facfSdinak CK_BYTE *subject = NULL; 9547711facfSdinak CK_ULONG subject_len = 0; 9557711facfSdinak CK_BYTE *value = NULL; 9567711facfSdinak CK_ULONG value_len = 0; 9577711facfSdinak CK_BYTE *label = NULL; 9587711facfSdinak CK_ULONG label_len = 0; 9597711facfSdinak CK_BYTE *id = NULL; 9607711facfSdinak CK_ULONG id_len = 0; 9617711facfSdinak CK_BYTE *issuer = NULL; 9627711facfSdinak CK_ULONG issuer_len = 0; 9637711facfSdinak CK_BYTE *serial = NULL; 9647711facfSdinak CK_ULONG serial_len = 0; 9657711facfSdinak CK_ATTRIBUTE cert_attrs[6] = { 9667711facfSdinak { CKA_SUBJECT, NULL, 0 }, /* required */ 9677711facfSdinak { CKA_VALUE, NULL, 0 }, /* required */ 9687711facfSdinak { CKA_LABEL, NULL, 0 }, /* optional */ 9697711facfSdinak { CKA_ID, NULL, 0 }, /* optional */ 9707711facfSdinak { CKA_ISSUER, NULL, 0 }, /* optional */ 9717711facfSdinak { CKA_SERIAL_NUMBER, NULL, 0 } /* optional */ 9727711facfSdinak }; 9737711facfSdinak CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE); 9747711facfSdinak int i = 0; 9757711facfSdinak X509_NAME *ssl_subject = NULL; 9767711facfSdinak X509_NAME *ssl_issuer = NULL; 9777711facfSdinak ASN1_INTEGER *ssl_serial = NULL; 9787711facfSdinak 9797711facfSdinak cryptodebug("inside cvt_cert2x509"); 9807711facfSdinak 9817711facfSdinak cryptodebug("calling X509_new"); 9827711facfSdinak if ((cert = X509_new()) == NULL) { 9837711facfSdinak cryptoerror(LOG_STDERR, gettext( 9847711facfSdinak "Unable to allocate internal X509 structure.")); 9857711facfSdinak return (CKR_HOST_MEMORY); 9867711facfSdinak } 9877711facfSdinak 9887711facfSdinak /* Get the sizes of the attributes we need. */ 9897711facfSdinak cryptodebug("calling C_GetAttributeValue for size info"); 9907711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) != 9917711facfSdinak CKR_OK) { 9927711facfSdinak cryptoerror(LOG_STDERR, gettext( 9937711facfSdinak "Unable to get certificate attribute sizes (%s)."), 9947711facfSdinak pkcs11_strerror(rv)); 9957711facfSdinak return (rv); 9967711facfSdinak } 9977711facfSdinak 9987711facfSdinak /* Allocate memory for each attribute. */ 9997711facfSdinak for (i = 0; i < count; i++) { 10007711facfSdinak if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 || 10017711facfSdinak cert_attrs[i].ulValueLen == 0) { 10027711facfSdinak cryptodebug("cvt_cert2x509: *** should not happen"); 10037711facfSdinak cert_attrs[i].ulValueLen = 0; 10047711facfSdinak continue; 10057711facfSdinak } 10067711facfSdinak if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen)) 10077711facfSdinak == NULL) { 10087711facfSdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 10097711facfSdinak return (CKR_HOST_MEMORY); 10107711facfSdinak } 10117711facfSdinak } 10127711facfSdinak 10137711facfSdinak /* Now really get the attributes. */ 10147711facfSdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 10157711facfSdinak if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) != 10167711facfSdinak CKR_OK) { 10177711facfSdinak cryptoerror(LOG_STDERR, gettext( 10187711facfSdinak "Unable to get certificate attributes (%s)."), 10197711facfSdinak pkcs11_strerror(rv)); 10207711facfSdinak return (rv); 10217711facfSdinak } 10227711facfSdinak 10237711facfSdinak /* 10247711facfSdinak * Fill in all the temp variables. Subject and value are required. 10257711facfSdinak * The rest are optional. 10267711facfSdinak */ 10277711facfSdinak i = 0; 10287711facfSdinak copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len); 10297711facfSdinak copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len); 10307711facfSdinak 10317711facfSdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 10327711facfSdinak cert_attrs[i].ulValueLen != 0) 10337711facfSdinak copy_attr_to_string(&(cert_attrs[i]), &label, &label_len); 10347711facfSdinak i++; 10357711facfSdinak 10367711facfSdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 10377711facfSdinak cert_attrs[i].ulValueLen != 0) 10387711facfSdinak copy_attr_to_string(&(cert_attrs[i]), &id, &id_len); 10397711facfSdinak i++; 10407711facfSdinak 10417711facfSdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 10427711facfSdinak cert_attrs[i].ulValueLen != 0) 10437711facfSdinak copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len); 10447711facfSdinak i++; 10457711facfSdinak 10467711facfSdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 10477711facfSdinak cert_attrs[i].ulValueLen != 0) 10487711facfSdinak copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len); 10497711facfSdinak i++; 10507711facfSdinak 10517711facfSdinak /* Start the conversion to internal OpenSSL X509 structure. */ 10527711facfSdinak 10537711facfSdinak /* Subject name (required) */ 10547711facfSdinak cryptodebug("calling d2i_X509_NAME for subject name"); 10557711facfSdinak if ((ssl_subject = d2i_X509_NAME(NULL, &subject, subject_len)) == 10567711facfSdinak NULL) { 10577711facfSdinak cryptoerror(LOG_STDERR, gettext( 10587711facfSdinak "Unable to convert certificate subject name.")); 10597711facfSdinak return (CKR_GENERAL_ERROR); 10607711facfSdinak } 10617711facfSdinak cryptodebug("calling X509_set_subject_name"); 10627711facfSdinak if (!X509_set_subject_name(cert, ssl_subject)) { 10637711facfSdinak cryptoerror(LOG_STDERR, gettext( 10647711facfSdinak "Unable to pack certificate subject name entries.")); 10657711facfSdinak return (CKR_GENERAL_ERROR); 10667711facfSdinak } 10677711facfSdinak 10687711facfSdinak /* Label (optional) */ 10697711facfSdinak cryptodebug("calling X509_alias_set1"); 10707711facfSdinak if (!X509_alias_set1(cert, label, label_len)) 10717711facfSdinak cryptodebug("error not caught"); 10727711facfSdinak 10737711facfSdinak /* Id (optional) */ 10747711facfSdinak cryptodebug("calling X509_keyid_set1"); 10757711facfSdinak if (!X509_keyid_set1(cert, id, id_len)) 10767711facfSdinak cryptodebug("error not caught"); 10777711facfSdinak 10787711facfSdinak /* Issuer name (optional) */ 10797711facfSdinak cryptodebug("calling d2i_X509_NAME for issuer name"); 10807711facfSdinak if ((ssl_issuer = d2i_X509_NAME(NULL, &issuer, issuer_len)) == NULL) { 10817711facfSdinak cryptoerror(LOG_STDERR, gettext( 10827711facfSdinak "Unable to convert certificate issuer name.")); 10837711facfSdinak return (CKR_GENERAL_ERROR); 10847711facfSdinak } 10857711facfSdinak cryptodebug("calling X509_set_issuer_name"); 10867711facfSdinak if (!X509_set_issuer_name(cert, ssl_issuer)) { 10877711facfSdinak cryptoerror(LOG_STDERR, gettext( 10887711facfSdinak "Unable to pack certificate issuer name entries.")); 10897711facfSdinak return (CKR_GENERAL_ERROR); 10907711facfSdinak } 10917711facfSdinak 10927711facfSdinak /* Serial number (optional) */ 10937711facfSdinak cryptodebug("calling c2i_ASN1_INTEGER for serial number"); 10947711facfSdinak if ((ssl_serial = c2i_ASN1_INTEGER(NULL, &serial, serial_len)) == 10957711facfSdinak NULL) { 10967711facfSdinak cryptoerror(LOG_STDERR, gettext( 10977711facfSdinak "Unable to convert certificate serial number.")); 10987711facfSdinak return (CKR_GENERAL_ERROR); 10997711facfSdinak } 11007711facfSdinak cryptodebug("calling X509_set_serialNumber"); 11017711facfSdinak if (!X509_set_serialNumber(cert, ssl_serial)) 11027711facfSdinak cryptodebug("error not caught"); 11037711facfSdinak 11047711facfSdinak /* 11057711facfSdinak * Value (required) 11067711facfSdinak * 11077711facfSdinak * The rest of this code takes the CKA_VALUE attribute, converts 11087711facfSdinak * it into a temp OpenSSL X509 structure and picks out the rest 11097711facfSdinak * of the fields we need to convert it back into the current X509 11107711facfSdinak * structure that will get exported. The reason we don't just 11117711facfSdinak * start with CKA_VALUE is because while the object was in the 11127711facfSdinak * softtoken, it is possible that some of its attributes changed. 11137711facfSdinak * Those changes would not appear in CKA_VALUE and would be lost 11147711facfSdinak * if we started with CKA_VALUE that was saved originally. 11157711facfSdinak */ 11167711facfSdinak cryptodebug("calling d2i_X509 for cert value"); 11177711facfSdinak if ((temp_cert = d2i_X509(NULL, &value, value_len)) == NULL) { 11187711facfSdinak cryptoerror(LOG_STDERR, gettext( 11197711facfSdinak "Unable to convert main certificate values.")); 11207711facfSdinak return (CKR_GENERAL_ERROR); 11217711facfSdinak } 11227711facfSdinak 11237711facfSdinak /* Transfer these values from temp_cert to cert. */ 11247711facfSdinak cryptodebug("calling X509_set_version/X509_get_version"); 11257711facfSdinak if (!X509_set_version(cert, X509_get_version(temp_cert))) 11267711facfSdinak cryptodebug("error not caught"); 11277711facfSdinak 11287711facfSdinak cryptodebug("calling X509_set_notBefore/X509_get_notBefore"); 11297711facfSdinak if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert))) 11307711facfSdinak cryptodebug("error not caught"); 11317711facfSdinak 11327711facfSdinak cryptodebug("calling X509_set_notAfter/X509_get_notAfter"); 11337711facfSdinak if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert))) 11347711facfSdinak cryptodebug("error not caught"); 11357711facfSdinak 11367711facfSdinak cryptodebug("calling X509_set_pubkey/X509_get_pubkey"); 11377711facfSdinak if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert))) 11387711facfSdinak cryptodebug("error not caught"); 11397711facfSdinak 11407711facfSdinak /* 11417711facfSdinak * These don't get transfered from temp_cert to cert. 11427711facfSdinak * It -appears- that they may get regenerated as needed. 11437711facfSdinak * 11447711facfSdinak * cert->cert_info->signature = dup(temp_cert->cert_info->signature); 11457711facfSdinak * cert->sig_alg = dup(temp_cert->sig_alg); 11467711facfSdinak * cert->signature = dup(temp_cert->signature); 11477711facfSdinak * cert->skid = dup(temp_cert->skid); 11487711facfSdinak * cert->akid = dup(temp_cert->akid); 11497711facfSdinak */ 11507711facfSdinak 11517711facfSdinak *c = cert; 11527711facfSdinak return (CKR_OK); 11537711facfSdinak } 11547711facfSdinak 11557711facfSdinak static CK_RV 11567711facfSdinak convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, 11577711facfSdinak CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len, 11587711facfSdinak EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca) 11597711facfSdinak { 11607711facfSdinak CK_RV rv = CKR_OK; 11617711facfSdinak EVP_PKEY *pk = NULL; 11627711facfSdinak X509 *c = NULL; 11637711facfSdinak X509 *one_ca = NULL; 11647711facfSdinak STACK_OF(X509) *ch = NULL; 11657711facfSdinak int i; 11667711facfSdinak 11677711facfSdinak cryptodebug("inside convert_token_objs"); 11687711facfSdinak 11697711facfSdinak if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK) 11707711facfSdinak return (rv); 11717711facfSdinak 11727711facfSdinak if (mate != ~0UL) { 11737711facfSdinak cryptodebug("converting cert corresponding to private key"); 11747711facfSdinak if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK) 11757711facfSdinak return (rv); 11767711facfSdinak } 11777711facfSdinak 11787711facfSdinak if (chain_len != 0) { 11797711facfSdinak cryptodebug("converting ca chain of %d certs corresponding " 11807711facfSdinak "to private key", chain_len); 11817711facfSdinak ch = sk_X509_new_null(); 11827711facfSdinak for (i = 0; i < chain_len; i++) { 11837711facfSdinak if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) != 11847711facfSdinak CKR_OK) { 11857711facfSdinak return (rv); 11867711facfSdinak } 11877711facfSdinak if (!sk_X509_push(ch, one_ca)) 11887711facfSdinak cryptodebug("error not caught"); 11897711facfSdinak } 11907711facfSdinak } 11917711facfSdinak 11927711facfSdinak *priv_key = pk; 11937711facfSdinak *cert = (mate != ~0UL) ? c : NULL; 11947711facfSdinak *ca = (chain_len != 0) ? ch : NULL; 11957711facfSdinak return (CKR_OK); 11967711facfSdinak } 11977711facfSdinak 11987711facfSdinak /* 11997711facfSdinak * Export objects from token to PKCS#12 file. 12007711facfSdinak */ 12017711facfSdinak int 12027711facfSdinak pk_export(int argc, char *argv[]) 12037711facfSdinak { 1204*49e21299Sdinak int opt; 1205*49e21299Sdinak extern int optind_av; 1206*49e21299Sdinak extern char *optarg_av; 1207*49e21299Sdinak char *token_spec = NULL; 12087711facfSdinak char *token_name = NULL; 12097711facfSdinak char *manuf_id = NULL; 12107711facfSdinak char *serial_no = NULL; 12117711facfSdinak char full_name[FULL_NAME_LEN]; 12127711facfSdinak char *filename = NULL; 12137711facfSdinak CK_SLOT_ID slot_id; 12147711facfSdinak CK_FLAGS pin_state; 12157711facfSdinak CK_UTF8CHAR_PTR pin = NULL; 12167711facfSdinak CK_ULONG pinlen = 0; 12177711facfSdinak CK_UTF8CHAR_PTR pk12pin = NULL; 12187711facfSdinak CK_ULONG pk12pinlen = 0; 12197711facfSdinak CK_SESSION_HANDLE sess; 12207711facfSdinak BIO *fbio = NULL; 12217711facfSdinak EVP_PKEY *priv_key = NULL; 12227711facfSdinak X509 *cert = NULL; 12237711facfSdinak STACK_OF(X509) *ca = NULL; 12247711facfSdinak CK_RV rv = CKR_OK; 12257711facfSdinak CK_OBJECT_HANDLE *objs = NULL; 12267711facfSdinak CK_ULONG num_objs = 0; 12277711facfSdinak CK_OBJECT_HANDLE mate = ~0UL; 12287711facfSdinak CK_OBJECT_HANDLE *chain = NULL; 12297711facfSdinak CK_ULONG chain_len; 12307711facfSdinak CK_BYTE *id = NULL; 12317711facfSdinak CK_ULONG id_len = 0; 12327711facfSdinak int i = 0; 12337711facfSdinak int good_ones = 0, bad_ones = 0; /* running totals */ 12347711facfSdinak 12357711facfSdinak cryptodebug("inside pk_export"); 12367711facfSdinak 1237*49e21299Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 1238*49e21299Sdinak while ((opt = getopt_av(argc, argv, "T:(token)o:(outfile)")) != EOF) { 1239*49e21299Sdinak switch (opt) { 1240*49e21299Sdinak case 'T': /* token specifier */ 1241*49e21299Sdinak if (token_spec) 1242*49e21299Sdinak return (PK_ERR_USAGE); 1243*49e21299Sdinak token_spec = optarg_av; 1244*49e21299Sdinak break; 1245*49e21299Sdinak case 'o': /* output file name */ 1246*49e21299Sdinak if (filename) 1247*49e21299Sdinak return (PK_ERR_USAGE); 1248*49e21299Sdinak filename = optarg_av; 1249*49e21299Sdinak break; 1250*49e21299Sdinak default: 1251*49e21299Sdinak return (PK_ERR_USAGE); 1252*49e21299Sdinak break; 1253*49e21299Sdinak } 1254*49e21299Sdinak } 12557711facfSdinak 1256*49e21299Sdinak /* If nothing is specified, default is to use softtoken. */ 1257*49e21299Sdinak if (token_spec == NULL) { 1258*49e21299Sdinak token_name = SOFT_TOKEN_LABEL; 1259*49e21299Sdinak manuf_id = SOFT_MANUFACTURER_ID; 1260*49e21299Sdinak serial_no = SOFT_TOKEN_SERIAL; 1261*49e21299Sdinak } else { 1262*49e21299Sdinak /* 1263*49e21299Sdinak * Parse token specifier into token_name, manuf_id, serial_no. 1264*49e21299Sdinak * Token_name is required; manuf_id and serial_no are optional. 1265*49e21299Sdinak */ 1266*49e21299Sdinak if (parse_token_spec(token_spec, &token_name, &manuf_id, 1267*49e21299Sdinak &serial_no) < 0) 1268*49e21299Sdinak return (PK_ERR_USAGE); 1269*49e21299Sdinak } 1270*49e21299Sdinak 1271*49e21299Sdinak /* Filename arg is required. */ 1272*49e21299Sdinak if (filename == NULL) 12737711facfSdinak return (PK_ERR_USAGE); 12747711facfSdinak 1275*49e21299Sdinak /* No additional args allowed. */ 1276*49e21299Sdinak argc -= optind_av; 1277*49e21299Sdinak argv += optind_av; 1278*49e21299Sdinak if (argc) 1279*49e21299Sdinak return (PK_ERR_USAGE); 12807711facfSdinak /* Done parsing command line options. */ 12817711facfSdinak 12827711facfSdinak /* Check if the file exists and might be overwritten. */ 12837711facfSdinak if (access(filename, F_OK) == 0) { 12847711facfSdinak cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, " 12857711facfSdinak "will be overwritten."), filename); 12867711facfSdinak if (yesno(gettext("Continue with export? "), 12877711facfSdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 12887711facfSdinak return (0); 12897711facfSdinak } 12907711facfSdinak } 12917711facfSdinak 12927711facfSdinak full_token_name(token_name, manuf_id, serial_no, full_name); 12937711facfSdinak 12947711facfSdinak /* Find the slot with token. */ 12957711facfSdinak if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, 12967711facfSdinak &pin_state)) != CKR_OK) { 12977711facfSdinak cryptoerror(LOG_STDERR, gettext( 12987711facfSdinak "Unable to find token %s (%s)."), full_name, 12997711facfSdinak pkcs11_strerror(rv)); 13007711facfSdinak return (PK_ERR_PK11); 13017711facfSdinak } 13027711facfSdinak 13037711facfSdinak /* Get the user's PIN. */ 13047711facfSdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, 13057711facfSdinak &pinlen)) != CKR_OK) { 13067711facfSdinak cryptoerror(LOG_STDERR, gettext( 13077711facfSdinak "Unable to get token passphrase (%s)."), 13087711facfSdinak pkcs11_strerror(rv)); 13097711facfSdinak quick_finish(NULL); 13107711facfSdinak return (PK_ERR_PK11); 13117711facfSdinak } 13127711facfSdinak 13137711facfSdinak /* Assume user must be logged in R/W to export objects from token. */ 13147711facfSdinak if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) != 13157711facfSdinak CKR_OK) { 13167711facfSdinak cryptoerror(LOG_STDERR, 13177711facfSdinak gettext("Unable to log into token (%s)."), 13187711facfSdinak pkcs11_strerror(rv)); 13197711facfSdinak quick_finish(sess); 13207711facfSdinak return (PK_ERR_PK11); 13217711facfSdinak } 13227711facfSdinak 13237711facfSdinak /* Collect all private keys first. */ 13247711facfSdinak if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL, 13257711facfSdinak &objs, &num_objs)) != CKR_OK) { 13267711facfSdinak cryptoerror(LOG_STDERR, gettext( 13277711facfSdinak "Unable to retrieve private key token objects (%s)."), 13287711facfSdinak pkcs11_strerror(rv)); 13297711facfSdinak quick_finish(sess); 13307711facfSdinak return (PK_ERR_PK11); 13317711facfSdinak } 13327711facfSdinak 13337711facfSdinak /* Nothing to do? */ 13347711facfSdinak if (num_objs == 0) { 13357711facfSdinak cryptoerror(LOG_STDERR, gettext("No objects found.")); 13367711facfSdinak quick_finish(sess); 13377711facfSdinak return (0); 13387711facfSdinak } 13397711facfSdinak 13407711facfSdinak /* Setup OpenSSL context. */ 13417711facfSdinak PKTOOL_setup_openssl(); 13427711facfSdinak 13437711facfSdinak /* Create PKCS#12 file. */ 13447711facfSdinak if ((create_pkcs12(filename, &fbio)) < 0) { 13457711facfSdinak cryptoerror(LOG_STDERR, gettext("No export file created.")); 13467711facfSdinak quick_finish(sess); 13477711facfSdinak return (PK_ERR_SYSTEM); 13487711facfSdinak } 13497711facfSdinak 13507711facfSdinak /* Get the PIN for the PKCS#12 export file. */ 13517711facfSdinak if ((rv = get_pin(gettext("Create export file passphrase:"), gettext( 13527711facfSdinak "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) != 13537711facfSdinak CKR_OK) { 13547711facfSdinak cryptoerror(LOG_STDERR, 13557711facfSdinak gettext("Unable to get export file passphrase (%s)."), 13567711facfSdinak pkcs11_strerror(rv)); 13577711facfSdinak close_pkcs12(fbio); 13587711facfSdinak quick_finish(sess); 13597711facfSdinak return (PK_ERR_PK11); 13607711facfSdinak } 13617711facfSdinak 13627711facfSdinak for (i = 0; i < num_objs; i++) { 13637711facfSdinak /* Get a private key and its certificate and CA chain. */ 13647711facfSdinak if ((rv = get_token_objs(sess, objs[i], &mate, &chain, 13657711facfSdinak &chain_len, &id, &id_len)) != CKR_OK) { 13667711facfSdinak /* 13677711facfSdinak * Note this "rv" is either CKR_OK or !CKR_OK. The 13687711facfSdinak * real error codes/messages are handled inside 13697711facfSdinak * read_token_objs(). 13707711facfSdinak */ 13717711facfSdinak cryptoerror(LOG_STDERR, 13727711facfSdinak gettext("Unable to get token objects.")); 13737711facfSdinak free(id); 13747711facfSdinak close_pkcs12(fbio); 13757711facfSdinak quick_finish(sess); 13767711facfSdinak return (PK_ERR_PK11); 13777711facfSdinak } 13787711facfSdinak 13797711facfSdinak /* Convert to OpenSSL equivalents. */ 13807711facfSdinak if ((rv = convert_token_objs(sess, objs[i], mate, chain, 13817711facfSdinak chain_len, &priv_key, &cert, &ca)) != CKR_OK) { 13827711facfSdinak /* 13837711facfSdinak * Note this "rv" is either CKR_OK or !CKR_OK. The 13847711facfSdinak * real error codes/messages are handled inside 13857711facfSdinak * read_token_objs(). 13867711facfSdinak */ 13877711facfSdinak cryptoerror(LOG_STDERR, 13887711facfSdinak gettext("Unable to convert token objects.")); 13897711facfSdinak free(id); 13907711facfSdinak close_pkcs12(fbio); 13917711facfSdinak quick_finish(sess); 13927711facfSdinak return (PK_ERR_PK11); 13937711facfSdinak } 13947711facfSdinak 13957711facfSdinak /* 13967711facfSdinak * When exporting of cert chains is implemented, these 13977711facfSdinak * messages should be updated accordingly. 13987711facfSdinak */ 13997711facfSdinak if (mate == ~0UL) 14007711facfSdinak (void) fprintf(stdout, gettext( 14017711facfSdinak "Writing object #%d...\n"), i+1); 14027711facfSdinak else 14037711facfSdinak (void) fprintf(stdout, gettext("Writing object #%d " 14047711facfSdinak "and its certificate...\n"), i+1); 14057711facfSdinak 14067711facfSdinak /* Write object and its certs to the PKCS#12 export file. */ 14077711facfSdinak if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len, 14087711facfSdinak priv_key, cert, ca, &good_ones, &bad_ones) < 0) { 14097711facfSdinak cryptoerror(LOG_STDERR, gettext( 14107711facfSdinak "Unable to write object #%d to export file."), i+1); 14117711facfSdinak sk_X509_pop_free(ca, X509_free); 14127711facfSdinak free(id); 14137711facfSdinak close_pkcs12(fbio); 14147711facfSdinak quick_finish(sess); 14157711facfSdinak return (PK_ERR_OPENSSL); 14167711facfSdinak } 14177711facfSdinak 14187711facfSdinak /* Destroy key id and CA cert chain, done with them. */ 14197711facfSdinak free(id); 14207711facfSdinak id = NULL; 14217711facfSdinak sk_X509_pop_free(ca, X509_free); 14227711facfSdinak ca = NULL; 14237711facfSdinak } 14247711facfSdinak 14257711facfSdinak (void) fprintf(stdout, gettext( 14267711facfSdinak "%d token objects exported, %d errors occurred.\n"), 14277711facfSdinak good_ones, bad_ones); 14287711facfSdinak 14297711facfSdinak /* Close PKCS#12 file. */ 14307711facfSdinak close_pkcs12(fbio); 14317711facfSdinak 14327711facfSdinak /* Clean up. */ 14337711facfSdinak quick_finish(sess); 14347711facfSdinak return (0); 14357711facfSdinak } 1436