export.c revision 7711facfe58561dd91d6ece0f5f41150c3956c83
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * CDDL HEADER START
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * The contents of this file are subject to the terms of the
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Common Development and Distribution License, Version 1.0 only
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * (the "License"). You may not use this file except in compliance
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * with the License.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * See the License for the specific language governing permissions
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * and limitations under the License.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * When distributing Covered Code, include this CDDL HEADER in each
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * If applicable, add the following below this CDDL HEADER, with the
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * fields enclosed by brackets "[]" replaced with your own identifying
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * information: Portions Copyright [yyyy] [name of copyright owner]
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * CDDL HEADER END
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Use is subject to license terms.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak#pragma ident "%Z%%M% %I% %E% SMI"
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * This file implements the export operation for this tool.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * The basic flow of the process is to find the soft token,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * log into it, find the PKCS#11 objects in the soft token
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * to be exported matching keys with their certificates, export
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * them to the PKCS#12 file encrypting them with a file password
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * if desired, and log out.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Writes OpenSSL objects to PKCS#12 file. The PKCS#11 objects from
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * the soft token need to be converted to OpenSSL structures prior
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * to this call, since the PKCS#12 routines depend on that format.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * This code is patterned from OpenSSL apps that write PKCS#12 files.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Note: it's not clear from the usage of all the functions here by
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * OpenSSL apps whether these functions have return values or error
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * conditions that can be checked. This function may benefit from
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * a closer review at a later time.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakwrite_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak STACK_OF(X509) *ca_certs, int *successes, int *failures)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak/* ARGSUSED */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Do not reset *successes or *failures -- keep running totals. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* If there is nothing to write to the PKCS#12 file, leave. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (cert == NULL && ca_certs == NULL && priv_key == NULL) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (0);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Section 1:
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * The first PKCS#12 container (safebag) will hold the certificates
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * associated with this key. The result of this section is a
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * PIN-encrypted PKCS#7 container (authsafe). If there are no
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * certificates, there is no point in creating the "safebag" or the
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * "authsafe" so we go to the next section.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start a PKCS#12 safebag container for the certificates. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to create PKCS#12 certificate bag."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Add the cert corresponding to private key to bag_stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Convert cert from X509 struct to PKCS#12 bag */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert certificate to "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "PKCS#12 bag."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Cleanup the safebag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Add the key id to the certificate bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Add the friendly name to the certificate bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "label PKCS#12 safebag with friendly name");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Pile it on the bag_stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Add all the CA chain certs to the bag_stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "safebag");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Go through the stack of CA certs, converting each
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * one to a PKCS#12 bag and piling them onto the
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * bag_stack.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * sk_X509_value() is macro that embeds a
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cast to (X509 *). Here it translates
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * into ((X509 *)sk_value((ca_certs), (i))).
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Lint is complaining about the embedded
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * casting, and to fix it, you need to fix
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * openssl header files.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* LINTED E_BAD_PTR_CAST_ALIGN */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Convert CA cert to PKCS#12 bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert CA certificate "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Cleanup the safebag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Note CA certs do not have friendly name. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Pile it onto the bag_stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Turn bag_stack of certs into encrypted authsafe. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "PKCS#7 authsafe");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Clear away this bag_stack, we're done with it. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to PKCS#7-encrypt certificate bag."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Section 2:
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * The second PKCS#12 container (safebag) will hold the private key
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * that goes with the certificates above. The results of this section
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * is an unencrypted PKCS#7 container (authsafe). If there is no
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * private key, there is no point in creating the "safebag" or the
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * "authsafe" so we go to the next section.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Make a PKCS#8 shrouded key bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("create PKCS#8 shrouded key out of private key");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to create PKCS#8 shrouded key for "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "private key."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Put the shrouded key into a PKCS#12 bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Clean up the PKCS#8 shrouded key, don't need it now. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert private key to PKCS#12 bag."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Add the key id to the certificate bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Add the cert friendly name to the private key bag. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("label PKCS#12 safebag with friendly name");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len))
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start a PKCS#12 safebag container for the private key. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to create PKCS#12 private key bag."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Pile on the private key on the bag_stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Turn bag_stack with private key into unencrypted authsafe. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Clear away this bag_stack, we're done with it. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to PKCS#7-convert private key bag."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Section 3:
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * This is where the two PKCS#7 containers, one for the certificates
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * and one for the private key, are put together into a PKCS#12
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * element. This final PKCS#12 element is written to the export file.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start a PKCS#7 stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("create PKCS#7 authsafe for private key and certificates");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to create PKCS#7 container for private key "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "and certificates."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Put certificates and private key into PKCS#7 stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("put private key authsafe into PKCS#7 container");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("put certificate authsafe into PKCS#7 container");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Create PKCS#12 element out of PKCS#7 stack. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("create PKCS#12 element for export file");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to create PKCS#12 element for export file."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Put the PKCS#7 stack into the PKCS#12 element. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Clear away the PKCS#7 stack, we're done with it. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Set the integrity MAC on the PKCS#12 element. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Write the PKCS#12 element to the export file. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("writing PKCS#12 element to export file");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Clear away the PKCS#12 element. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (0);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Get token objects: private key, its cert, and its cert chain.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakget_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_ULONG num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the size of the object's CKA_ID field first. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("getting CKA_ID size for object 0x%x", obj);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("Unable to get size of object"
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Allocate the space needed for the key id. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the CKA_ID field to match obj with its cert. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("getting CKA_ID attribute for object 0x%x", obj);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("Unable to get object "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Now try to find any certs that have the same id. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("searching for certificates with same CKA_ID");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("Unable to initialize "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Find the first cert that matches the key id. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("Certificate search failed "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* We currently do not find all the certs in the chain. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * "to" should be the address of a ptr init'ed to NULL to
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * receive the BIGNUM, e.g.,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * biginteger_t from;
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * BIGNUM *foo = NULL;
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cvt_bigint2bn(&from, &foo);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) ==
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (-1);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (0);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakcvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal RSA structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the sizes of the attributes we need. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for size info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get RSA private key attribute sizes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Allocate memory for each attribute. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak for (i = 0; i < count; i++) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("cvt_rsa2evp_pkey: *** should not happen");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Now really get the attributes. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for attribute info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get RSA private key attributes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Fill in all the temp variables. Modulus and public exponent
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * are required. The rest are optional.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start the conversion to internal OpenSSL RSA structure. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Modulus n */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key modulus."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Public exponent e */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key public exponent."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Private exponent e */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "RSA private key private exponent."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Prime p */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key prime 1."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Prime q */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key prime 2."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Private exponent d modulo p-1 */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key exponent 1."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Private exponent d modulo q-1 */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key exponent 2."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* CRT coefficient q-inverse mod p */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert RSA private key coefficient."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal EVP_PKEY structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Put the RSA struct into the EVP_PKEY struct and return it. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakcvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal DSA structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the sizes of the attributes we need. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for size info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get DSA private key object attributes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Allocate memory for each attribute. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak for (i = 0; i < count; i++) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("cvt_dsa2evp_pkey: *** should not happen");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Now really get the attributes. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for attribute info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get DSA private key attributes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Fill in all the temp variables. They are all required. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start the conversion to internal OpenSSL DSA structure. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Prime p */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DSA private key prime."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Subprime q */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DSA private key subprime."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Base g */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DSA private key base."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Private key x */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DSA private key value."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal EVP_PKEY structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Put the DSA struct into the EVP_PKEY struct and return it. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakcvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal DH structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the sizes of the attributes we need. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for size info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get DH private key object attributes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Allocate memory for each attribute. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak for (i = 0; i < count; i++) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Now really get the attributes. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for attribute info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get DH private key attributes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Fill in all the temp variables. They are all required. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start the conversion to internal OpenSSL DH structure. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Prime p */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DH private key prime."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Base g */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DH private key base."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Private value x */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert DH private key value."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal EVP_PKEY structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Put the DH struct into the EVP_PKEY struct and return it. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakcvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Find out the key type to do the right conversion. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get token object key type (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Private key type 0x%02x conversion not supported."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Convert PKCS#11 certificate object to OpenSSL X509 structure.
7711facfe58561dd91d6ece0f5f41150c3956c83dinakcvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to allocate internal X509 structure."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the sizes of the attributes we need. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for size info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get certificate attribute sizes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Allocate memory for each attribute. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak for (i = 0; i < count; i++) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen))
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Now really get the attributes. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling C_GetAttributeValue for attribute info");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get certificate attributes (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Fill in all the temp variables. Subject and value are required.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * The rest are optional.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak copy_attr_to_string(&(cert_attrs[i]), &label, &label_len);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Start the conversion to internal OpenSSL X509 structure. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Subject name (required) */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling d2i_X509_NAME for subject name");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((ssl_subject = d2i_X509_NAME(NULL, &subject, subject_len)) ==
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert certificate subject name."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to pack certificate subject name entries."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Label (optional) */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Id (optional) */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Issuer name (optional) */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((ssl_issuer = d2i_X509_NAME(NULL, &issuer, issuer_len)) == NULL) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert certificate issuer name."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to pack certificate issuer name entries."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Serial number (optional) */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling c2i_ASN1_INTEGER for serial number");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((ssl_serial = c2i_ASN1_INTEGER(NULL, &serial, serial_len)) ==
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert certificate serial number."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Value (required)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * The rest of this code takes the CKA_VALUE attribute, converts
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * it into a temp OpenSSL X509 structure and picks out the rest
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * of the fields we need to convert it back into the current X509
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * structure that will get exported. The reason we don't just
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * start with CKA_VALUE is because while the object was in the
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * softtoken, it is possible that some of its attributes changed.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Those changes would not appear in CKA_VALUE and would be lost
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * if we started with CKA_VALUE that was saved originally.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((temp_cert = d2i_X509(NULL, &value, value_len)) == NULL) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to convert main certificate values."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Transfer these values from temp_cert to cert. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling X509_set_version/X509_get_version");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (!X509_set_version(cert, X509_get_version(temp_cert)))
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling X509_set_notBefore/X509_get_notBefore");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert)))
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling X509_set_notAfter/X509_get_notAfter");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert)))
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("calling X509_set_pubkey/X509_get_pubkey");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert)))
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * These don't get transfered from temp_cert to cert.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * It -appears- that they may get regenerated as needed.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cert->cert_info->signature = dup(temp_cert->cert_info->signature);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cert->sig_alg = dup(temp_cert->sig_alg);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cert->signature = dup(temp_cert->signature);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cert->skid = dup(temp_cert->skid);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * cert->akid = dup(temp_cert->akid);
7711facfe58561dd91d6ece0f5f41150c3956c83dinakconvert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK)
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("converting cert corresponding to private key");
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptodebug("converting ca chain of %d certs corresponding "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak for (i = 0; i < chain_len; i++) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Export objects from token to PKCS#12 file.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get rid of subcommand work "export". */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* One additional arg required: filename. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Done parsing command line options. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Check if the file exists and might be overwritten. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, "
7711facfe58561dd91d6ece0f5f41150c3956c83dinak gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (0);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Export operation only supported on softtoken. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak full_token_name(token_name, manuf_id, serial_no, full_name);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Find the slot with token. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the user's PIN. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to get token passphrase (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Assume user must be logged in R/W to export objects from token. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Collect all private keys first. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Unable to retrieve private key token objects (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Nothing to do? */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("No objects found."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (0);
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Setup OpenSSL context. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Create PKCS#12 file. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak cryptoerror(LOG_STDERR, gettext("No export file created."));
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get the PIN for the PKCS#12 export file. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = get_pin(gettext("Create export file passphrase:"), gettext(
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) !=
7711facfe58561dd91d6ece0f5f41150c3956c83dinak gettext("Unable to get export file passphrase (%s)."),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak for (i = 0; i < num_objs; i++) {
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Get a private key and its certificate and CA chain. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = get_token_objs(sess, objs[i], &mate, &chain,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Note this "rv" is either CKR_OK or !CKR_OK. The
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * real error codes/messages are handled inside
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * read_token_objs().
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Convert to OpenSSL equivalents. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if ((rv = convert_token_objs(sess, objs[i], mate, chain,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * Note this "rv" is either CKR_OK or !CKR_OK. The
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * real error codes/messages are handled inside
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * read_token_objs().
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * When exporting of cert chains is implemented, these
7711facfe58561dd91d6ece0f5f41150c3956c83dinak * messages should be updated accordingly.
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Write object and its certs to the PKCS#12 export file. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len,
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Destroy key id and CA cert chain, done with them. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak "%d token objects exported, %d errors occurred.\n"),
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Close PKCS#12 file. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak /* Clean up. */
7711facfe58561dd91d6ece0f5f41150c3956c83dinak return (0);