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