diff options
Diffstat (limited to 'usr/src/cmd/cmd-crypto/pktool/export.c')
-rw-r--r-- | usr/src/cmd/cmd-crypto/pktool/export.c | 1682 |
1 files changed, 404 insertions, 1278 deletions
diff --git a/usr/src/cmd/cmd-crypto/pktool/export.c b/usr/src/cmd/cmd-crypto/pktool/export.c index 46fbccb37e..9170a00468 100644 --- a/usr/src/cmd/cmd-crypto/pktool/export.c +++ b/usr/src/cmd/cmd-crypto/pktool/export.c @@ -17,8 +17,8 @@ * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END - */ -/* + * + * * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -38,1170 +38,264 @@ #include <stdlib.h> #include <string.h> #include <errno.h> -#include <cryptoutil.h> -#include <security/cryptoki.h> +#include <fcntl.h> #include "common.h" -#include "biginteger.h" -#include "osslcommon.h" -#include "p12common.h" -#include <openssl/pkcs12.h> - -/* - * Writes OpenSSL objects to PKCS#12 file. The PKCS#11 objects from - * the soft token need to be converted to OpenSSL structures prior - * to this call, since the PKCS#12 routines depend on that format. - * This code is patterned from OpenSSL apps that write PKCS#12 files. - * - * Note: it's not clear from the usage of all the functions here by - * OpenSSL apps whether these functions have return values or error - * conditions that can be checked. This function may benefit from - * a closer review at a later time. - */ -static int -write_objs_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, - CK_BYTE_PTR id, CK_ULONG id_len, EVP_PKEY *priv_key, X509 *cert, - STACK_OF(X509) *ca_certs, int *successes, int *failures) -/* ARGSUSED */ -{ - STACK_OF(PKCS12_SAFEBAG) *bag_stack = NULL; - PKCS12_SAFEBAG *bag = NULL; - X509 *ca = NULL; - PKCS7 *cert_authsafe = NULL; - PKCS8_PRIV_KEY_INFO *p8 = NULL; - PKCS7 *key_authsafe = NULL; - STACK_OF(PKCS7) *authsafe_stack = NULL; - PKCS12 *p12_elem = NULL; - unsigned char *lab = NULL; - int lab_len = 0; - int i; - int n_writes = 0; - - cryptodebug("inside write_objs_pkcs12"); - - /* Do not reset *successes or *failures -- keep running totals. */ - - /* If there is nothing to write to the PKCS#12 file, leave. */ - if (cert == NULL && ca_certs == NULL && priv_key == NULL) { - cryptodebug("nothing to write to export file"); - return (0); - } - - /* - * Section 1: - * - * The first PKCS#12 container (safebag) will hold the certificates - * associated with this key. The result of this section is a - * PIN-encrypted PKCS#7 container (authsafe). If there are no - * certificates, there is no point in creating the "safebag" or the - * "authsafe" so we go to the next section. - */ - if (cert != NULL || ca_certs != NULL) { - /* Start a PKCS#12 safebag container for the certificates. */ - cryptodebug("creating certificate PKCS#12 safebag"); - bag_stack = sk_PKCS12_SAFEBAG_new_null(); - if (bag_stack == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to create PKCS#12 certificate bag.")); - (*failures)++; - return (-1); - } - - /* Add the cert corresponding to private key to bag_stack. */ - if (cert) { - /* Convert cert from X509 struct to PKCS#12 bag */ - cryptodebug("adding certificate to PKCS#12 safebag"); - bag = PKCS12_x5092certbag(cert); - if (bag == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert certificate to " - "PKCS#12 bag.")); - /* Cleanup the safebag. */ - sk_PKCS12_SAFEBAG_pop_free(bag_stack, - PKCS12_SAFEBAG_free); - (*failures)++; - return (-1); - } - - /* Add the key id to the certificate bag. */ - cryptodebug("add key id to PKCS#12 safebag"); - if (!PKCS12_add_localkeyid(bag, id, id_len)) - cryptodebug("error not caught"); - - /* Add the friendly name to the certificate bag. */ - if ((lab = X509_alias_get0(cert, &lab_len)) != NULL) { - cryptodebug( - "label PKCS#12 safebag with friendly name"); - if (!PKCS12_add_friendlyname(bag, (char *)lab, - lab_len)) - cryptodebug("error not caught"); - } - - /* Pile it on the bag_stack. */ - if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) - cryptodebug("error not caught"); - - n_writes++; - } - - /* Add all the CA chain certs to the bag_stack. */ - if (ca_certs) { - cryptodebug("adding CA certificate chain to PKCS#12 " - "safebag"); - /* - * Go through the stack of CA certs, converting each - * one to a PKCS#12 bag and piling them onto the - * bag_stack. - */ - for (i = 0; i < sk_X509_num(ca_certs); i++) { - /* - * sk_X509_value() is macro that embeds a - * cast to (X509 *). Here it translates - * into ((X509 *)sk_value((ca_certs), (i))). - * Lint is complaining about the embedded - * casting, and to fix it, you need to fix - * openssl header files. - */ - /* LINTED E_BAD_PTR_CAST_ALIGN */ - ca = sk_X509_value(ca_certs, i); - - /* Convert CA cert to PKCS#12 bag. */ - cryptodebug("adding CA certificate #%d " - "to PKCS#12 safebag", i+1); - bag = PKCS12_x5092certbag(ca); - if (bag == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert CA certificate " - "#%d to PKCS#12 bag."), i+1); - /* Cleanup the safebag. */ - sk_PKCS12_SAFEBAG_pop_free(bag_stack, - PKCS12_SAFEBAG_free); - (*failures)++; - return (-1); - } - - /* Note CA certs do not have friendly name. */ - - /* Pile it onto the bag_stack. */ - if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) - cryptodebug("error not caught"); - - n_writes++; - } - } - - /* Turn bag_stack of certs into encrypted authsafe. */ - cryptodebug("encrypt certificate PKCS#12 bag into " - "PKCS#7 authsafe"); - cert_authsafe = PKCS12_pack_p7encdata( - NID_pbe_WithSHA1And40BitRC2_CBC, (char *)pin, -1, NULL, - 0, PKCS12_DEFAULT_ITER, bag_stack); - - /* Clear away this bag_stack, we're done with it. */ - sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); - bag_stack = NULL; - - if (cert_authsafe == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to PKCS#7-encrypt certificate bag.")); - (*failures)++; - return (-1); - } - } - - /* - * Section 2: - * - * The second PKCS#12 container (safebag) will hold the private key - * that goes with the certificates above. The results of this section - * is an unencrypted PKCS#7 container (authsafe). If there is no - * private key, there is no point in creating the "safebag" or the - * "authsafe" so we go to the next section. - */ - if (priv_key != NULL) { - /* Make a PKCS#8 shrouded key bag. */ - cryptodebug("create PKCS#8 shrouded key out of private key"); - p8 = EVP_PKEY2PKCS8(priv_key); - if (p8 == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to create PKCS#8 shrouded key for " - "private key.")); - (*failures)++; - return (-1); - } - - /* Put the shrouded key into a PKCS#12 bag. */ - cryptodebug("convert shrouded key to PKCS#12 bag"); - bag = PKCS12_MAKE_SHKEYBAG( - NID_pbe_WithSHA1And3_Key_TripleDES_CBC, (char *)pin, - -1, NULL, 0, PKCS12_DEFAULT_ITER, p8); - - /* Clean up the PKCS#8 shrouded key, don't need it now. */ - PKCS8_PRIV_KEY_INFO_free(p8); - p8 = NULL; - - if (bag == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert private key to PKCS#12 bag.")); - (*failures)++; - return (-1); - } - - /* Add the key id to the certificate bag. */ - cryptodebug("add key id to PKCS#12 safebag"); - if (!PKCS12_add_localkeyid(bag, id, id_len)) - cryptodebug("error not caught"); - - /* Add the cert friendly name to the private key bag. */ - if (lab != NULL) { - cryptodebug("label PKCS#12 safebag with friendly name"); - if (!PKCS12_add_friendlyname(bag, (char *)lab, lab_len)) - cryptodebug("error not caught"); - } - - /* Start a PKCS#12 safebag container for the private key. */ - cryptodebug("creating private key PKCS#12 safebag"); - bag_stack = sk_PKCS12_SAFEBAG_new_null(); - if (bag_stack == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to create PKCS#12 private key bag.")); - (*failures)++; - return (-1); - } - - /* Pile on the private key on the bag_stack. */ - if (!sk_PKCS12_SAFEBAG_push(bag_stack, bag)) - cryptodebug("error not caught"); - /* Turn bag_stack with private key into unencrypted authsafe. */ - cryptodebug("put private PKCS#12 bag into PKCS#7 authsafe"); - key_authsafe = PKCS12_pack_p7data(bag_stack); +#include <kmfapi.h> - /* Clear away this bag_stack, we're done with it. */ - sk_PKCS12_SAFEBAG_pop_free(bag_stack, PKCS12_SAFEBAG_free); - bag_stack = NULL; - - if (key_authsafe == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to PKCS#7-convert private key bag.")); - (*failures)++; - return (-1); - } - - n_writes++; - } - - /* - * Section 3: - * - * This is where the two PKCS#7 containers, one for the certificates - * and one for the private key, are put together into a PKCS#12 - * element. This final PKCS#12 element is written to the export file. - */ - /* Start a PKCS#7 stack. */ - cryptodebug("create PKCS#7 authsafe for private key and certificates"); - authsafe_stack = sk_PKCS7_new_null(); - if (authsafe_stack == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to create PKCS#7 container for private key " - "and certificates.")); - (*failures)++; - return (-1); - } - - /* Put certificates and private key into PKCS#7 stack. */ - if (key_authsafe != NULL) { - cryptodebug("put private key authsafe into PKCS#7 container"); - if (!sk_PKCS7_push(authsafe_stack, key_authsafe)) - cryptodebug("error not caught"); - } - if (cert_authsafe != NULL) { - cryptodebug("put certificate authsafe into PKCS#7 container"); - if (!sk_PKCS7_push(authsafe_stack, cert_authsafe)) - cryptodebug("error not caught"); - } - - /* Create PKCS#12 element out of PKCS#7 stack. */ - cryptodebug("create PKCS#12 element for export file"); - p12_elem = PKCS12_init(NID_pkcs7_data); - if (p12_elem == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to create PKCS#12 element for export file.")); - sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); - (*failures)++; - return (-1); - } - - /* Put the PKCS#7 stack into the PKCS#12 element. */ - if (!PKCS12_pack_authsafes(p12_elem, authsafe_stack)) - cryptodebug("error not caught"); - - /* Clear away the PKCS#7 stack, we're done with it. */ - sk_PKCS7_pop_free(authsafe_stack, PKCS7_free); - authsafe_stack = NULL; - - /* Set the integrity MAC on the PKCS#12 element. */ - cryptodebug("setting MAC for PKCS#12 element"); - if (!PKCS12_set_mac(p12_elem, (char *)pin, -1, NULL, 0, - PKCS12_DEFAULT_ITER, NULL)) - cryptodebug("error not caught"); - - /* Write the PKCS#12 element to the export file. */ - cryptodebug("writing PKCS#12 element to export file"); - if (!i2d_PKCS12_bio(fbio, p12_elem)) - cryptodebug("error not caught"); - - (*successes) += n_writes; - - /* Clear away the PKCS#12 element. */ - PKCS12_free(p12_elem); - return (0); -} - -/* - * Get token objects: private key, its cert, and its cert chain. - */ -static CK_RV -get_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, - CK_OBJECT_HANDLE *mate, CK_OBJECT_HANDLE_PTR *chain, - CK_ULONG *chain_len, CK_BYTE_PTR *id, CK_ULONG *id_len) +static KMF_RETURN +pk_find_export_cert(KMF_HANDLE_T kmfhandle, KMF_FINDCERT_PARAMS *parms, + KMF_X509_DER_CERT *cert) { - CK_RV rv = CKR_OK; - CK_ATTRIBUTE keyid_attr[1] = { - { CKA_ID, NULL, 0 } - }; - static CK_OBJECT_CLASS class = CKO_CERTIFICATE; - static CK_CERTIFICATE_TYPE certtype = CKC_X_509; - CK_ATTRIBUTE cert_attr[4] = { - { CKA_CLASS, &class, sizeof (CK_OBJECT_CLASS) }, - { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) }, - { CKA_TOKEN, &pk_true, sizeof (pk_true) }, - { CKA_ID, NULL, 0 } - }; - CK_ULONG num_attr = sizeof (cert_attr) / sizeof (CK_ATTRIBUTE); - CK_OBJECT_HANDLE cert = ~0UL; - CK_ULONG num = 0; - - cryptodebug("inside get_token_objs"); - - /* Get the size of the object's CKA_ID field first. */ - cryptodebug("getting CKA_ID size for object 0x%x", obj); - if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext("Unable to get size of object" - " key id (%s)."), pkcs11_strerror(rv)); - return (rv); - } - - /* Allocate the space needed for the key id. */ - if ((keyid_attr[0].pValue = malloc(keyid_attr[0].ulValueLen)) == NULL) { - cryptoerror(LOG_STDERR, "%s.", strerror(errno)); - return (CKR_HOST_MEMORY); - } + KMF_RETURN rv = KMF_OK; + uint32_t numcerts = 0; - /* Get the CKA_ID field to match obj with its cert. */ - cryptodebug("getting CKA_ID attribute for object 0x%x", obj); - if ((rv = C_GetAttributeValue(sess, obj, keyid_attr, 1)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext("Unable to get object " - "key id (%s)."), pkcs11_strerror(rv)); - free(keyid_attr[0].pValue); + numcerts = 0; + (void) memset(cert, 0, sizeof (KMF_X509_DER_CERT)); + rv = KMF_FindCert(kmfhandle, parms, NULL, &numcerts); + if (rv != KMF_OK) { return (rv); } + if (numcerts == 0) { + cryptoerror(LOG_STDERR, + gettext("No matching certificates found.")); + return (KMF_ERR_CERT_NOT_FOUND); - /* Now try to find any certs that have the same id. */ - cryptodebug("searching for certificates with same CKA_ID"); - cert_attr[3].pValue = keyid_attr[0].pValue; - cert_attr[3].ulValueLen = keyid_attr[0].ulValueLen; - if ((rv = C_FindObjectsInit(sess, cert_attr, num_attr)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext("Unable to initialize " - "certificate search (%s)."), pkcs11_strerror(rv)); - free(keyid_attr[0].pValue); - return (rv); - } + } else if (numcerts == 1) { + rv = KMF_FindCert(kmfhandle, parms, cert, &numcerts); - /* Find the first cert that matches the key id. */ - if ((rv = C_FindObjects(sess, &cert, 1, &num)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext("Certificate search failed " - "(%s)."), pkcs11_strerror(rv)); - free(keyid_attr[0].pValue); - return (rv); + } else if (numcerts > 1) { + cryptoerror(LOG_STDERR, + gettext("%d certificates found, refine the " + "search parameters to eliminate ambiguity\n"), + numcerts); + return (KMF_ERR_BAD_PARAMETER); } - - (void) C_FindObjectsFinal(sess); - - *id = keyid_attr[0].pValue; - *id_len = keyid_attr[0].ulValueLen; - - *mate = (num == 1) ? cert : ~0UL; - - /* We currently do not find all the certs in the chain. */ - *chain_len = 0; - *chain = NULL; - - return (CKR_OK); + return (rv); } -/* - * Converts PKCS#11 biginteger_t format to OpenSSL BIGNUM. - * "to" should be the address of a ptr init'ed to NULL to - * receive the BIGNUM, e.g., - * biginteger_t from; - * BIGNUM *foo = NULL; - * cvt_bigint2bn(&from, &foo); - */ -static int -cvt_bigint2bn(biginteger_t *from, BIGNUM **to) +static KMF_RETURN +pk_export_file_objects(KMF_HANDLE_T kmfhandle, int oclass, + char *issuer, char *subject, KMF_BIGINT *serial, + KMF_ENCODE_FORMAT ofmt, + char *dir, char *infile, char *filename) { - BIGNUM *temp = NULL; - - cryptodebug("inside cvt_bigint2bn"); - - if (from == NULL || to == NULL) - return (-1); - - cryptodebug("calling BN_bin2bn"); - if ((temp = BN_bin2bn(from->big_value, from->big_value_len, *to)) == - NULL) - return (-1); - - *to = temp; - return (0); + KMF_RETURN rv = KMF_OK; + KMF_STORECERT_PARAMS scparms; + KMF_X509_DER_CERT kmfcert; + + /* If searching for public objects or certificates, find certs now */ + if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { + KMF_FINDCERT_PARAMS fcargs; + + (void) memset(&fcargs, 0, sizeof (fcargs)); + fcargs.kstype = KMF_KEYSTORE_OPENSSL; + fcargs.certLabel = NULL; + fcargs.issuer = issuer; + fcargs.subject = subject; + fcargs.serial = serial; + fcargs.sslparms.dirpath = dir; + fcargs.sslparms.certfile = infile; + fcargs.sslparms.format = ofmt; + + rv = pk_find_export_cert(kmfhandle, &fcargs, &kmfcert); + if (rv == KMF_OK) { + (void) memset(&scparms, 0, sizeof (scparms)); + scparms.kstype = KMF_KEYSTORE_OPENSSL; + scparms.sslparms.certfile = filename; + rv = KMF_StoreCert(kmfhandle, &scparms, + &kmfcert.certificate); + + KMF_FreeKMFCert(kmfhandle, &kmfcert); + } + } + return (rv); } -/* - * Convert PKCS#11 RSA private key to OpenSSL EVP_PKEY structure. - */ -static CK_RV -cvt_rsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) +static KMF_RETURN +pk_export_pk12_nss(KMF_HANDLE_T kmfhandle, + char *token_spec, char *dir, char *prefix, + char *certlabel, char *issuer, char *subject, + KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, + char *filename) { - CK_RV rv = CKR_OK; - EVP_PKEY *key = NULL; /* OpenSSL representation */ - RSA *rsa = NULL; /* OpenSSL representation */ - biginteger_t mod = { NULL, 0 }; /* required */ - biginteger_t pubexp = { NULL, 0 }; /* required */ - biginteger_t priexp = { NULL, 0 }; /* optional */ - biginteger_t prime1 = { NULL, 0 }; /* optional */ - biginteger_t prime2 = { NULL, 0 }; /* optional */ - biginteger_t exp1 = { NULL, 0 }; /* optional */ - biginteger_t exp2 = { NULL, 0 }; /* optional */ - biginteger_t coef = { NULL, 0 }; /* optional */ - CK_ATTRIBUTE rsa_pri_attrs[8] = { - { CKA_MODULUS, NULL, 0 }, - { CKA_PUBLIC_EXPONENT, NULL, 0 }, - { CKA_PRIVATE_EXPONENT, NULL, 0 }, /* optional */ - { CKA_PRIME_1, NULL, 0 }, /* | */ - { CKA_PRIME_2, NULL, 0 }, /* | */ - { CKA_EXPONENT_1, NULL, 0 }, /* | */ - { CKA_EXPONENT_2, NULL, 0 }, /* | */ - { CKA_COEFFICIENT, NULL, 0 } /* V */ - }; - CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE); - int i; - - cryptodebug("inside cvt_rsa2evp_pkey"); - - cryptodebug("calling RSA_new"); - if ((rsa = RSA_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal RSA structure.")); - return (CKR_HOST_MEMORY); - } + KMF_RETURN rv = KMF_OK; + KMF_EXPORTP12_PARAMS p12parms; - /* Get the sizes of the attributes we need. */ - cryptodebug("calling C_GetAttributeValue for size info"); - if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get RSA private key attribute sizes (%s)."), - pkcs11_strerror(rv)); + rv = configure_nss(kmfhandle, dir, prefix); + if (rv != KMF_OK) return (rv); - } - /* Allocate memory for each attribute. */ - for (i = 0; i < count; i++) { - if (rsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || - rsa_pri_attrs[i].ulValueLen == 0) { - cryptodebug("cvt_rsa2evp_pkey: *** should not happen"); - rsa_pri_attrs[i].ulValueLen = 0; - continue; - } - if ((rsa_pri_attrs[i].pValue = - malloc(rsa_pri_attrs[i].ulValueLen)) == NULL) { - cryptoerror(LOG_STDERR, "%s.", strerror(errno)); - return (CKR_HOST_MEMORY); - } - } + (void) memset(&p12parms, 0, sizeof (p12parms)); + if (token_spec == NULL) + token_spec = DEFAULT_NSS_TOKEN; - /* Now really get the attributes. */ - cryptodebug("calling C_GetAttributeValue for attribute info"); - if ((rv = C_GetAttributeValue(sess, obj, rsa_pri_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get RSA private key attributes (%s)."), - pkcs11_strerror(rv)); - return (rv); - } + p12parms.kstype = KMF_KEYSTORE_NSS; + p12parms.certLabel = certlabel; + p12parms.issuer = issuer; + p12parms.subject = subject; + p12parms.serial = serial; + p12parms.idstr = NULL; + if (tokencred != NULL) + p12parms.cred = *tokencred; + p12parms.nssparms.slotlabel = token_spec; - /* - * Fill in all the temp variables. Modulus and public exponent - * are required. The rest are optional. - */ - i = 0; - copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &mod); - copy_attr_to_bigint(&(rsa_pri_attrs[i++]), &pubexp); - - if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && - rsa_pri_attrs[i].ulValueLen != 0) - copy_attr_to_bigint(&(rsa_pri_attrs[i]), &priexp); - i++; - - if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && - rsa_pri_attrs[i].ulValueLen != 0) - copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime1); - i++; - - if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && - rsa_pri_attrs[i].ulValueLen != 0) - copy_attr_to_bigint(&(rsa_pri_attrs[i]), &prime2); - i++; - - if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && - rsa_pri_attrs[i].ulValueLen != 0) - copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp1); - i++; - - if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && - rsa_pri_attrs[i].ulValueLen != 0) - copy_attr_to_bigint(&(rsa_pri_attrs[i]), &exp2); - i++; - - if (rsa_pri_attrs[i].ulValueLen != (CK_ULONG)-1 && - rsa_pri_attrs[i].ulValueLen != 0) - copy_attr_to_bigint(&(rsa_pri_attrs[i]), &coef); - i++; - - /* Start the conversion to internal OpenSSL RSA structure. */ - - /* Modulus n */ - if (cvt_bigint2bn(&mod, &(rsa->n)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key modulus.")); - return (CKR_GENERAL_ERROR); - } + (void) get_pk12_password(&p12parms.p12cred); - /* Public exponent e */ - if (cvt_bigint2bn(&pubexp, &(rsa->e)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key public exponent.")); - return (CKR_GENERAL_ERROR); - } + rv = KMF_ExportPK12(kmfhandle, &p12parms, filename); + if (p12parms.p12cred.cred) + free(p12parms.p12cred.cred); - /* Private exponent e */ - if (priexp.big_value != NULL) { - if (cvt_bigint2bn(&priexp, &(rsa->d)) < 0) { - cryptoerror(LOG_STDERR, gettext("Unable to convert " - "RSA private key private exponent.")); - return (CKR_GENERAL_ERROR); - } - } else - cryptodebug("no RSA private key private exponent"); - - /* Prime p */ - if (prime1.big_value != NULL) { - if (cvt_bigint2bn(&prime1, &(rsa->p)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key prime 1.")); - return (CKR_GENERAL_ERROR); - } - } else - cryptodebug("no RSA private key prime 1"); - - /* Prime q */ - if (prime2.big_value != NULL) { - if (cvt_bigint2bn(&prime2, &(rsa->q)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key prime 2.")); - return (CKR_GENERAL_ERROR); - } - } else - cryptodebug("no RSA private key prime 2"); - - /* Private exponent d modulo p-1 */ - if (exp1.big_value != NULL) { - if (cvt_bigint2bn(&exp1, &(rsa->dmp1)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key exponent 1.")); - return (CKR_GENERAL_ERROR); - } - } else - cryptodebug("no RSA private key exponent 1"); - - /* Private exponent d modulo q-1 */ - if (exp2.big_value != NULL) { - if (cvt_bigint2bn(&exp2, &(rsa->dmq1)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key exponent 2.")); - return (CKR_GENERAL_ERROR); - } - } else - cryptodebug("no RSA private key exponent 2"); - - /* CRT coefficient q-inverse mod p */ - if (coef.big_value != NULL) { - if (cvt_bigint2bn(&coef, &(rsa->iqmp)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert RSA private key coefficient.")); - return (CKR_GENERAL_ERROR); - } - } else - cryptodebug("no RSA private key coefficient"); - - /* Create OpenSSL EVP_PKEY struct in which to stuff RSA struct. */ - cryptodebug("calling EVP_PKEY_new"); - if ((key = EVP_PKEY_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal EVP_PKEY structure.")); - return (CKR_HOST_MEMORY); - } - - /* Put the RSA struct into the EVP_PKEY struct and return it. */ - cryptodebug("calling EVP_PKEY_set1_RSA"); - (void) EVP_PKEY_set1_RSA(key, rsa); - - *pk = key; - return (CKR_OK); + return (rv); } -/* - * Convert PKCS#11 DSA private key to OpenSSL EVP_PKEY structure. - */ -static CK_RV -cvt_dsa2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) +static KMF_RETURN +pk_export_pk12_files(KMF_HANDLE_T kmfhandle, + char *certfile, char *keyfile, char *dir, + char *outfile) { - CK_RV rv = CKR_OK; - EVP_PKEY *key = NULL; /* OpenSSL representation */ - DSA *dsa = NULL; /* OpenSSL representation */ - biginteger_t prime = { NULL, 0 }; /* required */ - biginteger_t subprime = { NULL, 0 }; /* required */ - biginteger_t base = { NULL, 0 }; /* required */ - biginteger_t value = { NULL, 0 }; /* required */ - CK_ATTRIBUTE dsa_pri_attrs[4] = { - { CKA_PRIME, NULL, 0 }, - { CKA_SUBPRIME, NULL, 0 }, - { CKA_BASE, NULL, 0 }, - { CKA_VALUE, NULL, 0 } - }; - CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE); - int i; - - cryptodebug("inside cvt_dsa2evp_pkey"); - - cryptodebug("calling DSA_new"); - if ((dsa = DSA_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal DSA structure.")); - return (CKR_HOST_MEMORY); - } - - /* Get the sizes of the attributes we need. */ - cryptodebug("calling C_GetAttributeValue for size info"); - if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get DSA private key object attributes (%s)."), - pkcs11_strerror(rv)); - return (rv); - } - - /* Allocate memory for each attribute. */ - for (i = 0; i < count; i++) { - if (dsa_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || - dsa_pri_attrs[i].ulValueLen == 0) { - cryptodebug("cvt_dsa2evp_pkey: *** should not happen"); - dsa_pri_attrs[i].ulValueLen = 0; - continue; - } - if ((dsa_pri_attrs[i].pValue = - malloc(dsa_pri_attrs[i].ulValueLen)) == NULL) { - cryptoerror(LOG_STDERR, "%s.", strerror(errno)); - return (CKR_HOST_MEMORY); - } - } - - /* Now really get the attributes. */ - cryptodebug("calling C_GetAttributeValue for attribute info"); - if ((rv = C_GetAttributeValue(sess, obj, dsa_pri_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get DSA private key attributes (%s)."), - pkcs11_strerror(rv)); - return (rv); - } - - /* Fill in all the temp variables. They are all required. */ - i = 0; - copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &prime); - copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &subprime); - copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &base); - copy_attr_to_bigint(&(dsa_pri_attrs[i++]), &value); - - /* Start the conversion to internal OpenSSL DSA structure. */ + KMF_RETURN rv; + KMF_EXPORTP12_PARAMS p12parms; - /* Prime p */ - if (cvt_bigint2bn(&prime, &(dsa->p)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DSA private key prime.")); - return (CKR_GENERAL_ERROR); - } + (void) memset(&p12parms, 0, sizeof (p12parms)); - /* Subprime q */ - if (cvt_bigint2bn(&subprime, &(dsa->q)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DSA private key subprime.")); - return (CKR_GENERAL_ERROR); - } + p12parms.kstype = KMF_KEYSTORE_OPENSSL; + p12parms.certLabel = NULL; + p12parms.issuer = NULL; + p12parms.subject = NULL; + p12parms.serial = 0; + p12parms.idstr = NULL; + p12parms.sslparms.dirpath = dir; + p12parms.sslparms.certfile = certfile; + p12parms.sslparms.keyfile = keyfile; - /* Base g */ - if (cvt_bigint2bn(&base, &(dsa->g)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DSA private key base.")); - return (CKR_GENERAL_ERROR); - } + (void) get_pk12_password(&p12parms.p12cred); - /* Private key x */ - if (cvt_bigint2bn(&value, &(dsa->priv_key)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DSA private key value.")); - return (CKR_GENERAL_ERROR); - } + rv = KMF_ExportPK12(kmfhandle, &p12parms, outfile); - /* Create OpenSSL EVP PKEY struct in which to stuff DSA struct. */ - cryptodebug("calling EVP_PKEY_new"); - if ((key = EVP_PKEY_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal EVP_PKEY structure.")); - return (CKR_HOST_MEMORY); - } - - /* Put the DSA struct into the EVP_PKEY struct and return it. */ - cryptodebug("calling EVP_PKEY_set1_DSA"); - (void) EVP_PKEY_set1_DSA(key, dsa); + if (p12parms.p12cred.cred) + free(p12parms.p12cred.cred); - *pk = key; - return (CKR_OK); + return (rv); } -/* - * Convert PKCS#11 DH private key to OpenSSL EVP_PKEY structure. - */ -static CK_RV -cvt_dh2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) +static KMF_RETURN +pk_export_nss_objects(KMF_HANDLE_T kmfhandle, char *token_spec, + int oclass, char *certlabel, char *issuer, char *subject, + KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, char *dir, + char *prefix, char *filename) { - CK_RV rv = CKR_OK; - EVP_PKEY *key = NULL; /* OpenSSL representation */ - DH *dh = NULL; /* OpenSSL representation */ - biginteger_t prime = { NULL, 0 }; /* required */ - biginteger_t base = { NULL, 0 }; /* required */ - biginteger_t value = { NULL, 0 }; /* required */ - CK_ATTRIBUTE dh_pri_attrs[3] = { - { CKA_PRIME, NULL, 0 }, - { CKA_BASE, NULL, 0 }, - { CKA_VALUE, NULL, 0 } - }; - CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE); - int i; - - cryptodebug("inside cvt_dh2evp_pkey"); - - cryptodebug("calling DH_new"); - if ((dh = DH_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal DH structure.")); - return (CKR_HOST_MEMORY); - } + KMF_RETURN rv = KMF_OK; + KMF_STORECERT_PARAMS scparms; + KMF_X509_DER_CERT kmfcert; - /* Get the sizes of the attributes we need. */ - cryptodebug("calling C_GetAttributeValue for size info"); - if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get DH private key object attributes (%s)."), - pkcs11_strerror(rv)); + rv = configure_nss(kmfhandle, dir, prefix); + if (rv != KMF_OK) return (rv); - } - /* Allocate memory for each attribute. */ - for (i = 0; i < count; i++) { - if (dh_pri_attrs[i].ulValueLen == (CK_ULONG)-1 || - dh_pri_attrs[i].ulValueLen == 0) { - cryptodebug("cvt_dh2evp_pkey: ***should not happen"); - dh_pri_attrs[i].ulValueLen = 0; - continue; - } - if ((dh_pri_attrs[i].pValue = - malloc(dh_pri_attrs[i].ulValueLen)) == NULL) { - cryptoerror(LOG_STDERR, "%s.", strerror(errno)); - return (CKR_HOST_MEMORY); + /* If searching for public objects or certificates, find certs now */ + if (oclass & (PK_CERT_OBJ | PK_PUBLIC_OBJ)) { + KMF_FINDCERT_PARAMS fcargs; + + (void) memset(&fcargs, 0, sizeof (fcargs)); + fcargs.kstype = KMF_KEYSTORE_NSS; + fcargs.certLabel = certlabel; + fcargs.issuer = issuer; + fcargs.subject = subject; + fcargs.serial = serial; + fcargs.nssparms.slotlabel = token_spec; + + rv = pk_find_export_cert(kmfhandle, &fcargs, &kmfcert); + if (rv == KMF_OK) { + (void) memset(&scparms, 0, sizeof (scparms)); + scparms.kstype = KMF_KEYSTORE_OPENSSL; + scparms.sslparms.certfile = filename; + scparms.sslparms.format = kfmt; + + rv = KMF_StoreCert(kmfhandle, &scparms, + &kmfcert.certificate); + + KMF_FreeKMFCert(kmfhandle, &kmfcert); } } + return (rv); +} - /* Now really get the attributes. */ - cryptodebug("calling C_GetAttributeValue for attribute info"); - if ((rv = C_GetAttributeValue(sess, obj, dh_pri_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get DH private key attributes (%s)."), - pkcs11_strerror(rv)); - return (rv); - } - - /* Fill in all the temp variables. They are all required. */ - i = 0; - copy_attr_to_bigint(&(dh_pri_attrs[i++]), &prime); - copy_attr_to_bigint(&(dh_pri_attrs[i++]), &base); - copy_attr_to_bigint(&(dh_pri_attrs[i++]), &value); - - /* Start the conversion to internal OpenSSL DH structure. */ +static KMF_RETURN +pk_export_pk12_pk11(KMF_HANDLE_T kmfhandle, char *token_spec, + char *certlabel, char *issuer, char *subject, + KMF_BIGINT *serial, KMF_CREDENTIAL *tokencred, char *filename) +{ + KMF_RETURN rv = KMF_OK; + KMF_EXPORTP12_PARAMS p12parms; - /* Prime p */ - if (cvt_bigint2bn(&prime, &(dh->p)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DH private key prime.")); - return (CKR_GENERAL_ERROR); + rv = select_token(kmfhandle, token_spec, TRUE); + if (rv != KMF_OK) { + return (rv); } - /* Base g */ - if (cvt_bigint2bn(&base, &(dh->g)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DH private key base.")); - return (CKR_GENERAL_ERROR); - } + (void) memset(&p12parms, 0, sizeof (p12parms)); - /* Private value x */ - if (cvt_bigint2bn(&value, &(dh->priv_key)) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert DH private key value.")); - return (CKR_GENERAL_ERROR); - } + p12parms.kstype = KMF_KEYSTORE_PK11TOKEN; + p12parms.certLabel = certlabel; + p12parms.issuer = issuer; + p12parms.subject = subject; + p12parms.serial = serial; + p12parms.idstr = NULL; + if (tokencred != NULL) + p12parms.cred = *tokencred; + (void) get_pk12_password(&p12parms.p12cred); - /* Create OpenSSL EVP PKEY struct in which to stuff DH struct. */ - cryptodebug("calling EVP_PKEY_new"); - if ((key = EVP_PKEY_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal EVP_PKEY structure.")); - return (CKR_HOST_MEMORY); - } + rv = KMF_ExportPK12(kmfhandle, &p12parms, filename); - /* Put the DH struct into the EVP_PKEY struct and return it. */ - cryptodebug("calling EVP_PKEY_set1_DH"); - (void) EVP_PKEY_set1_DH(key, dh); + if (p12parms.p12cred.cred) + free(p12parms.p12cred.cred); - *pk = key; - return (CKR_OK); + return (rv); } -/* - * Convert PKCS#11 private key object to OpenSSL EVP_PKEY structure. - */ -static CK_RV -cvt_obj2evp_pkey(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, EVP_PKEY **pk) +static KMF_RETURN +pk_export_pk11_objects(KMF_HANDLE_T kmfhandle, char *token_spec, + char *certlabel, char *issuer, char *subject, + KMF_BIGINT *serial, KMF_ENCODE_FORMAT kfmt, + char *filename) { - CK_RV rv = CKR_OK; - static CK_KEY_TYPE keytype = 0; - CK_ATTRIBUTE keytype_attr[1] = { - { CKA_KEY_TYPE, &keytype, sizeof (keytype) } - }; - - cryptodebug("inside cvt_obj2evp_pkey"); - - /* Find out the key type to do the right conversion. */ - cryptodebug("calling C_GetAttributeValue"); - if ((rv = C_GetAttributeValue(sess, obj, keytype_attr, 1)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get token object key type (%s)."), - pkcs11_strerror(rv)); - return (rv); - } + KMF_RETURN rv = KMF_OK; + KMF_FINDCERT_PARAMS fcparms; + KMF_STORECERT_PARAMS scparms; + KMF_X509_DER_CERT kmfcert; - switch (keytype) { - case CKK_RSA: - cryptodebug("converting RSA key"); - return (cvt_rsa2evp_pkey(sess, obj, pk)); - case CKK_DSA: - cryptodebug("converting DSA key"); - return (cvt_dsa2evp_pkey(sess, obj, pk)); - case CKK_DH: - cryptodebug("converting DH key"); - return (cvt_dh2evp_pkey(sess, obj, pk)); - default: - cryptoerror(LOG_STDERR, gettext( - "Private key type 0x%02x conversion not supported."), - keytype); - return (CKR_GENERAL_ERROR); - } -} - -/* - * Convert PKCS#11 certificate object to OpenSSL X509 structure. - */ -static CK_RV -cvt_cert2x509(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, X509 **c) -{ - CK_RV rv = CKR_OK; - X509 *cert = NULL; /* OpenSSL representation */ - X509 *temp_cert = NULL; - CK_BYTE *subject = NULL; - CK_ULONG subject_len = 0; - CK_BYTE *value = NULL; - CK_ULONG value_len = 0; - CK_BYTE *label = NULL; - CK_ULONG label_len = 0; - CK_BYTE *id = NULL; - CK_ULONG id_len = 0; - CK_BYTE *issuer = NULL; - CK_ULONG issuer_len = 0; - CK_BYTE *serial = NULL; - CK_ULONG serial_len = 0; - CK_ATTRIBUTE cert_attrs[6] = { - { CKA_SUBJECT, NULL, 0 }, /* required */ - { CKA_VALUE, NULL, 0 }, /* required */ - { CKA_LABEL, NULL, 0 }, /* optional */ - { CKA_ID, NULL, 0 }, /* optional */ - { CKA_ISSUER, NULL, 0 }, /* optional */ - { CKA_SERIAL_NUMBER, NULL, 0 } /* optional */ - }; - CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE); - int i = 0; - X509_NAME *ssl_subject = NULL; - X509_NAME *ssl_issuer = NULL; - ASN1_INTEGER *ssl_serial = NULL; - - cryptodebug("inside cvt_cert2x509"); - - cryptodebug("calling X509_new"); - if ((cert = X509_new()) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to allocate internal X509 structure.")); - return (CKR_HOST_MEMORY); - } + rv = select_token(kmfhandle, token_spec, TRUE); - /* Get the sizes of the attributes we need. */ - cryptodebug("calling C_GetAttributeValue for size info"); - if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get certificate attribute sizes (%s)."), - pkcs11_strerror(rv)); + if (rv != KMF_OK) { return (rv); } - /* Allocate memory for each attribute. */ - for (i = 0; i < count; i++) { - if (cert_attrs[i].ulValueLen == (CK_ULONG)-1 || - cert_attrs[i].ulValueLen == 0) { - cryptodebug("cvt_cert2x509: *** should not happen"); - cert_attrs[i].ulValueLen = 0; - continue; - } - if ((cert_attrs[i].pValue = malloc(cert_attrs[i].ulValueLen)) - == NULL) { - cryptoerror(LOG_STDERR, "%s.", strerror(errno)); - return (CKR_HOST_MEMORY); - } - } + (void) memset(&fcparms, 0, sizeof (fcparms)); + fcparms.kstype = KMF_KEYSTORE_PK11TOKEN; + fcparms.certLabel = certlabel; + fcparms.issuer = issuer; + fcparms.subject = subject; + fcparms.serial = serial; - /* Now really get the attributes. */ - cryptodebug("calling C_GetAttributeValue for attribute info"); - if ((rv = C_GetAttributeValue(sess, obj, cert_attrs, count)) != - CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get certificate attributes (%s)."), - pkcs11_strerror(rv)); - return (rv); - } - - /* - * Fill in all the temp variables. Subject and value are required. - * The rest are optional. - */ - i = 0; - copy_attr_to_string(&(cert_attrs[i++]), &subject, &subject_len); - copy_attr_to_string(&(cert_attrs[i++]), &value, &value_len); - - if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && - cert_attrs[i].ulValueLen != 0) - copy_attr_to_string(&(cert_attrs[i]), &label, &label_len); - i++; - - if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && - cert_attrs[i].ulValueLen != 0) - copy_attr_to_string(&(cert_attrs[i]), &id, &id_len); - i++; - - if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && - cert_attrs[i].ulValueLen != 0) - copy_attr_to_string(&(cert_attrs[i]), &issuer, &issuer_len); - i++; - - if (cert_attrs[i].ulValueLen != (CK_ULONG)-1 && - cert_attrs[i].ulValueLen != 0) - copy_attr_to_string(&(cert_attrs[i]), &serial, &serial_len); - i++; - - /* Start the conversion to internal OpenSSL X509 structure. */ - - /* Subject name (required) */ - cryptodebug("calling d2i_X509_NAME for subject name"); - if ((ssl_subject = d2i_X509_NAME(NULL, - (const unsigned char **) &subject, subject_len)) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert certificate subject name.")); - return (CKR_GENERAL_ERROR); - } - cryptodebug("calling X509_set_subject_name"); - if (!X509_set_subject_name(cert, ssl_subject)) { - cryptoerror(LOG_STDERR, gettext( - "Unable to pack certificate subject name entries.")); - return (CKR_GENERAL_ERROR); - } - - /* Label (optional) */ - cryptodebug("calling X509_alias_set1"); - if (!X509_alias_set1(cert, label, label_len)) - cryptodebug("error not caught"); - - /* Id (optional) */ - cryptodebug("calling X509_keyid_set1"); - if (!X509_keyid_set1(cert, id, id_len)) - cryptodebug("error not caught"); - - /* Issuer name (optional) */ - cryptodebug("calling d2i_X509_NAME for issuer name"); - if ((ssl_issuer = d2i_X509_NAME(NULL, (const unsigned char **) &issuer, - issuer_len)) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert certificate issuer name.")); - return (CKR_GENERAL_ERROR); - } - cryptodebug("calling X509_set_issuer_name"); - if (!X509_set_issuer_name(cert, ssl_issuer)) { - cryptoerror(LOG_STDERR, gettext( - "Unable to pack certificate issuer name entries.")); - return (CKR_GENERAL_ERROR); - } - - /* Serial number (optional) */ - cryptodebug("calling OPENSSL_malloc() for serial number"); - if ((ssl_serial = OPENSSL_malloc(sizeof (ASN1_INTEGER))) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert certificate serial number.")); - return (CKR_HOST_MEMORY); - } - ssl_serial->length = serial_len; - ssl_serial->type = (serial[0] & 0x80) ? V_ASN1_NEG_INTEGER : - V_ASN1_INTEGER; - ssl_serial->data = serial; - ssl_serial->flags = 0; - cryptodebug("calling X509_set_serialNumber"); - if (!X509_set_serialNumber(cert, ssl_serial)) - cryptodebug("error not caught"); - - /* - * Value (required) - * - * The rest of this code takes the CKA_VALUE attribute, converts - * it into a temp OpenSSL X509 structure and picks out the rest - * of the fields we need to convert it back into the current X509 - * structure that will get exported. The reason we don't just - * start with CKA_VALUE is because while the object was in the - * softtoken, it is possible that some of its attributes changed. - * Those changes would not appear in CKA_VALUE and would be lost - * if we started with CKA_VALUE that was saved originally. - */ - cryptodebug("calling d2i_X509 for cert value"); - if ((temp_cert = d2i_X509(NULL, (const unsigned char **) &value, - value_len)) == NULL) { - cryptoerror(LOG_STDERR, gettext( - "Unable to convert main certificate values.")); - return (CKR_GENERAL_ERROR); - } - - /* Transfer these values from temp_cert to cert. */ - cryptodebug("calling X509_set_version/X509_get_version"); - if (!X509_set_version(cert, X509_get_version(temp_cert))) - cryptodebug("error not caught"); - - cryptodebug("calling X509_set_notBefore/X509_get_notBefore"); - if (!X509_set_notBefore(cert, X509_get_notBefore(temp_cert))) - cryptodebug("error not caught"); - - cryptodebug("calling X509_set_notAfter/X509_get_notAfter"); - if (!X509_set_notAfter(cert, X509_get_notAfter(temp_cert))) - cryptodebug("error not caught"); - - cryptodebug("calling X509_set_pubkey/X509_get_pubkey"); - if (!X509_set_pubkey(cert, X509_get_pubkey(temp_cert))) - cryptodebug("error not caught"); - - /* - * These don't get transfered from temp_cert to cert. - * It -appears- that they may get regenerated as needed. - * - * cert->cert_info->signature = dup(temp_cert->cert_info->signature); - * cert->sig_alg = dup(temp_cert->sig_alg); - * cert->signature = dup(temp_cert->signature); - * cert->skid = dup(temp_cert->skid); - * cert->akid = dup(temp_cert->akid); - */ - - *c = cert; - return (CKR_OK); -} - -static CK_RV -convert_token_objs(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj, - CK_OBJECT_HANDLE mate, CK_OBJECT_HANDLE *chain, CK_ULONG chain_len, - EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca) -{ - CK_RV rv = CKR_OK; - EVP_PKEY *pk = NULL; - X509 *c = NULL; - X509 *one_ca = NULL; - STACK_OF(X509) *ch = NULL; - int i; + rv = pk_find_export_cert(kmfhandle, &fcparms, &kmfcert); - cryptodebug("inside convert_token_objs"); + if (rv == KMF_OK) { + (void) memset(&scparms, 0, sizeof (scparms)); + scparms.kstype = KMF_KEYSTORE_OPENSSL; + scparms.sslparms.certfile = filename; + scparms.sslparms.format = kfmt; - if ((rv = cvt_obj2evp_pkey(sess, obj, &pk)) != CKR_OK) - return (rv); - - if (mate != ~0UL) { - cryptodebug("converting cert corresponding to private key"); - if ((rv = cvt_cert2x509(sess, mate, &c)) != CKR_OK) - return (rv); - } + rv = KMF_StoreCert(kmfhandle, &scparms, + &kmfcert.certificate); - if (chain_len != 0) { - cryptodebug("converting ca chain of %d certs corresponding " - "to private key", chain_len); - ch = sk_X509_new_null(); - for (i = 0; i < chain_len; i++) { - if ((rv = cvt_cert2x509(sess, chain[i], &one_ca)) != - CKR_OK) { - return (rv); - } - if (!sk_X509_push(ch, one_ca)) - cryptodebug("error not caught"); - } + KMF_FreeKMFCert(kmfhandle, &kmfcert); } - - *priv_key = pk; - *cert = (mate != ~0UL) ? c : NULL; - *ca = (chain_len != 0) ? ch : NULL; - return (CKR_OK); + return (rv); } /* - * Export objects from token to PKCS#12 file. + * Export objects from one keystore to a file. */ int pk_export(int argc, char *argv[]) @@ -1210,231 +304,263 @@ pk_export(int argc, char *argv[]) extern int optind_av; extern char *optarg_av; char *token_spec = NULL; - char *token_name = NULL; - char *manuf_id = NULL; - char *serial_no = NULL; - char full_name[FULL_NAME_LEN]; char *filename = NULL; - CK_SLOT_ID slot_id; - CK_FLAGS pin_state; - CK_UTF8CHAR_PTR pin = NULL; - CK_ULONG pinlen = 0; - CK_UTF8CHAR_PTR pk12pin = NULL; - CK_ULONG pk12pinlen = 0; - CK_SESSION_HANDLE sess; - BIO *fbio = NULL; - EVP_PKEY *priv_key = NULL; - X509 *cert = NULL; - STACK_OF(X509) *ca = NULL; - CK_RV rv = CKR_OK; - CK_OBJECT_HANDLE *objs = NULL; - CK_ULONG num_objs = 0; - CK_OBJECT_HANDLE mate = ~0UL; - CK_OBJECT_HANDLE *chain = NULL; - CK_ULONG chain_len; - CK_BYTE *id = NULL; - CK_ULONG id_len = 0; - int i = 0; - int good_ones = 0, bad_ones = 0; /* running totals */ - - cryptodebug("inside pk_export"); + char *dir = NULL; + char *prefix = NULL; + char *certlabel = NULL; + char *subject = NULL; + char *issuer = NULL; + char *infile = NULL; + char *keyfile = NULL; + char *certfile = NULL; + char *serstr = NULL; + KMF_KEYSTORE_TYPE kstype = 0; + KMF_ENCODE_FORMAT kfmt = KMF_FORMAT_PKCS12; + KMF_RETURN rv = KMF_OK; + int oclass = PK_CERT_OBJ; + KMF_BIGINT serial = { NULL, 0 }; + KMF_HANDLE_T kmfhandle = NULL; + KMF_CREDENTIAL tokencred = {NULL, 0}; /* Parse command line options. Do NOT i18n/l10n. */ - while ((opt = getopt_av(argc, argv, "T:(token)o:(outfile)")) != EOF) { + while ((opt = getopt_av(argc, argv, + "k:(keystore)y:(objtype)T:(token)" + "d:(dir)p:(prefix)" + "l:(label)n:(nickname)s:(subject)" + "i:(issuer)S:(serial)" + "K:(keyfile)c:(certfile)" + "F:(outformat)" + "I:(infile)o:(outfile)")) != EOF) { + if (EMPTYSTRING(optarg_av)) + return (PK_ERR_USAGE); switch (opt) { + case 'k': + kstype = KS2Int(optarg_av); + if (kstype == 0) + return (PK_ERR_USAGE); + break; + case 'y': + oclass = OT2Int(optarg_av); + if (oclass == -1) + return (PK_ERR_USAGE); + break; case 'T': /* token specifier */ if (token_spec) return (PK_ERR_USAGE); token_spec = optarg_av; break; + case 'd': + if (dir) + return (PK_ERR_USAGE); + dir = optarg_av; + break; + case 'p': + if (prefix) + return (PK_ERR_USAGE); + prefix = optarg_av; + break; + case 'n': + case 'l': + if (certlabel) + return (PK_ERR_USAGE); + certlabel = optarg_av; + break; + case 's': + if (subject) + return (PK_ERR_USAGE); + subject = optarg_av; + break; + case 'i': + if (issuer) + return (PK_ERR_USAGE); + issuer = optarg_av; + break; + case 'S': + serstr = optarg_av; + break; + case 'F': + kfmt = Str2Format(optarg_av); + if (kfmt == KMF_FORMAT_UNDEF) + return (PK_ERR_USAGE); + break; + case 'I': /* output file name */ + if (infile) + return (PK_ERR_USAGE); + infile = optarg_av; + break; case 'o': /* output file name */ if (filename) return (PK_ERR_USAGE); filename = optarg_av; break; + case 'c': /* input cert file name */ + if (certfile) + return (PK_ERR_USAGE); + certfile = optarg_av; + break; + case 'K': /* input key file name */ + if (keyfile) + return (PK_ERR_USAGE); + keyfile = optarg_av; + break; default: return (PK_ERR_USAGE); break; } } - /* If nothing is specified, default is to use softtoken. */ - if (token_spec == NULL) { - token_name = SOFT_TOKEN_LABEL; - manuf_id = SOFT_MANUFACTURER_ID; - serial_no = SOFT_TOKEN_SERIAL; - } else { - /* - * Parse token specifier into token_name, manuf_id, serial_no. - * Token_name is required; manuf_id and serial_no are optional. - */ - if (parse_token_spec(token_spec, &token_name, &manuf_id, - &serial_no) < 0) - return (PK_ERR_USAGE); - } + /* Assume keystore = PKCS#11 if not specified */ + if (kstype == 0) + kstype = KMF_KEYSTORE_PK11TOKEN; /* Filename arg is required. */ - if (filename == NULL) + if (EMPTYSTRING(filename)) { + cryptoerror(LOG_STDERR, gettext("You must specify " + "an 'outfile' parameter when exporting.\n")); return (PK_ERR_USAGE); + } /* No additional args allowed. */ argc -= optind_av; argv += optind_av; if (argc) return (PK_ERR_USAGE); - /* Done parsing command line options. */ + + /* if PUBLIC or PRIVATE obj was given, the old syntax was used. */ + if ((oclass & (PK_PUBLIC_OBJ | PK_PRIVATE_OBJ)) && + kstype != KMF_KEYSTORE_PK11TOKEN) { + + (void) fprintf(stderr, gettext("The objtype parameter " + "is only relevant if keystore=pkcs11\n")); + return (PK_ERR_USAGE); + } + + if (kstype == KMF_KEYSTORE_PK11TOKEN && EMPTYSTRING(token_spec)) + token_spec = PK_DEFAULT_PK11TOKEN; + else if (kstype == KMF_KEYSTORE_NSS && EMPTYSTRING(token_spec)) + token_spec = DEFAULT_NSS_TOKEN; + + if (kstype == KMF_KEYSTORE_OPENSSL) { + if (kfmt != KMF_FORMAT_PKCS12) { + cryptoerror(LOG_STDERR, gettext("PKCS12 " + "is the only export format " + "supported for the 'file' " + "keystore.\n")); + return (PK_ERR_USAGE); + } + if (EMPTYSTRING(keyfile) || EMPTYSTRING(certfile)) { + cryptoerror(LOG_STDERR, gettext("A cert file" + "and a key file must be specified " + "when exporting to PKCS12 from the " + "'file' keystore.\n")); + return (PK_ERR_USAGE); + } + } /* Check if the file exists and might be overwritten. */ if (access(filename, F_OK) == 0) { - cryptoerror(LOG_STDERR, gettext("Warning: file \"%s\" exists, " - "will be overwritten."), filename); + cryptoerror(LOG_STDERR, + gettext("Warning: file \"%s\" exists, " + "will be overwritten."), filename); if (yesno(gettext("Continue with export? "), gettext("Respond with yes or no.\n"), B_FALSE) == B_FALSE) { return (0); } + } else { + rv = verify_file(filename); + if (rv != KMF_OK) { + cryptoerror(LOG_STDERR, gettext("The file (%s) " + "cannot be created.\n"), filename); + return (PK_ERR_USAGE); + } } - full_token_name(token_name, manuf_id, serial_no, full_name); - - /* Find the slot with token. */ - if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, - &pin_state)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to find token %s (%s)."), full_name, - pkcs11_strerror(rv)); - return (PK_ERR_PK11); - } - - /* Get the user's PIN. */ - if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, - &pinlen)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to get token passphrase (%s)."), - pkcs11_strerror(rv)); - quick_finish(NULL); - return (PK_ERR_PK11); - } - - /* Assume user must be logged in R/W to export objects from token. */ - if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) != - CKR_OK) { - cryptoerror(LOG_STDERR, - gettext("Unable to log into token (%s)."), - pkcs11_strerror(rv)); - quick_finish(sess); - return (PK_ERR_PK11); - } + if (serstr != NULL) { + uchar_t *bytes = NULL; + size_t bytelen; - /* Collect all private keys first. */ - if ((rv = find_objs(sess, PK_PRIVATE_OBJ|PK_KEY_OBJ, NULL, - &objs, &num_objs)) != CKR_OK) { - cryptoerror(LOG_STDERR, gettext( - "Unable to retrieve private key token objects (%s)."), - pkcs11_strerror(rv)); - quick_finish(sess); - return (PK_ERR_PK11); + rv = KMF_HexString2Bytes((uchar_t *)serstr, &bytes, &bytelen); + if (rv != KMF_OK || bytes == NULL) { + (void) fprintf(stderr, gettext("serial number " + "must be specified as a hex number " + "(ex: 0x0102030405ffeeddee)\n")); + return (PK_ERR_USAGE); + } + serial.val = bytes; + serial.len = bytelen; } - /* Nothing to do? */ - if (num_objs == 0) { - cryptoerror(LOG_STDERR, gettext("No objects found.")); - quick_finish(sess); - return (0); + if ((kstype == KMF_KEYSTORE_PK11TOKEN || + kstype == KMF_KEYSTORE_NSS) && + (oclass & (PK_KEY_OBJ | PK_PRIVATE_OBJ) || + kfmt == KMF_FORMAT_PKCS12)) { + (void) get_token_password(kstype, token_spec, + &tokencred); } - /* Setup OpenSSL context. */ - PKTOOL_setup_openssl(); - - /* Create PKCS#12 file. */ - if ((create_pkcs12(filename, &fbio)) < 0) { - cryptoerror(LOG_STDERR, gettext("No export file created.")); - quick_finish(sess); - return (PK_ERR_SYSTEM); + if ((rv = KMF_Initialize(&kmfhandle, NULL, NULL)) != KMF_OK) { + cryptoerror(LOG_STDERR, gettext("Error initializing " + "KMF: 0x%02x\n"), rv); + return (rv); } - /* Get the PIN for the PKCS#12 export file. */ - if ((rv = get_pin(gettext("Create export file passphrase:"), gettext( - "Re-enter export file passphrase:"), &pk12pin, &pk12pinlen)) != - CKR_OK) { - cryptoerror(LOG_STDERR, - gettext("Unable to get export file passphrase (%s)."), - pkcs11_strerror(rv)); - close_pkcs12(fbio); - quick_finish(sess); - return (PK_ERR_PK11); + switch (kstype) { + case KMF_KEYSTORE_PK11TOKEN: + if (kfmt == KMF_FORMAT_PKCS12) + rv = pk_export_pk12_pk11( + kmfhandle, + token_spec, + certlabel, + issuer, subject, + &serial, &tokencred, + filename); + else + rv = pk_export_pk11_objects(kmfhandle, + token_spec, + certlabel, + issuer, subject, + &serial, kfmt, + filename); + break; + case KMF_KEYSTORE_NSS: + if (dir == NULL) + dir = PK_DEFAULT_DIRECTORY; + if (kfmt == KMF_FORMAT_PKCS12) + rv = pk_export_pk12_nss(kmfhandle, + token_spec, dir, prefix, + certlabel, issuer, + subject, &serial, + &tokencred, filename); + else + rv = pk_export_nss_objects(kmfhandle, + token_spec, + oclass, certlabel, issuer, subject, + &serial, kfmt, dir, prefix, filename); + break; + case KMF_KEYSTORE_OPENSSL: + if (kfmt == KMF_FORMAT_PKCS12) + rv = pk_export_pk12_files(kmfhandle, + certfile, keyfile, dir, + filename); + else + rv = pk_export_file_objects(kmfhandle, oclass, + issuer, subject, &serial, kfmt, + dir, infile, filename); + break; + default: + rv = PK_ERR_USAGE; + break; } - for (i = 0; i < num_objs; i++) { - /* Get a private key and its certificate and CA chain. */ - if ((rv = get_token_objs(sess, objs[i], &mate, &chain, - &chain_len, &id, &id_len)) != CKR_OK) { - /* - * Note this "rv" is either CKR_OK or !CKR_OK. The - * real error codes/messages are handled inside - * read_token_objs(). - */ - cryptoerror(LOG_STDERR, - gettext("Unable to get token objects.")); - free(id); - close_pkcs12(fbio); - quick_finish(sess); - return (PK_ERR_PK11); - } - - /* Convert to OpenSSL equivalents. */ - if ((rv = convert_token_objs(sess, objs[i], mate, chain, - chain_len, &priv_key, &cert, &ca)) != CKR_OK) { - /* - * Note this "rv" is either CKR_OK or !CKR_OK. The - * real error codes/messages are handled inside - * read_token_objs(). - */ - cryptoerror(LOG_STDERR, - gettext("Unable to convert token objects.")); - free(id); - close_pkcs12(fbio); - quick_finish(sess); - return (PK_ERR_PK11); - } - - /* - * When exporting of cert chains is implemented, these - * messages should be updated accordingly. - */ - if (mate == ~0UL) - (void) fprintf(stdout, gettext( - "Writing object #%d...\n"), i+1); - else - (void) fprintf(stdout, gettext("Writing object #%d " - "and its certificate...\n"), i+1); - - /* Write object and its certs to the PKCS#12 export file. */ - if (write_objs_pkcs12(fbio, pk12pin, pk12pinlen, id, id_len, - priv_key, cert, ca, &good_ones, &bad_ones) < 0) { - cryptoerror(LOG_STDERR, gettext( - "Unable to write object #%d to export file."), i+1); - sk_X509_pop_free(ca, X509_free); - free(id); - close_pkcs12(fbio); - quick_finish(sess); - return (PK_ERR_OPENSSL); - } - - /* Destroy key id and CA cert chain, done with them. */ - free(id); - id = NULL; - sk_X509_pop_free(ca, X509_free); - ca = NULL; + if (rv != KMF_OK) { + display_error(kmfhandle, rv, + gettext("Error exporting objects")); } - (void) fprintf(stdout, gettext( - "%d token objects exported, %d errors occurred.\n"), - good_ones, bad_ones); + if (serial.val != NULL) + free(serial.val); - /* Close PKCS#12 file. */ - close_pkcs12(fbio); + (void) KMF_Finalize(kmfhandle); - /* Clean up. */ - quick_finish(sess); - return (0); + return (rv); } |