117Sdinak /* 217Sdinak * CDDL HEADER START 317Sdinak * 417Sdinak * The contents of this file are subject to the terms of the 5*1837Sdinak * Common Development and Distribution License (the "License"). 6*1837Sdinak * You may not use this file except in compliance with the License. 717Sdinak * 817Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 917Sdinak * or http://www.opensolaris.org/os/licensing. 1017Sdinak * See the License for the specific language governing permissions 1117Sdinak * and limitations under the License. 1217Sdinak * 1317Sdinak * When distributing Covered Code, include this CDDL HEADER in each 1417Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1517Sdinak * If applicable, add the following below this CDDL HEADER, with the 1617Sdinak * fields enclosed by brackets "[]" replaced with your own identifying 1717Sdinak * information: Portions Copyright [yyyy] [name of copyright owner] 1817Sdinak * 1917Sdinak * CDDL HEADER END 2017Sdinak */ 2117Sdinak /* 22*1837Sdinak * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 2317Sdinak * Use is subject to license terms. 2417Sdinak */ 2517Sdinak 2617Sdinak #pragma ident "%Z%%M% %I% %E% SMI" 2717Sdinak 2817Sdinak /* 2917Sdinak * This file implements the export operation for this tool. 3017Sdinak * The basic flow of the process is to find the soft token, 3117Sdinak * log into it, find the PKCS#11 objects in the soft token 3217Sdinak * to be exported matching keys with their certificates, export 3317Sdinak * them to the PKCS#12 file encrypting them with a file password 3417Sdinak * if desired, and log out. 3517Sdinak */ 3617Sdinak 3717Sdinak #include <stdio.h> 3817Sdinak #include <stdlib.h> 3917Sdinak #include <string.h> 4017Sdinak #include <errno.h> 4117Sdinak #include <cryptoutil.h> 4217Sdinak #include <security/cryptoki.h> 4317Sdinak #include "common.h" 4417Sdinak #include "biginteger.h" 4517Sdinak #include "osslcommon.h" 4617Sdinak #include "p12common.h" 4717Sdinak #include <openssl/pkcs12.h> 4817Sdinak 4917Sdinak /* 5017Sdinak * Writes OpenSSL objects to PKCS#12 file. The PKCS#11 objects from 5117Sdinak * the soft token need to be converted to OpenSSL structures prior 5217Sdinak * to this call, since the PKCS#12 routines depend on that format. 5317Sdinak * This code is patterned from OpenSSL apps that write PKCS#12 files. 5417Sdinak * 5517Sdinak * Note: it's not clear from the usage of all the functions here by 5617Sdinak * OpenSSL apps whether these functions have return values or error 5717Sdinak * conditions that can be checked. This function may benefit from 5817Sdinak * a closer review at a later time. 5917Sdinak */ 6017Sdinak static int 6117Sdinak write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 6217Sdinak CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert, 6317Sdinak STACK_OF(X509) *ca_certs, int *successes, int *failures) 6417Sdinak /* ARGSUSED */ 6517Sdinak { 6617Sdinak STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; 6717Sdinak PKCS12_SAFEBAG *bag = NULL; 6817Sdinak X509 *ca = NULL; 6917Sdinak PKCS7 *cert_authsafe = NULL; 7017Sdinak PKCS8_PRIV_KEY_INFO *p8 = NULL; 7117Sdinak PKCS7 *key_authsafe = NULL; 7217Sdinak STACK_OF(PKCS7) *authsafe_stack = NULL; 7317Sdinak PKCS12 *p12_elem = NULL; 7417Sdinak unsigned char *lab = NULL; 7517Sdinak int lab_len = 0; 7617Sdinak int i; 7717Sdinak int n_writes = 0; 7817Sdinak 7917Sdinak cryptodebug("inside write_objs_pkcs12"); 8017Sdinak 8117Sdinak /* Do not reset *successes or *failures -- keep running totals. */ 8217Sdinak 8317Sdinak /* If there is nothing to write to the PKCS#12 file, leave. */ 8417Sdinak if (cert == NULL && ca_certs == NULL && priv_key == NULL) { 8517Sdinak cryptodebug("nothing to write to export file"); 8617Sdinak return (0); 8717Sdinak } 8817Sdinak 8917Sdinak /* 9017Sdinak * Section 1: 9117Sdinak * 9217Sdinak * The first PKCS#12 container (safebag) will hold the certificates 9317Sdinak * associated with this key. The result of this section is a 9417Sdinak * PIN-encrypted PKCS#7 container (authsafe). If there are no 9517Sdinak * certificates, there is no point in creating the "safebag" or the 9617Sdinak * "authsafe" so we go to the next section. 9717Sdinak */ 9817Sdinak if (cert != NULL || ca_certs != NULL) { 9917Sdinak /* Start a PKCS#12 safebag container for the certificates. */ 10017Sdinak cryptodebug("creating certificate PKCS#12 safebag"); 10117Sdinak bag_stack = sk_PKCS12_SAFEBAG_new_null(); 10217Sdinak if (bag_stack == NULL) { 10317Sdinak cryptoerror(LOG_STDERR, gettext( 10417Sdinak "Unable to create PKCS#12 certificate bag.")); 10517Sdinak (*failures)++; 10617Sdinak return (-1); 10717Sdinak } 10817Sdinak 10917Sdinak /* Add the cert corresponding to private key to bag_stack. */ 11017Sdinak if (cert) { 11117Sdinak /* Convert cert from X509 struct to PKCS#12 bag */ 11217Sdinak cryptodebug("adding certificate to PKCS#12 safebag"); 11317Sdinak bag = PKCS12_x5092certbag(cert); 11417Sdinak if (bag == NULL) { 11517Sdinak cryptoerror(LOG_STDERR, gettext( 11617Sdinak "Unable to convert certificate to " 11717Sdinak "PKCS#12 bag.")); 11817Sdinak /* Cleanup the safebag. */ 11917Sdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, 12017Sdinak PKCS12_SAFEBAG_free); 12117Sdinak (*failures)++; 12217Sdinak return (-1); 12317Sdinak } 12417Sdinak 12517Sdinak /* Add the key id to the certificate bag. */ 12617Sdinak cryptodebug("add key id to PKCS#12 safebag"); 12717Sdinak if (!PKCS12_add_localkeyid(bag, id, id_len)) 12817Sdinak cryptodebug("error not caught"); 12917Sdinak 13017Sdinak /* Add the friendly name to the certificate bag. */ 13117Sdinak if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) { 13217Sdinak cryptodebug( 13317Sdinak "label PKCS#12 safebag with friendly name"); 13417Sdinak if (!PKCS12_add_friendlyname(bag, (char *)lab, 13517Sdinak lab_len)) 13617Sdinak cryptodebug("error not caught"); 13717Sdinak } 13817Sdinak 13917Sdinak /* Pile it on the bag_stack. */ 14017Sdinak if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 14117Sdinak cryptodebug("error not caught"); 14217Sdinak 14317Sdinak n_writes++; 14417Sdinak } 14517Sdinak 14617Sdinak /* Add all the CA chain certs to the bag_stack. */ 14717Sdinak if (ca_certs) { 14817Sdinak cryptodebug("adding CA certificate chain to PKCS#12 " 14917Sdinak "safebag"); 15017Sdinak /* 15117Sdinak * Go through the stack of CA certs, converting each 15217Sdinak * one to a PKCS#12 bag and piling them onto the 15317Sdinak * bag_stack. 15417Sdinak */ 15517Sdinak for (i = 0; i < sk_X509_num(ca_certs); i++) { 15617Sdinak /* 15717Sdinak * sk_X509_value() is macro that embeds a 15817Sdinak * cast to (X509 *). Here it translates 15917Sdinak * into ((X509 *)sk_value((ca_certs), (i))). 16017Sdinak * Lint is complaining about the embedded 16117Sdinak * casting, and to fix it, you need to fix 16217Sdinak * openssl header files. 16317Sdinak */ 16417Sdinak /* LINTED E_BAD_PTR_CAST_ALIGN */ 16517Sdinak ca = sk_X509_value(ca_certs, i); 16617Sdinak 16717Sdinak /* Convert CA cert to PKCS#12 bag. */ 16817Sdinak cryptodebug("adding CA certificate #%d " 16917Sdinak "to PKCS#12 safebag", i+1); 17017Sdinak bag = PKCS12_x5092certbag(ca); 17117Sdinak if (bag == NULL) { 17217Sdinak cryptoerror(LOG_STDERR, gettext( 17317Sdinak "Unable to convert CA certificate " 17417Sdinak "#%d to PKCS#12 bag."), i+1); 17517Sdinak /* Cleanup the safebag. */ 17617Sdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, 17717Sdinak PKCS12_SAFEBAG_free); 17817Sdinak (*failures)++; 17917Sdinak return (-1); 18017Sdinak } 18117Sdinak 18217Sdinak /* Note CA certs do not have friendly name. */ 18317Sdinak 18417Sdinak /* Pile it onto the bag_stack. */ 18517Sdinak if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 18617Sdinak cryptodebug("error not caught"); 18717Sdinak 18817Sdinak n_writes++; 18917Sdinak } 19017Sdinak } 19117Sdinak 19217Sdinak /* Turn bag_stack of certs into encrypted authsafe. */ 19317Sdinak cryptodebug("encrypt certificate PKCS#12 bag into " 19417Sdinak "PKCS#7 authsafe"); 19517Sdinak cert_authsafe = PKCS12_pack_p7encdata( 19617Sdinak NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL, 19717Sdinak 0, PKCS12_DEFAULT_ITER, bag_stack); 19817Sdinak 19917Sdinak /* Clear away this bag_stack, we're done with it. */ 20017Sdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 20117Sdinak bag_stack = NULL; 20217Sdinak 20317Sdinak if (cert_authsafe == NULL) { 20417Sdinak cryptoerror(LOG_STDERR, gettext( 20517Sdinak "Unable to PKCS#7-encrypt certificate bag.")); 20617Sdinak (*failures)++; 20717Sdinak return (-1); 20817Sdinak } 20917Sdinak } 21017Sdinak 21117Sdinak /* 21217Sdinak * Section 2: 21317Sdinak * 21417Sdinak * The second PKCS#12 container (safebag) will hold the private key 21517Sdinak * that goes with the certificates above. The results of this section 21617Sdinak * is an unencrypted PKCS#7 container (authsafe). If there is no 21717Sdinak * private key, there is no point in creating the "safebag" or the 21817Sdinak * "authsafe" so we go to the next section. 21917Sdinak */ 22017Sdinak if (priv_key != NULL) { 22117Sdinak /* Make a PKCS#8 shrouded key bag. */ 22217Sdinak cryptodebug("create PKCS#8 shrouded key out of private key"); 22317Sdinak p8 = EVP_PKEY2PKCS8(priv_key); 22417Sdinak if (p8 == NULL) { 22517Sdinak cryptoerror(LOG_STDERR, gettext( 22617Sdinak "Unable to create PKCS#8 shrouded key for " 22717Sdinak "private key.")); 22817Sdinak (*failures)++; 22917Sdinak return (-1); 23017Sdinak } 23117Sdinak 23217Sdinak /* Put the shrouded key into a PKCS#12 bag. */ 23317Sdinak cryptodebug("convert shrouded key to PKCS#12 bag"); 23417Sdinak bag = PKCS12_MAKE_SHKEYBAG( 23517Sdinak NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin, 23617Sdinak -1, NULL, 0, PKCS12_DEFAULT_ITER, p8); 23717Sdinak 23817Sdinak /* Clean up the PKCS#8 shrouded key, don't need it now. */ 23917Sdinak PKCS8_PRIV_KEY_INFO_free(p8); 24017Sdinak p8 = NULL; 24117Sdinak 24217Sdinak if (bag == NULL) { 24317Sdinak cryptoerror(LOG_STDERR, gettext( 24417Sdinak "Unable to convert private key to PKCS#12 bag.")); 24517Sdinak (*failures)++; 24617Sdinak return (-1); 24717Sdinak } 24817Sdinak 24917Sdinak /* Add the key id to the certificate bag. */ 25017Sdinak cryptodebug("add key id to PKCS#12 safebag"); 25117Sdinak if (!PKCS12_add_localkeyid(bag, id, id_len)) 25217Sdinak cryptodebug("error not caught"); 25317Sdinak 25417Sdinak /* Add the cert friendly name to the private key bag. */ 25517Sdinak if (lab != NULL) { 25617Sdinak cryptodebug("label PKCS#12 safebag with friendly name"); 25717Sdinak if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len)) 25817Sdinak cryptodebug("error not caught"); 25917Sdinak } 26017Sdinak 26117Sdinak /* Start a PKCS#12 safebag container for the private key. */ 26217Sdinak cryptodebug("creating private key PKCS#12 safebag"); 26317Sdinak bag_stack = sk_PKCS12_SAFEBAG_new_null(); 26417Sdinak if (bag_stack == NULL) { 26517Sdinak cryptoerror(LOG_STDERR, gettext( 26617Sdinak "Unable to create PKCS#12 private key bag.")); 26717Sdinak (*failures)++; 26817Sdinak return (-1); 26917Sdinak } 27017Sdinak 27117Sdinak /* Pile on the private key on the bag_stack. */ 27217Sdinak if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) 27317Sdinak cryptodebug("error not caught"); 27417Sdinak 27517Sdinak /* Turn bag_stack with private key into unencrypted authsafe. */ 27617Sdinak cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe"); 27717Sdinak key_authsafe = PKCS12_pack_p7data(bag_stack); 27817Sdinak 27917Sdinak /* Clear away this bag_stack, we're done with it. */ 28017Sdinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); 28117Sdinak bag_stack = NULL; 28217Sdinak 28317Sdinak if (key_authsafe == NULL) { 28417Sdinak cryptoerror(LOG_STDERR, gettext( 28517Sdinak "Unable to PKCS#7-convert private key bag.")); 28617Sdinak (*failures)++; 28717Sdinak return (-1); 28817Sdinak } 28917Sdinak 29017Sdinak n_writes++; 29117Sdinak } 29217Sdinak 29317Sdinak /* 29417Sdinak * Section 3: 29517Sdinak * 29617Sdinak * This is where the two PKCS#7 containers, one for the certificates 29717Sdinak * and one for the private key, are put together into a PKCS#12 29817Sdinak * element. This final PKCS#12 element is written to the export file. 29917Sdinak */ 30017Sdinak /* Start a PKCS#7 stack. */ 30117Sdinak cryptodebug("create PKCS#7 authsafe for private key and certificates"); 30217Sdinak authsafe_stack = sk_PKCS7_new_null(); 30317Sdinak if (authsafe_stack == NULL) { 30417Sdinak cryptoerror(LOG_STDERR, gettext( 30517Sdinak "Unable to create PKCS#7 container for private key " 30617Sdinak "and certificates.")); 30717Sdinak (*failures)++; 30817Sdinak return (-1); 30917Sdinak } 31017Sdinak 31117Sdinak /* Put certificates and private key into PKCS#7 stack. */ 31217Sdinak if (key_authsafe != NULL) { 31317Sdinak cryptodebug("put private key authsafe into PKCS#7 container"); 31417Sdinak if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) 31517Sdinak cryptodebug("error not caught"); 31617Sdinak } 31717Sdinak if (cert_authsafe != NULL) { 31817Sdinak cryptodebug("put certificate authsafe into PKCS#7 container"); 31917Sdinak if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) 32017Sdinak cryptodebug("error not caught"); 32117Sdinak } 32217Sdinak 32317Sdinak /* Create PKCS#12 element out of PKCS#7 stack. */ 32417Sdinak cryptodebug("create PKCS#12 element for export file"); 32517Sdinak p12_elem = PKCS12_init(NID_pkcs7_data); 32617Sdinak if (p12_elem == NULL) { 32717Sdinak cryptoerror(LOG_STDERR, gettext( 32817Sdinak "Unable to create PKCS#12 element for export file.")); 32917Sdinak sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 33017Sdinak (*failures)++; 33117Sdinak return (-1); 33217Sdinak } 33317Sdinak 33417Sdinak /* Put the PKCS#7 stack into the PKCS#12 element. */ 33517Sdinak if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) 33617Sdinak cryptodebug("error not caught"); 33717Sdinak 33817Sdinak /* Clear away the PKCS#7 stack, we're done with it. */ 33917Sdinak sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); 34017Sdinak authsafe_stack = NULL; 34117Sdinak 34217Sdinak /* Set the integrity MAC on the PKCS#12 element. */ 34317Sdinak cryptodebug("setting MAC for PKCS#12 element"); 34417Sdinak if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0, 34517Sdinak PKCS12_DEFAULT_ITER, NULL)) 34617Sdinak cryptodebug("error not caught"); 34717Sdinak 34817Sdinak /* Write the PKCS#12 element to the export file. */ 34917Sdinak cryptodebug("writing PKCS#12 element to export file"); 35017Sdinak if (!i2d_PKCS12_bio(fbio, p12_elem)) 35117Sdinak cryptodebug("error not caught"); 35217Sdinak 35317Sdinak (*successes) += n_writes; 35417Sdinak 35517Sdinak /* Clear away the PKCS#12 element. */ 35617Sdinak PKCS12_free(p12_elem); 35717Sdinak return (0); 35817Sdinak } 35917Sdinak 36017Sdinak /* 36117Sdinak * Get token objects: private key, its cert, and its cert chain. 36217Sdinak */ 36317Sdinak static CK_RV 36417Sdinak get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, 36517Sdinak CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain, 36617Sdinak CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len) 36717Sdinak { 36817Sdinak CK_RV rv = CKR_OK; 36917Sdinak CK_ATTRIBUTE keyid_attr[1] = { 37017Sdinak { CKA_ID, NULL, 0 } 37117Sdinak }; 37217Sdinak static CK_OBJECT_CLASS class = CKO_CERTIFICATE; 37317Sdinak static CK_CERTIFICATE_TYPE certtype = CKC_X_509; 37417Sdinak CK_ATTRIBUTE cert_attr[4] = { 37517Sdinak { CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) }, 37617Sdinak { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) }, 37717Sdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 37817Sdinak { CKA_ID, NULL, 0 } 37917Sdinak }; 38017Sdinak CK_ULONG num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE); 38117Sdinak CK_OBJECT_HANDLE cert = ~0UL; 38217Sdinak CK_ULONG num = 0; 38317Sdinak 38417Sdinak cryptodebug("inside get_token_objs"); 38517Sdinak 38617Sdinak /* Get the size of the object's CKA_ID field first. */ 38717Sdinak cryptodebug("getting CKA_ID size for object 0x%x", obj); 38817Sdinak if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) { 38917Sdinak cryptoerror(LOG_STDERR, gettext("Unable to get size of object" 39017Sdinak " key id (%s)."), pkcs11_strerror(rv)); 39117Sdinak return (rv); 39217Sdinak } 39317Sdinak 39417Sdinak /* Allocate the space needed for the key id. */ 39517Sdinak if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) { 39617Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 39717Sdinak return (CKR_HOST_MEMORY); 39817Sdinak } 39917Sdinak 40017Sdinak /* Get the CKA_ID field to match obj with its cert. */ 40117Sdinak cryptodebug("getting CKA_ID attribute for object 0x%x", obj); 40217Sdinak if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) { 40317Sdinak cryptoerror(LOG_STDERR, gettext("Unable to get object " 40417Sdinak "key id (%s)."), pkcs11_strerror(rv)); 40517Sdinak free(keyid_attr[0].pValue); 40617Sdinak return (rv); 40717Sdinak } 40817Sdinak 40917Sdinak /* Now try to find any certs that have the same id. */ 41017Sdinak cryptodebug("searching for certificates with same CKA_ID"); 41117Sdinak cert_attr[3].pValue = keyid_attr[0].pValue; 41217Sdinak cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen; 41317Sdinak if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) { 41417Sdinak cryptoerror(LOG_STDERR, gettext("Unable to initialize " 41517Sdinak "certificate search (%s)."), pkcs11_strerror(rv)); 41617Sdinak free(keyid_attr[0].pValue); 41717Sdinak return (rv); 41817Sdinak } 41917Sdinak 42017Sdinak /* Find the first cert that matches the key id. */ 42117Sdinak if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) { 42217Sdinak cryptoerror(LOG_STDERR, gettext("Certificate search failed " 42317Sdinak "(%s)."), pkcs11_strerror(rv)); 42417Sdinak free(keyid_attr[0].pValue); 42517Sdinak return (rv); 42617Sdinak } 42717Sdinak 42817Sdinak (void) C_FindObjectsFinal(sess); 42917Sdinak 43017Sdinak *id = keyid_attr[0].pValue; 43117Sdinak *id_len = keyid_attr[0].ulValueLen; 43217Sdinak 43317Sdinak *mate = (num == 1) ? cert : ~0UL; 43417Sdinak 43517Sdinak /* We currently do not find all the certs in the chain. */ 43617Sdinak *chain_len = 0; 43717Sdinak *chain = NULL; 43817Sdinak 43917Sdinak return (CKR_OK); 44017Sdinak } 44117Sdinak 44217Sdinak /* 44317Sdinak * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM. 44417Sdinak * "to" should be the address of a ptr init'ed to NULL to 44517Sdinak * receive the BIGNUM, e.g., 44617Sdinak * biginteger_t from; 44717Sdinak * BIGNUM *foo = NULL; 44817Sdinak * cvt_bigint2bn(&from, &foo); 44917Sdinak */ 45017Sdinak static int 45117Sdinak cvt_bigint2bn(biginteger_t *from, BIGNUM **to) 45217Sdinak { 45317Sdinak BIGNUM *temp = NULL; 45417Sdinak 45517Sdinak cryptodebug("inside cvt_bigint2bn"); 45617Sdinak 45717Sdinak if (from == NULL || to == NULL) 45817Sdinak return (-1); 45917Sdinak 46017Sdinak cryptodebug("calling BN_bin2bn"); 46117Sdinak if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) == 46217Sdinak NULL) 46317Sdinak return (-1); 46417Sdinak 46517Sdinak *to = temp; 46617Sdinak return (0); 46717Sdinak } 46817Sdinak 46917Sdinak /* 47017Sdinak * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure. 47117Sdinak */ 47217Sdinak static CK_RV 47317Sdinak cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 47417Sdinak { 47517Sdinak CK_RV rv = CKR_OK; 47617Sdinak EVP_PKEY *key = NULL; /* OpenSSL representation */ 47717Sdinak RSA *rsa = NULL; /* OpenSSL representation */ 47817Sdinak biginteger_t mod = { NULL, 0 }; /* required */ 47917Sdinak biginteger_t pubexp = { NULL, 0 }; /* required */ 48017Sdinak biginteger_t priexp = { NULL, 0 }; /* optional */ 48117Sdinak biginteger_t prime1 = { NULL, 0 }; /* optional */ 48217Sdinak biginteger_t prime2 = { NULL, 0 }; /* optional */ 48317Sdinak biginteger_t exp1 = { NULL, 0 }; /* optional */ 48417Sdinak biginteger_t exp2 = { NULL, 0 }; /* optional */ 48517Sdinak biginteger_t coef = { NULL, 0 }; /* optional */ 48617Sdinak CK_ATTRIBUTE rsa_pri_attrs[8] = { 48717Sdinak { CKA_MODULUS, NULL, 0 }, 48817Sdinak { CKA_PUBLIC_EXPONENT, NULL, 0 }, 48917Sdinak { CKA_PRIVATE_EXPONENT, NULL, 0 }, /* optional */ 49017Sdinak { CKA_PRIME_1, NULL, 0 }, /* | */ 49117Sdinak { CKA_PRIME_2, NULL, 0 }, /* | */ 49217Sdinak { CKA_EXPONENT_1, NULL, 0 }, /* | */ 49317Sdinak { CKA_EXPONENT_2, NULL, 0 }, /* | */ 49417Sdinak { CKA_COEFFICIENT, NULL, 0 } /* V */ 49517Sdinak }; 49617Sdinak CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE); 49717Sdinak int i; 49817Sdinak 49917Sdinak cryptodebug("inside cvt_rsa2evp_pkey"); 50017Sdinak 50117Sdinak cryptodebug("calling RSA_new"); 50217Sdinak if ((rsa = RSA_new()) == NULL) { 50317Sdinak cryptoerror(LOG_STDERR, gettext( 50417Sdinak "Unable to allocate internal RSA structure.")); 50517Sdinak return (CKR_HOST_MEMORY); 50617Sdinak } 50717Sdinak 50817Sdinak /* Get the sizes of the attributes we need. */ 50917Sdinak cryptodebug("calling C_GetAttributeValue for size info"); 51017Sdinak if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != 51117Sdinak CKR_OK) { 51217Sdinak cryptoerror(LOG_STDERR, gettext( 51317Sdinak "Unable to get RSA private key attribute sizes (%s)."), 51417Sdinak pkcs11_strerror(rv)); 51517Sdinak return (rv); 51617Sdinak } 51717Sdinak 51817Sdinak /* Allocate memory for each attribute. */ 51917Sdinak for (i = 0; i < count; i++) { 52017Sdinak if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || 52117Sdinak rsa_pri_attrs[i].ulValueLen == 0) { 52217Sdinak cryptodebug("cvt_rsa2evp_pkey: *** should not happen"); 52317Sdinak rsa_pri_attrs[i].ulValueLen = 0; 52417Sdinak continue; 52517Sdinak } 52617Sdinak if ((rsa_pri_attrs[i].pValue = 52717Sdinak malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) { 52817Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 52917Sdinak return (CKR_HOST_MEMORY); 53017Sdinak } 53117Sdinak } 53217Sdinak 53317Sdinak /* Now really get the attributes. */ 53417Sdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 53517Sdinak if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != 53617Sdinak CKR_OK) { 53717Sdinak cryptoerror(LOG_STDERR, gettext( 53817Sdinak "Unable to get RSA private key attributes (%s)."), 53917Sdinak pkcs11_strerror(rv)); 54017Sdinak return (rv); 54117Sdinak } 54217Sdinak 54317Sdinak /* 54417Sdinak * Fill in all the temp variables. Modulus and public exponent 54517Sdinak * are required. The rest are optional. 54617Sdinak */ 54717Sdinak i = 0; 54817Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod); 54917Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp); 55017Sdinak 55117Sdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 55217Sdinak rsa_pri_attrs[i].ulValueLen != 0) 55317Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp); 55417Sdinak i++; 55517Sdinak 55617Sdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 55717Sdinak rsa_pri_attrs[i].ulValueLen != 0) 55817Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1); 55917Sdinak i++; 56017Sdinak 56117Sdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 56217Sdinak rsa_pri_attrs[i].ulValueLen != 0) 56317Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2); 56417Sdinak i++; 56517Sdinak 56617Sdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 56717Sdinak rsa_pri_attrs[i].ulValueLen != 0) 56817Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1); 56917Sdinak i++; 57017Sdinak 57117Sdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 57217Sdinak rsa_pri_attrs[i].ulValueLen != 0) 57317Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2); 57417Sdinak i++; 57517Sdinak 57617Sdinak if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && 57717Sdinak rsa_pri_attrs[i].ulValueLen != 0) 57817Sdinak copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef); 57917Sdinak i++; 58017Sdinak 58117Sdinak /* Start the conversion to internal OpenSSL RSA structure. */ 58217Sdinak 58317Sdinak /* Modulus n */ 58417Sdinak if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) { 58517Sdinak cryptoerror(LOG_STDERR, gettext( 58617Sdinak "Unable to convert RSA private key modulus.")); 58717Sdinak return (CKR_GENERAL_ERROR); 58817Sdinak } 58917Sdinak 59017Sdinak /* Public exponent e */ 59117Sdinak if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) { 59217Sdinak cryptoerror(LOG_STDERR, gettext( 59317Sdinak "Unable to convert RSA private key public exponent.")); 59417Sdinak return (CKR_GENERAL_ERROR); 59517Sdinak } 59617Sdinak 59717Sdinak /* Private exponent e */ 59817Sdinak if (priexp.big_value != NULL) { 59917Sdinak if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) { 60017Sdinak cryptoerror(LOG_STDERR, gettext("Unable to convert " 60117Sdinak "RSA private key private exponent.")); 60217Sdinak return (CKR_GENERAL_ERROR); 60317Sdinak } 60417Sdinak } else 60517Sdinak cryptodebug("no RSA private key private exponent"); 60617Sdinak 60717Sdinak /* Prime p */ 60817Sdinak if (prime1.big_value != NULL) { 60917Sdinak if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) { 61017Sdinak cryptoerror(LOG_STDERR, gettext( 61117Sdinak "Unable to convert RSA private key prime 1.")); 61217Sdinak return (CKR_GENERAL_ERROR); 61317Sdinak } 61417Sdinak } else 61517Sdinak cryptodebug("no RSA private key prime 1"); 61617Sdinak 61717Sdinak /* Prime q */ 61817Sdinak if (prime2.big_value != NULL) { 61917Sdinak if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) { 62017Sdinak cryptoerror(LOG_STDERR, gettext( 62117Sdinak "Unable to convert RSA private key prime 2.")); 62217Sdinak return (CKR_GENERAL_ERROR); 62317Sdinak } 62417Sdinak } else 62517Sdinak cryptodebug("no RSA private key prime 2"); 62617Sdinak 62717Sdinak /* Private exponent d modulo p-1 */ 62817Sdinak if (exp1.big_value != NULL) { 62917Sdinak if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) { 63017Sdinak cryptoerror(LOG_STDERR, gettext( 63117Sdinak "Unable to convert RSA private key exponent 1.")); 63217Sdinak return (CKR_GENERAL_ERROR); 63317Sdinak } 63417Sdinak } else 63517Sdinak cryptodebug("no RSA private key exponent 1"); 63617Sdinak 63717Sdinak /* Private exponent d modulo q-1 */ 63817Sdinak if (exp2.big_value != NULL) { 63917Sdinak if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) { 64017Sdinak cryptoerror(LOG_STDERR, gettext( 64117Sdinak "Unable to convert RSA private key exponent 2.")); 64217Sdinak return (CKR_GENERAL_ERROR); 64317Sdinak } 64417Sdinak } else 64517Sdinak cryptodebug("no RSA private key exponent 2"); 64617Sdinak 64717Sdinak /* CRT coefficient q-inverse mod p */ 64817Sdinak if (coef.big_value != NULL) { 64917Sdinak if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) { 65017Sdinak cryptoerror(LOG_STDERR, gettext( 65117Sdinak "Unable to convert RSA private key coefficient.")); 65217Sdinak return (CKR_GENERAL_ERROR); 65317Sdinak } 65417Sdinak } else 65517Sdinak cryptodebug("no RSA private key coefficient"); 65617Sdinak 65717Sdinak /* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */ 65817Sdinak cryptodebug("calling EVP_PKEY_new"); 65917Sdinak if ((key = EVP_PKEY_new()) == NULL) { 66017Sdinak cryptoerror(LOG_STDERR, gettext( 66117Sdinak "Unable to allocate internal EVP_PKEY structure.")); 66217Sdinak return (CKR_HOST_MEMORY); 66317Sdinak } 66417Sdinak 66517Sdinak /* Put the RSA struct into the EVP_PKEY struct and return it. */ 66617Sdinak cryptodebug("calling EVP_PKEY_set1_RSA"); 66717Sdinak (void) EVP_PKEY_set1_RSA(key, rsa); 66817Sdinak 66917Sdinak *pk = key; 67017Sdinak return (CKR_OK); 67117Sdinak } 67217Sdinak 67317Sdinak /* 67417Sdinak * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure. 67517Sdinak */ 67617Sdinak static CK_RV 67717Sdinak cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 67817Sdinak { 67917Sdinak CK_RV rv = CKR_OK; 68017Sdinak EVP_PKEY *key = NULL; /* OpenSSL representation */ 68117Sdinak DSA *dsa = NULL; /* OpenSSL representation */ 68217Sdinak biginteger_t prime = { NULL, 0 }; /* required */ 68317Sdinak biginteger_t subprime = { NULL, 0 }; /* required */ 68417Sdinak biginteger_t base = { NULL, 0 }; /* required */ 68517Sdinak biginteger_t value = { NULL, 0 }; /* required */ 68617Sdinak CK_ATTRIBUTE dsa_pri_attrs[4] = { 68717Sdinak { CKA_PRIME, NULL, 0 }, 68817Sdinak { CKA_SUBPRIME, NULL, 0 }, 68917Sdinak { CKA_BASE, NULL, 0 }, 69017Sdinak { CKA_VALUE, NULL, 0 } 69117Sdinak }; 69217Sdinak CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE); 69317Sdinak int i; 69417Sdinak 69517Sdinak cryptodebug("inside cvt_dsa2evp_pkey"); 69617Sdinak 69717Sdinak cryptodebug("calling DSA_new"); 69817Sdinak if ((dsa = DSA_new()) == NULL) { 69917Sdinak cryptoerror(LOG_STDERR, gettext( 70017Sdinak "Unable to allocate internal DSA structure.")); 70117Sdinak return (CKR_HOST_MEMORY); 70217Sdinak } 70317Sdinak 70417Sdinak /* Get the sizes of the attributes we need. */ 70517Sdinak cryptodebug("calling C_GetAttributeValue for size info"); 70617Sdinak if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) != 70717Sdinak CKR_OK) { 70817Sdinak cryptoerror(LOG_STDERR, gettext( 70917Sdinak "Unable to get DSA private key object attributes (%s)."), 71017Sdinak pkcs11_strerror(rv)); 71117Sdinak return (rv); 71217Sdinak } 71317Sdinak 71417Sdinak /* Allocate memory for each attribute. */ 71517Sdinak for (i = 0; i < count; i++) { 71617Sdinak if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || 71717Sdinak dsa_pri_attrs[i].ulValueLen == 0) { 71817Sdinak cryptodebug("cvt_dsa2evp_pkey: *** should not happen"); 71917Sdinak dsa_pri_attrs[i].ulValueLen = 0; 72017Sdinak continue; 72117Sdinak } 72217Sdinak if ((dsa_pri_attrs[i].pValue = 72317Sdinak malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) { 72417Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 72517Sdinak return (CKR_HOST_MEMORY); 72617Sdinak } 72717Sdinak } 72817Sdinak 72917Sdinak /* Now really get the attributes. */ 73017Sdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 73117Sdinak if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) != 73217Sdinak CKR_OK) { 73317Sdinak cryptoerror(LOG_STDERR, gettext( 73417Sdinak "Unable to get DSA private key attributes (%s)."), 73517Sdinak pkcs11_strerror(rv)); 73617Sdinak return (rv); 73717Sdinak } 73817Sdinak 73917Sdinak /* Fill in all the temp variables. They are all required. */ 74017Sdinak i = 0; 74117Sdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime); 74217Sdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime); 74317Sdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base); 74417Sdinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value); 74517Sdinak 74617Sdinak /* Start the conversion to internal OpenSSL DSA structure. */ 74717Sdinak 74817Sdinak /* Prime p */ 74917Sdinak if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) { 75017Sdinak cryptoerror(LOG_STDERR, gettext( 75117Sdinak "Unable to convert DSA private key prime.")); 75217Sdinak return (CKR_GENERAL_ERROR); 75317Sdinak } 75417Sdinak 75517Sdinak /* Subprime q */ 75617Sdinak if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) { 75717Sdinak cryptoerror(LOG_STDERR, gettext( 75817Sdinak "Unable to convert DSA private key subprime.")); 75917Sdinak return (CKR_GENERAL_ERROR); 76017Sdinak } 76117Sdinak 76217Sdinak /* Base g */ 76317Sdinak if (cvt_bigint2bn(&base, &(dsa->g)) < 0) { 76417Sdinak cryptoerror(LOG_STDERR, gettext( 76517Sdinak "Unable to convert DSA private key base.")); 76617Sdinak return (CKR_GENERAL_ERROR); 76717Sdinak } 76817Sdinak 76917Sdinak /* Private key x */ 77017Sdinak if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) { 77117Sdinak cryptoerror(LOG_STDERR, gettext( 77217Sdinak "Unable to convert DSA private key value.")); 77317Sdinak return (CKR_GENERAL_ERROR); 77417Sdinak } 77517Sdinak 77617Sdinak /* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */ 77717Sdinak cryptodebug("calling EVP_PKEY_new"); 77817Sdinak if ((key = EVP_PKEY_new()) == NULL) { 77917Sdinak cryptoerror(LOG_STDERR, gettext( 78017Sdinak "Unable to allocate internal EVP_PKEY structure.")); 78117Sdinak return (CKR_HOST_MEMORY); 78217Sdinak } 78317Sdinak 78417Sdinak /* Put the DSA struct into the EVP_PKEY struct and return it. */ 78517Sdinak cryptodebug("calling EVP_PKEY_set1_DSA"); 78617Sdinak (void) EVP_PKEY_set1_DSA(key, dsa); 78717Sdinak 78817Sdinak *pk = key; 78917Sdinak return (CKR_OK); 79017Sdinak } 79117Sdinak 79217Sdinak /* 79317Sdinak * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure. 79417Sdinak */ 79517Sdinak static CK_RV 79617Sdinak cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 79717Sdinak { 79817Sdinak CK_RV rv = CKR_OK; 79917Sdinak EVP_PKEY *key = NULL; /* OpenSSL representation */ 80017Sdinak DH *dh = NULL; /* OpenSSL representation */ 80117Sdinak biginteger_t prime = { NULL, 0 }; /* required */ 80217Sdinak biginteger_t base = { NULL, 0 }; /* required */ 80317Sdinak biginteger_t value = { NULL, 0 }; /* required */ 80417Sdinak CK_ATTRIBUTE dh_pri_attrs[3] = { 80517Sdinak { CKA_PRIME, NULL, 0 }, 80617Sdinak { CKA_BASE, NULL, 0 }, 80717Sdinak { CKA_VALUE, NULL, 0 } 80817Sdinak }; 80917Sdinak CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE); 81017Sdinak int i; 81117Sdinak 81217Sdinak cryptodebug("inside cvt_dh2evp_pkey"); 81317Sdinak 81417Sdinak cryptodebug("calling DH_new"); 81517Sdinak if ((dh = DH_new()) == NULL) { 81617Sdinak cryptoerror(LOG_STDERR, gettext( 81717Sdinak "Unable to allocate internal DH structure.")); 81817Sdinak return (CKR_HOST_MEMORY); 81917Sdinak } 82017Sdinak 82117Sdinak /* Get the sizes of the attributes we need. */ 82217Sdinak cryptodebug("calling C_GetAttributeValue for size info"); 82317Sdinak if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) != 82417Sdinak CKR_OK) { 82517Sdinak cryptoerror(LOG_STDERR, gettext( 82617Sdinak "Unable to get DH private key object attributes (%s)."), 82717Sdinak pkcs11_strerror(rv)); 82817Sdinak return (rv); 82917Sdinak } 83017Sdinak 83117Sdinak /* Allocate memory for each attribute. */ 83217Sdinak for (i = 0; i < count; i++) { 83317Sdinak if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || 83417Sdinak dh_pri_attrs[i].ulValueLen == 0) { 83517Sdinak cryptodebug("cvt_dh2evp_pkey: ***should not happen"); 83617Sdinak dh_pri_attrs[i].ulValueLen = 0; 83717Sdinak continue; 83817Sdinak } 83917Sdinak if ((dh_pri_attrs[i].pValue = 84017Sdinak malloc(dh_pri_attrs[i].ulValueLen)) == NULL) { 84117Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 84217Sdinak return (CKR_HOST_MEMORY); 84317Sdinak } 84417Sdinak } 84517Sdinak 84617Sdinak /* Now really get the attributes. */ 84717Sdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 84817Sdinak if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) != 84917Sdinak CKR_OK) { 85017Sdinak cryptoerror(LOG_STDERR, gettext( 85117Sdinak "Unable to get DH private key attributes (%s)."), 85217Sdinak pkcs11_strerror(rv)); 85317Sdinak return (rv); 85417Sdinak } 85517Sdinak 85617Sdinak /* Fill in all the temp variables. They are all required. */ 85717Sdinak i = 0; 85817Sdinak copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime); 85917Sdinak copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base); 86017Sdinak copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value); 86117Sdinak 86217Sdinak /* Start the conversion to internal OpenSSL DH structure. */ 86317Sdinak 86417Sdinak /* Prime p */ 86517Sdinak if (cvt_bigint2bn(&prime, &(dh->p)) < 0) { 86617Sdinak cryptoerror(LOG_STDERR, gettext( 86717Sdinak "Unable to convert DH private key prime.")); 86817Sdinak return (CKR_GENERAL_ERROR); 86917Sdinak } 87017Sdinak 87117Sdinak /* Base g */ 87217Sdinak if (cvt_bigint2bn(&base, &(dh->g)) < 0) { 87317Sdinak cryptoerror(LOG_STDERR, gettext( 87417Sdinak "Unable to convert DH private key base.")); 87517Sdinak return (CKR_GENERAL_ERROR); 87617Sdinak } 87717Sdinak 87817Sdinak /* Private value x */ 87917Sdinak if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) { 88017Sdinak cryptoerror(LOG_STDERR, gettext( 88117Sdinak "Unable to convert DH private key value.")); 88217Sdinak return (CKR_GENERAL_ERROR); 88317Sdinak } 88417Sdinak 88517Sdinak /* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */ 88617Sdinak cryptodebug("calling EVP_PKEY_new"); 88717Sdinak if ((key = EVP_PKEY_new()) == NULL) { 88817Sdinak cryptoerror(LOG_STDERR, gettext( 88917Sdinak "Unable to allocate internal EVP_PKEY structure.")); 89017Sdinak return (CKR_HOST_MEMORY); 89117Sdinak } 89217Sdinak 89317Sdinak /* Put the DH struct into the EVP_PKEY struct and return it. */ 89417Sdinak cryptodebug("calling EVP_PKEY_set1_DH"); 89517Sdinak (void) EVP_PKEY_set1_DH(key, dh); 89617Sdinak 89717Sdinak *pk = key; 89817Sdinak return (CKR_OK); 89917Sdinak } 90017Sdinak 90117Sdinak /* 90217Sdinak * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure. 90317Sdinak */ 90417Sdinak static CK_RV 90517Sdinak cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) 90617Sdinak { 90717Sdinak CK_RV rv = CKR_OK; 90817Sdinak static CK_KEY_TYPE keytype = 0; 90917Sdinak CK_ATTRIBUTE keytype_attr[1] = { 91017Sdinak { CKA_KEY_TYPE, &keytype, sizeof (keytype) } 91117Sdinak }; 91217Sdinak 91317Sdinak cryptodebug("inside cvt_obj2evp_pkey"); 91417Sdinak 91517Sdinak /* Find out the key type to do the right conversion. */ 91617Sdinak cryptodebug("calling C_GetAttributeValue"); 91717Sdinak if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) != 91817Sdinak CKR_OK) { 91917Sdinak cryptoerror(LOG_STDERR, gettext( 92017Sdinak "Unable to get token object key type (%s)."), 92117Sdinak pkcs11_strerror(rv)); 92217Sdinak return (rv); 92317Sdinak } 92417Sdinak 92517Sdinak switch (keytype) { 92617Sdinak case CKK_RSA: 92717Sdinak cryptodebug("converting RSA key"); 92817Sdinak return (cvt_rsa2evp_pkey(sess, obj, pk)); 92917Sdinak case CKK_DSA: 93017Sdinak cryptodebug("converting DSA key"); 93117Sdinak return (cvt_dsa2evp_pkey(sess, obj, pk)); 93217Sdinak case CKK_DH: 93317Sdinak cryptodebug("converting DH key"); 93417Sdinak return (cvt_dh2evp_pkey(sess, obj, pk)); 93517Sdinak default: 93617Sdinak cryptoerror(LOG_STDERR, gettext( 93717Sdinak "Private key type 0x%02x conversion not supported."), 93817Sdinak keytype); 93917Sdinak return (CKR_GENERAL_ERROR); 94017Sdinak } 94117Sdinak } 94217Sdinak 94317Sdinak /* 94417Sdinak * Convert PKCS#11 certificate object to OpenSSL X509 structure. 94517Sdinak */ 94617Sdinak static CK_RV 94717Sdinak cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c) 94817Sdinak { 94917Sdinak CK_RV rv = CKR_OK; 95017Sdinak X509 *cert = NULL; /* OpenSSL representation */ 95117Sdinak X509 *temp_cert = NULL; 95217Sdinak CK_BYTE *subject = NULL; 95317Sdinak CK_ULONG subject_len = 0; 95417Sdinak CK_BYTE *value = NULL; 95517Sdinak CK_ULONG value_len = 0; 95617Sdinak CK_BYTE *label = NULL; 95717Sdinak CK_ULONG label_len = 0; 95817Sdinak CK_BYTE *id = NULL; 95917Sdinak CK_ULONG id_len = 0; 96017Sdinak CK_BYTE *issuer = NULL; 96117Sdinak CK_ULONG issuer_len = 0; 96217Sdinak CK_BYTE *serial = NULL; 96317Sdinak CK_ULONG serial_len = 0; 96417Sdinak CK_ATTRIBUTE cert_attrs[6] = { 96517Sdinak { CKA_SUBJECT, NULL, 0 }, /* required */ 96617Sdinak { CKA_VALUE, NULL, 0 }, /* required */ 96717Sdinak { CKA_LABEL, NULL, 0 }, /* optional */ 96817Sdinak { CKA_ID, NULL, 0 }, /* optional */ 96917Sdinak { CKA_ISSUER, NULL, 0 }, /* optional */ 97017Sdinak { CKA_SERIAL_NUMBER, NULL, 0 } /* optional */ 97117Sdinak }; 97217Sdinak CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE); 97317Sdinak int i = 0; 97417Sdinak X509_NAME *ssl_subject = NULL; 97517Sdinak X509_NAME *ssl_issuer = NULL; 97617Sdinak ASN1_INTEGER *ssl_serial = NULL; 97717Sdinak 97817Sdinak cryptodebug("inside cvt_cert2x509"); 97917Sdinak 98017Sdinak cryptodebug("calling X509_new"); 98117Sdinak if ((cert = X509_new()) == NULL) { 98217Sdinak cryptoerror(LOG_STDERR, gettext( 98317Sdinak "Unable to allocate internal X509 structure.")); 98417Sdinak return (CKR_HOST_MEMORY); 98517Sdinak } 98617Sdinak 98717Sdinak /* Get the sizes of the attributes we need. */ 98817Sdinak cryptodebug("calling C_GetAttributeValue for size info"); 98917Sdinak if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) != 99017Sdinak CKR_OK) { 99117Sdinak cryptoerror(LOG_STDERR, gettext( 99217Sdinak "Unable to get certificate attribute sizes (%s)."), 99317Sdinak pkcs11_strerror(rv)); 99417Sdinak return (rv); 99517Sdinak } 99617Sdinak 99717Sdinak /* Allocate memory for each attribute. */ 99817Sdinak for (i = 0; i < count; i++) { 99917Sdinak if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 || 100017Sdinak cert_attrs[i].ulValueLen == 0) { 100117Sdinak cryptodebug("cvt_cert2x509: *** should not happen"); 100217Sdinak cert_attrs[i].ulValueLen = 0; 100317Sdinak continue; 100417Sdinak } 100517Sdinak if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen)) 100617Sdinak == NULL) { 100717Sdinak cryptoerror(LOG_STDERR, "%s.", strerror(errno)); 100817Sdinak return (CKR_HOST_MEMORY); 100917Sdinak } 101017Sdinak } 101117Sdinak 101217Sdinak /* Now really get the attributes. */ 101317Sdinak cryptodebug("calling C_GetAttributeValue for attribute info"); 101417Sdinak if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) != 101517Sdinak CKR_OK) { 101617Sdinak cryptoerror(LOG_STDERR, gettext( 101717Sdinak "Unable to get certificate attributes (%s)."), 101817Sdinak pkcs11_strerror(rv)); 101917Sdinak return (rv); 102017Sdinak } 102117Sdinak 102217Sdinak /* 102317Sdinak * Fill in all the temp variables. Subject and value are required. 102417Sdinak * The rest are optional. 102517Sdinak */ 102617Sdinak i = 0; 102717Sdinak copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len); 102817Sdinak copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len); 102917Sdinak 103017Sdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 103117Sdinak cert_attrs[i].ulValueLen != 0) 103217Sdinak copy_attr_to_string(&(cert_attrs[i]), &label, &label_len); 103317Sdinak i++; 103417Sdinak 103517Sdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 103617Sdinak cert_attrs[i].ulValueLen != 0) 103717Sdinak copy_attr_to_string(&(cert_attrs[i]), &id, &id_len); 103817Sdinak i++; 103917Sdinak 104017Sdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 104117Sdinak cert_attrs[i].ulValueLen != 0) 104217Sdinak copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len); 104317Sdinak i++; 104417Sdinak 104517Sdinak if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && 104617Sdinak cert_attrs[i].ulValueLen != 0) 104717Sdinak copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len); 104817Sdinak i++; 104917Sdinak 105017Sdinak /* Start the conversion to internal OpenSSL X509 structure. */ 105117Sdinak 105217Sdinak /* Subject name (required) */ 105317Sdinak cryptodebug("calling d2i_X509_NAME for subject name"); 105417Sdinak if ((ssl_subject = d2i_X509_NAME(NULL, &subject, subject_len)) == 105517Sdinak NULL) { 105617Sdinak cryptoerror(LOG_STDERR, gettext( 105717Sdinak "Unable to convert certificate subject name.")); 105817Sdinak return (CKR_GENERAL_ERROR); 105917Sdinak } 106017Sdinak cryptodebug("calling X509_set_subject_name"); 106117Sdinak if (!X509_set_subject_name(cert, ssl_subject)) { 106217Sdinak cryptoerror(LOG_STDERR, gettext( 106317Sdinak "Unable to pack certificate subject name entries.")); 106417Sdinak return (CKR_GENERAL_ERROR); 106517Sdinak } 106617Sdinak 106717Sdinak /* Label (optional) */ 106817Sdinak cryptodebug("calling X509_alias_set1"); 106917Sdinak if (!X509_alias_set1(cert, label, label_len)) 107017Sdinak cryptodebug("error not caught"); 107117Sdinak 107217Sdinak /* Id (optional) */ 107317Sdinak cryptodebug("calling X509_keyid_set1"); 107417Sdinak if (!X509_keyid_set1(cert, id, id_len)) 107517Sdinak cryptodebug("error not caught"); 107617Sdinak 107717Sdinak /* Issuer name (optional) */ 107817Sdinak cryptodebug("calling d2i_X509_NAME for issuer name"); 107917Sdinak if ((ssl_issuer = d2i_X509_NAME(NULL, &issuer, issuer_len)) == NULL) { 108017Sdinak cryptoerror(LOG_STDERR, gettext( 108117Sdinak "Unable to convert certificate issuer name.")); 108217Sdinak return (CKR_GENERAL_ERROR); 108317Sdinak } 108417Sdinak cryptodebug("calling X509_set_issuer_name"); 108517Sdinak if (!X509_set_issuer_name(cert, ssl_issuer)) { 108617Sdinak cryptoerror(LOG_STDERR, gettext( 108717Sdinak "Unable to pack certificate issuer name entries.")); 108817Sdinak return (CKR_GENERAL_ERROR); 108917Sdinak } 109017Sdinak 109117Sdinak /* Serial number (optional) */ 1092*1837Sdinak cryptodebug("calling OPENSSL_malloc() for serial number"); 1093*1837Sdinak if ((ssl_serial = OPENSSL_malloc(sizeof (ASN1_INTEGER))) == NULL) { 109417Sdinak cryptoerror(LOG_STDERR, gettext( 109517Sdinak "Unable to convert certificate serial number.")); 1096*1837Sdinak return (CKR_HOST_MEMORY); 109717Sdinak } 1098*1837Sdinak ssl_serial->length = serial_len; 1099*1837Sdinak ssl_serial->type = (serial[0] & 0x80) ? V_ASN1_NEG_INTEGER : 1100*1837Sdinak V_ASN1_INTEGER; 1101*1837Sdinak ssl_serial->data = serial; 1102*1837Sdinak ssl_serial->flags = 0; 110317Sdinak cryptodebug("calling X509_set_serialNumber"); 110417Sdinak if (!X509_set_serialNumber(cert, ssl_serial)) 110517Sdinak cryptodebug("error not caught"); 110617Sdinak 110717Sdinak /* 110817Sdinak * Value (required) 110917Sdinak * 111017Sdinak * The rest of this code takes the CKA_VALUE attribute, converts 111117Sdinak * it into a temp OpenSSL X509 structure and picks out the rest 111217Sdinak * of the fields we need to convert it back into the current X509 111317Sdinak * structure that will get exported. The reason we don't just 111417Sdinak * start with CKA_VALUE is because while the object was in the 111517Sdinak * softtoken, it is possible that some of its attributes changed. 111617Sdinak * Those changes would not appear in CKA_VALUE and would be lost 111717Sdinak * if we started with CKA_VALUE that was saved originally. 111817Sdinak */ 111917Sdinak cryptodebug("calling d2i_X509 for cert value"); 112017Sdinak if ((temp_cert = d2i_X509(NULL, &value, value_len)) == NULL) { 112117Sdinak cryptoerror(LOG_STDERR, gettext( 112217Sdinak "Unable to convert main certificate values.")); 112317Sdinak return (CKR_GENERAL_ERROR); 112417Sdinak } 112517Sdinak 112617Sdinak /* Transfer these values from temp_cert to cert. */ 112717Sdinak cryptodebug("calling X509_set_version/X509_get_version"); 112817Sdinak if (!X509_set_version(cert, X509_get_version(temp_cert))) 112917Sdinak cryptodebug("error not caught"); 113017Sdinak 113117Sdinak cryptodebug("calling X509_set_notBefore/X509_get_notBefore"); 113217Sdinak if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert))) 113317Sdinak cryptodebug("error not caught"); 113417Sdinak 113517Sdinak cryptodebug("calling X509_set_notAfter/X509_get_notAfter"); 113617Sdinak if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert))) 113717Sdinak cryptodebug("error not caught"); 113817Sdinak 113917Sdinak cryptodebug("calling X509_set_pubkey/X509_get_pubkey"); 114017Sdinak if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert))) 114117Sdinak cryptodebug("error not caught"); 114217Sdinak 114317Sdinak /* 114417Sdinak * These don't get transfered from temp_cert to cert. 114517Sdinak * It -appears- that they may get regenerated as needed. 114617Sdinak * 114717Sdinak * cert->cert_info->signature = dup(temp_cert->cert_info->signature); 114817Sdinak * cert->sig_alg = dup(temp_cert->sig_alg); 114917Sdinak * cert->signature = dup(temp_cert->signature); 115017Sdinak * cert->skid = dup(temp_cert->skid); 115117Sdinak * cert->akid = dup(temp_cert->akid); 115217Sdinak */ 115317Sdinak 115417Sdinak *c = cert; 115517Sdinak return (CKR_OK); 115617Sdinak } 115717Sdinak 115817Sdinak static CK_RV 115917Sdinak convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, 116017Sdinak CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len, 116117Sdinak EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca) 116217Sdinak { 116317Sdinak CK_RV rv = CKR_OK; 116417Sdinak EVP_PKEY *pk = NULL; 116517Sdinak X509 *c = NULL; 116617Sdinak X509 *one_ca = NULL; 116717Sdinak STACK_OF(X509) *ch = NULL; 116817Sdinak int i; 116917Sdinak 117017Sdinak cryptodebug("inside convert_token_objs"); 117117Sdinak 117217Sdinak if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK) 117317Sdinak return (rv); 117417Sdinak 117517Sdinak if (mate != ~0UL) { 117617Sdinak cryptodebug("converting cert corresponding to private key"); 117717Sdinak if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK) 117817Sdinak return (rv); 117917Sdinak } 118017Sdinak 118117Sdinak if (chain_len != 0) { 118217Sdinak cryptodebug("converting ca chain of %d certs corresponding " 118317Sdinak "to private key", chain_len); 118417Sdinak ch = sk_X509_new_null(); 118517Sdinak for (i = 0; i < chain_len; i++) { 118617Sdinak if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) != 118717Sdinak CKR_OK) { 118817Sdinak return (rv); 118917Sdinak } 119017Sdinak if (!sk_X509_push(ch, one_ca)) 119117Sdinak cryptodebug("error not caught"); 119217Sdinak } 119317Sdinak } 119417Sdinak 119517Sdinak *priv_key = pk; 119617Sdinak *cert = (mate != ~0UL) ? c : NULL; 119717Sdinak *ca = (chain_len != 0) ? ch : NULL; 119817Sdinak return (CKR_OK); 119917Sdinak } 120017Sdinak 120117Sdinak /* 120217Sdinak * Export objects from token to PKCS#12 file. 120317Sdinak */ 120417Sdinak int 120517Sdinak pk_export(int argc, char *argv[]) 120617Sdinak { 1207864Sdinak int opt; 1208864Sdinak extern int optind_av; 1209864Sdinak extern char *optarg_av; 1210864Sdinak char *token_spec = NULL; 121117Sdinak char *token_name = NULL; 121217Sdinak char *manuf_id = NULL; 121317Sdinak char *serial_no = NULL; 121417Sdinak char full_name[FULL_NAME_LEN]; 121517Sdinak char *filename = NULL; 121617Sdinak CK_SLOT_ID slot_id; 121717Sdinak CK_FLAGS pin_state; 121817Sdinak CK_UTF8CHAR_PTR pin = NULL; 121917Sdinak CK_ULONG pinlen = 0; 122017Sdinak CK_UTF8CHAR_PTR pk12pin = NULL; 122117Sdinak CK_ULONG pk12pinlen = 0; 122217Sdinak CK_SESSION_HANDLE sess; 122317Sdinak BIO *fbio = NULL; 122417Sdinak EVP_PKEY *priv_key = NULL; 122517Sdinak X509 *cert = NULL; 122617Sdinak STACK_OF(X509) *ca = NULL; 122717Sdinak CK_RV rv = CKR_OK; 122817Sdinak CK_OBJECT_HANDLE *objs = NULL; 122917Sdinak CK_ULONG num_objs = 0; 123017Sdinak CK_OBJECT_HANDLE mate = ~0UL; 123117Sdinak CK_OBJECT_HANDLE *chain = NULL; 123217Sdinak CK_ULONG chain_len; 123317Sdinak CK_BYTE *id = NULL; 123417Sdinak CK_ULONG id_len = 0; 123517Sdinak int i = 0; 123617Sdinak int good_ones = 0, bad_ones = 0; /* running totals */ 123717Sdinak 123817Sdinak cryptodebug("inside pk_export"); 123917Sdinak 1240864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 1241864Sdinak while ((opt = getopt_av(argc, argv, "T:(token)o:(outfile)")) != EOF) { 1242864Sdinak switch (opt) { 1243864Sdinak case 'T': /* token specifier */ 1244864Sdinak if (token_spec) 1245864Sdinak return (PK_ERR_USAGE); 1246864Sdinak token_spec = optarg_av; 1247864Sdinak break; 1248864Sdinak case 'o': /* output file name */ 1249864Sdinak if (filename) 1250864Sdinak return (PK_ERR_USAGE); 1251864Sdinak filename = optarg_av; 1252864Sdinak break; 1253864Sdinak default: 1254864Sdinak return (PK_ERR_USAGE); 1255864Sdinak break; 1256864Sdinak } 1257864Sdinak } 125817Sdinak 1259864Sdinak /* If nothing is specified, default is to use softtoken. */ 1260864Sdinak if (token_spec == NULL) { 1261864Sdinak token_name = SOFT_TOKEN_LABEL; 1262864Sdinak manuf_id = SOFT_MANUFACTURER_ID; 1263864Sdinak serial_no = SOFT_TOKEN_SERIAL; 1264864Sdinak } else { 1265864Sdinak /* 1266864Sdinak * Parse token specifier into token_name, manuf_id, serial_no. 1267864Sdinak * Token_name is required; manuf_id and serial_no are optional. 1268864Sdinak */ 1269864Sdinak if (parse_token_spec(token_spec, &token_name, &manuf_id, 1270864Sdinak &serial_no) < 0) 1271864Sdinak return (PK_ERR_USAGE); 1272864Sdinak } 1273864Sdinak 1274864Sdinak /* Filename arg is required. */ 1275864Sdinak if (filename == NULL) 127617Sdinak return (PK_ERR_USAGE); 127717Sdinak 1278864Sdinak /* No additional args allowed. */ 1279864Sdinak argc -= optind_av; 1280864Sdinak argv += optind_av; 1281864Sdinak if (argc) 1282864Sdinak return (PK_ERR_USAGE); 128317Sdinak /* Done parsing command line options. */ 128417Sdinak 128517Sdinak /* Check if the file exists and might be overwritten. */ 128617Sdinak if (access(filename, F_OK) == 0) { 128717Sdinak cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, " 128817Sdinak "will be overwritten."), filename); 128917Sdinak if (yesno(gettext("Continue with export? "), 129017Sdinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { 129117Sdinak return (0); 129217Sdinak } 129317Sdinak } 129417Sdinak 129517Sdinak full_token_name(token_name, manuf_id, serial_no, full_name); 129617Sdinak 129717Sdinak /* Find the slot with token. */ 129817Sdinak if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, 129917Sdinak &pin_state)) != CKR_OK) { 130017Sdinak cryptoerror(LOG_STDERR, gettext( 130117Sdinak "Unable to find token %s (%s)."), full_name, 130217Sdinak pkcs11_strerror(rv)); 130317Sdinak return (PK_ERR_PK11); 130417Sdinak } 130517Sdinak 130617Sdinak /* Get the user's PIN. */ 130717Sdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, 130817Sdinak &pinlen)) != CKR_OK) { 130917Sdinak cryptoerror(LOG_STDERR, gettext( 131017Sdinak "Unable to get token passphrase (%s)."), 131117Sdinak pkcs11_strerror(rv)); 131217Sdinak quick_finish(NULL); 131317Sdinak return (PK_ERR_PK11); 131417Sdinak } 131517Sdinak 131617Sdinak /* Assume user must be logged in R/W to export objects from token. */ 131717Sdinak if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) != 131817Sdinak CKR_OK) { 131917Sdinak cryptoerror(LOG_STDERR, 132017Sdinak gettext("Unable to log into token (%s)."), 132117Sdinak pkcs11_strerror(rv)); 132217Sdinak quick_finish(sess); 132317Sdinak return (PK_ERR_PK11); 132417Sdinak } 132517Sdinak 132617Sdinak /* Collect all private keys first. */ 132717Sdinak if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL, 132817Sdinak &objs, &num_objs)) != CKR_OK) { 132917Sdinak cryptoerror(LOG_STDERR, gettext( 133017Sdinak "Unable to retrieve private key token objects (%s)."), 133117Sdinak pkcs11_strerror(rv)); 133217Sdinak quick_finish(sess); 133317Sdinak return (PK_ERR_PK11); 133417Sdinak } 133517Sdinak 133617Sdinak /* Nothing to do? */ 133717Sdinak if (num_objs == 0) { 133817Sdinak cryptoerror(LOG_STDERR, gettext("No objects found.")); 133917Sdinak quick_finish(sess); 134017Sdinak return (0); 134117Sdinak } 134217Sdinak 134317Sdinak /* Setup OpenSSL context. */ 134417Sdinak PKTOOL_setup_openssl(); 134517Sdinak 134617Sdinak /* Create PKCS#12 file. */ 134717Sdinak if ((create_pkcs12(filename, &fbio)) < 0) { 134817Sdinak cryptoerror(LOG_STDERR, gettext("No export file created.")); 134917Sdinak quick_finish(sess); 135017Sdinak return (PK_ERR_SYSTEM); 135117Sdinak } 135217Sdinak 135317Sdinak /* Get the PIN for the PKCS#12 export file. */ 135417Sdinak if ((rv = get_pin(gettext("Create export file passphrase:"), gettext( 135517Sdinak "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) != 135617Sdinak CKR_OK) { 135717Sdinak cryptoerror(LOG_STDERR, 135817Sdinak gettext("Unable to get export file passphrase (%s)."), 135917Sdinak pkcs11_strerror(rv)); 136017Sdinak close_pkcs12(fbio); 136117Sdinak quick_finish(sess); 136217Sdinak return (PK_ERR_PK11); 136317Sdinak } 136417Sdinak 136517Sdinak for (i = 0; i < num_objs; i++) { 136617Sdinak /* Get a private key and its certificate and CA chain. */ 136717Sdinak if ((rv = get_token_objs(sess, objs[i], &mate, &chain, 136817Sdinak &chain_len, &id, &id_len)) != CKR_OK) { 136917Sdinak /* 137017Sdinak * Note this "rv" is either CKR_OK or !CKR_OK. The 137117Sdinak * real error codes/messages are handled inside 137217Sdinak * read_token_objs(). 137317Sdinak */ 137417Sdinak cryptoerror(LOG_STDERR, 137517Sdinak gettext("Unable to get token objects.")); 137617Sdinak free(id); 137717Sdinak close_pkcs12(fbio); 137817Sdinak quick_finish(sess); 137917Sdinak return (PK_ERR_PK11); 138017Sdinak } 138117Sdinak 138217Sdinak /* Convert to OpenSSL equivalents. */ 138317Sdinak if ((rv = convert_token_objs(sess, objs[i], mate, chain, 138417Sdinak chain_len, &priv_key, &cert, &ca)) != CKR_OK) { 138517Sdinak /* 138617Sdinak * Note this "rv" is either CKR_OK or !CKR_OK. The 138717Sdinak * real error codes/messages are handled inside 138817Sdinak * read_token_objs(). 138917Sdinak */ 139017Sdinak cryptoerror(LOG_STDERR, 139117Sdinak gettext("Unable to convert token objects.")); 139217Sdinak free(id); 139317Sdinak close_pkcs12(fbio); 139417Sdinak quick_finish(sess); 139517Sdinak return (PK_ERR_PK11); 139617Sdinak } 139717Sdinak 139817Sdinak /* 139917Sdinak * When exporting of cert chains is implemented, these 140017Sdinak * messages should be updated accordingly. 140117Sdinak */ 140217Sdinak if (mate == ~0UL) 140317Sdinak (void) fprintf(stdout, gettext( 140417Sdinak "Writing object #%d...\n"), i+1); 140517Sdinak else 140617Sdinak (void) fprintf(stdout, gettext("Writing object #%d " 140717Sdinak "and its certificate...\n"), i+1); 140817Sdinak 140917Sdinak /* Write object and its certs to the PKCS#12 export file. */ 141017Sdinak if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len, 141117Sdinak priv_key, cert, ca, &good_ones, &bad_ones) < 0) { 141217Sdinak cryptoerror(LOG_STDERR, gettext( 141317Sdinak "Unable to write object #%d to export file."), i+1); 141417Sdinak sk_X509_pop_free(ca, X509_free); 141517Sdinak free(id); 141617Sdinak close_pkcs12(fbio); 141717Sdinak quick_finish(sess); 141817Sdinak return (PK_ERR_OPENSSL); 141917Sdinak } 142017Sdinak 142117Sdinak /* Destroy key id and CA cert chain, done with them. */ 142217Sdinak free(id); 142317Sdinak id = NULL; 142417Sdinak sk_X509_pop_free(ca, X509_free); 142517Sdinak ca = NULL; 142617Sdinak } 142717Sdinak 142817Sdinak (void) fprintf(stdout, gettext( 142917Sdinak "%d token objects exported, %d errors occurred.\n"), 143017Sdinak good_ones, bad_ones); 143117Sdinak 143217Sdinak /* Close PKCS#12 file. */ 143317Sdinak close_pkcs12(fbio); 143417Sdinak 143517Sdinak /* Clean up. */ 143617Sdinak quick_finish(sess); 143717Sdinak return (0); 143817Sdinak } 1439