117Sdinak /* 217Sdinak * CDDL HEADER START 317Sdinak * 417Sdinak * The contents of this file are subject to the terms of the 517Sdinak * Common Development and Distribution License, Version 1.0 only 617Sdinak * (the "License"). You may not use this file except in compliance 717Sdinak * with the License. 817Sdinak * 917Sdinak * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 1017Sdinak * or http://www.opensolaris.org/os/licensing. 1117Sdinak * See the License for the specific language governing permissions 1217Sdinak * and limitations under the License. 1317Sdinak * 1417Sdinak * When distributing Covered Code, include this CDDL HEADER in each 1517Sdinak * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1617Sdinak * If applicable, add the following below this CDDL HEADER, with the 1717Sdinak * fields enclosed by brackets "[]" replaced with your own identifying 1817Sdinak * information: Portions Copyright [yyyy] [name of copyright owner] 1917Sdinak * 2017Sdinak * CDDL HEADER END 2117Sdinak */ 2217Sdinak /* 2317Sdinak * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2417Sdinak * Use is subject to license terms. 2517Sdinak */ 2617Sdinak 2717Sdinak #pragma ident "%Z%%M% %I% %E% SMI" 2817Sdinak 2917Sdinak /* 3017Sdinak * This file implements the import operation for this tool. 3117Sdinak * The basic flow of the process is to decrypt the PKCS#12 3217Sdinak * input file if it has a password, parse the elements in 3317Sdinak * the file, find the soft token, log into it, import the 3417Sdinak * PKCS#11 objects into the soft token, and log out. 3517Sdinak */ 3617Sdinak 3717Sdinak #include <stdio.h> 3817Sdinak #include <stdlib.h> 3917Sdinak #include <string.h> 4017Sdinak #include <errno.h> 4117Sdinak #include <fcntl.h> 4217Sdinak #include <sys/types.h> 4317Sdinak #include <sys/stat.h> 4417Sdinak #include <cryptoutil.h> 4517Sdinak #include <security/cryptoki.h> 4617Sdinak #include "common.h" 4717Sdinak #include "biginteger.h" 4817Sdinak #include "osslcommon.h" 4917Sdinak #include "p12common.h" 5017Sdinak #include <openssl/pkcs12.h> 5117Sdinak #include <openssl/err.h> 5217Sdinak 5317Sdinak /* 5417Sdinak * Helper function decrypt and parse PKCS#12 import file. 5517Sdinak */ 5617Sdinak static CK_RV 5717Sdinak extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen, 5817Sdinak EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca) 5917Sdinak /* ARGSUSED */ 6017Sdinak { 6117Sdinak PKCS12 *pk12, *pk12_tmp; 6217Sdinak EVP_PKEY *temp_pkey = NULL; 6317Sdinak X509 *temp_cert = NULL; 6417Sdinak STACK_OF(X509) *temp_ca = NULL; 6517Sdinak 6617Sdinak cryptodebug("inside extract_pkcs12"); 6717Sdinak 6817Sdinak cryptodebug("calling PKCS12_new"); 6917Sdinak if ((pk12 = PKCS12_new()) == NULL) { 7017Sdinak cryptoerror(LOG_STDERR, gettext( 7117Sdinak "Unable to create PKCS#12 context.")); 7217Sdinak return (CKR_GENERAL_ERROR); 7317Sdinak } 7417Sdinak 7517Sdinak cryptodebug("calling d2i_PKCS12_bio"); 7617Sdinak if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) { 7717Sdinak /* This is ok; it seems to mean there is no more to read. */ 7817Sdinak if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 && 7917Sdinak ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG) 8017Sdinak goto end_extract_pkcs12; 8117Sdinak 8217Sdinak cryptoerror(LOG_STDERR, gettext( 8317Sdinak "Unable to populate PKCS#12 context.")); 8417Sdinak PKCS12_free(pk12); 8517Sdinak return (CKR_GENERAL_ERROR); 8617Sdinak } 8717Sdinak pk12 = pk12_tmp; 8817Sdinak 8917Sdinak cryptodebug("calling PKCS12_parse"); 9017Sdinak if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert, 9117Sdinak &temp_ca) <= 0) { 9217Sdinak cryptoerror(LOG_STDERR, 9317Sdinak gettext("Unable to parse import file.")); 9417Sdinak PKCS12_free(pk12); 9517Sdinak return (CKR_GENERAL_ERROR); 9617Sdinak } 9717Sdinak 9817Sdinak end_extract_pkcs12: 9917Sdinak 10017Sdinak *priv_key = temp_pkey; 10117Sdinak *cert = temp_cert; 10217Sdinak *ca = temp_ca; 10317Sdinak 10417Sdinak PKCS12_free(pk12); 10517Sdinak return (CKR_OK); 10617Sdinak } 10717Sdinak 10817Sdinak /* 10917Sdinak * Converts OpenSSL BIGNUM into PKCS#11 biginteger_t format. 11017Sdinak */ 11117Sdinak static CK_RV 11217Sdinak cvt_bn2bigint(BIGNUM *from, biginteger_t *to) 11317Sdinak { 11417Sdinak CK_BYTE *temp; 11517Sdinak CK_ULONG temp_alloc_sz, temp_cvt_sz; 11617Sdinak 11717Sdinak cryptodebug("inside cvt_bn2bigint"); 11817Sdinak 11917Sdinak if (from == NULL || to == NULL) 12017Sdinak return (CKR_ARGUMENTS_BAD); 12117Sdinak 12217Sdinak cryptodebug("calling BN_num_bytes"); 12317Sdinak temp_alloc_sz = BN_num_bytes(from); 12417Sdinak if ((temp = malloc(temp_alloc_sz)) == NULL) 12517Sdinak return (CKR_HOST_MEMORY); 12617Sdinak 12717Sdinak cryptodebug("calling BN_bn2bin"); 12817Sdinak temp_cvt_sz = BN_bn2bin(from, (unsigned char *)temp); 12917Sdinak if (temp_cvt_sz != temp_alloc_sz) 13017Sdinak return (CKR_GENERAL_ERROR); 13117Sdinak 13217Sdinak to->big_value = temp; 13317Sdinak to->big_value_len = temp_cvt_sz; 13417Sdinak return (CKR_OK); 13517Sdinak } 13617Sdinak 13717Sdinak /* 13817Sdinak * Write RSA private key to token. 13917Sdinak */ 14017Sdinak static CK_RV 14117Sdinak write_rsa_private(CK_SESSION_HANDLE sess, RSA *rsa, X509 *cert) 14217Sdinak { 14317Sdinak CK_RV rv = CKR_OK; 14417Sdinak int i = 0; 14517Sdinak static CK_OBJECT_CLASS objclass = CKO_PRIVATE_KEY; 14617Sdinak static CK_KEY_TYPE keytype = CKK_RSA; 14717Sdinak CK_BYTE *label = NULL; 14817Sdinak CK_ULONG label_len = 0; 14917Sdinak CK_BYTE *id = NULL; 15017Sdinak CK_ULONG id_len = 0; 15117Sdinak CK_DATE startdate = { "", "", "" }; 15217Sdinak CK_DATE enddate = { "", "", "" }; 15317Sdinak char tmpdate[8]; 15417Sdinak biginteger_t mod = { NULL, 0 }; /* required */ 15517Sdinak biginteger_t pubexp = { NULL, 0 }; /* required */ 15617Sdinak biginteger_t priexp = { NULL, 0 }; /* optional */ 15717Sdinak biginteger_t prime1 = { NULL, 0 }; /* optional */ 15817Sdinak biginteger_t prime2 = { NULL, 0 }; /* optional */ 15917Sdinak biginteger_t exp1 = { NULL, 0 }; /* optional */ 16017Sdinak biginteger_t exp2 = { NULL, 0 }; /* optional */ 16117Sdinak biginteger_t coef = { NULL, 0 }; /* optional */ 16217Sdinak CK_ATTRIBUTE rsa_pri_attrs[16] = { 16317Sdinak { CKA_CLASS, &objclass, sizeof (objclass) }, 16417Sdinak { CKA_KEY_TYPE, &keytype, sizeof (keytype) }, 16517Sdinak { CKA_PRIVATE, &pk_true, sizeof (pk_true) }, 16617Sdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 16717Sdinak { CKA_LABEL, NULL, 0 }, 16817Sdinak { CKA_ID, NULL, 0 }, 16917Sdinak { CKA_START_DATE, NULL, 0 }, 17017Sdinak { CKA_END_DATE, NULL, 0 }, 17117Sdinak { CKA_MODULUS, NULL, 0 }, 17217Sdinak { CKA_PUBLIC_EXPONENT, NULL, 0 }, 17317Sdinak { 0 /* CKA_PRIVATE_EXPONENT */, NULL, 0 }, /* optional */ 17417Sdinak { 0 /* CKA_PRIME_1 */, NULL, 0 }, /* | */ 17517Sdinak { 0 /* CKA_PRIME_2 */, NULL, 0 }, /* | */ 17617Sdinak { 0 /* CKA_EXPONENT_1 */, NULL, 0 }, /* | */ 17717Sdinak { 0 /* CKA_EXPONENT_2 */, NULL, 0 }, /* | */ 17817Sdinak { 0 /* CKA_COEFFICIENT */, NULL, 0 } /* V */ 17917Sdinak }; 18017Sdinak CK_ULONG count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE); 18117Sdinak CK_OBJECT_HANDLE obj; 18217Sdinak 18317Sdinak cryptodebug("inside write_rsa_private"); 18417Sdinak 18517Sdinak /* Attributes start at array index 4. */ 18617Sdinak i = 4; 18717Sdinak 18817Sdinak /* Recycle the certificate label for the private key label. */ 18917Sdinak cryptodebug("calling X509_alias_get0"); 19017Sdinak if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) { 19117Sdinak label = (CK_BYTE *)gettext("no label"); 19217Sdinak label_len = strlen((char *)label); 19317Sdinak } 19417Sdinak copy_string_to_attr(label, label_len, &(rsa_pri_attrs[i++])); 19517Sdinak 19617Sdinak /* Recycle the certificate id for the private key id. */ 19717Sdinak cryptodebug("calling PKTOOL_X509_keyid_get0"); 19817Sdinak if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) { 19917Sdinak id = (CK_BYTE *)gettext("no id"); 20017Sdinak id_len = strlen((char *)id); 20117Sdinak } 20217Sdinak copy_string_to_attr(id, id_len, &(rsa_pri_attrs[i++])); 20317Sdinak 20417Sdinak /* Recycle the certificate start and end dates for private key. */ 20517Sdinak cryptodebug("calling X509_get_notBefore"); 20617Sdinak if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) { 20717Sdinak (void) memcpy(&startdate, tmpdate, sizeof (startdate)); 20817Sdinak copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate), 20917Sdinak &(rsa_pri_attrs[i++])); 21017Sdinak } 21117Sdinak 21217Sdinak cryptodebug("calling X509_get_notAfter"); 21317Sdinak if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) { 21417Sdinak (void) memcpy(&enddate, tmpdate, sizeof (enddate)); 21517Sdinak copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate), 21617Sdinak &(rsa_pri_attrs[i++])); 21717Sdinak } 21817Sdinak 21917Sdinak /* Modulus n */ 22017Sdinak cryptodebug("converting RSA private key modulus"); 22117Sdinak if ((rv = cvt_bn2bigint(rsa->n, &mod)) != CKR_OK) { 22217Sdinak cryptoerror(LOG_STDERR, gettext( 22317Sdinak "Unable to convert RSA private key modulus.")); 22417Sdinak return (rv); 22517Sdinak } 22617Sdinak copy_bigint_to_attr(mod, &(rsa_pri_attrs[i++])); 22717Sdinak 22817Sdinak /* Public exponent e */ 22917Sdinak cryptodebug("converting RSA private key public exponent"); 23017Sdinak if ((rv = cvt_bn2bigint(rsa->e, &pubexp)) != CKR_OK) { 23117Sdinak cryptoerror(LOG_STDERR, gettext( 23217Sdinak "Unable to convert RSA private key public exponent.")); 23317Sdinak return (rv); 23417Sdinak } 23517Sdinak copy_bigint_to_attr(pubexp, &(rsa_pri_attrs[i++])); 23617Sdinak 23717Sdinak /* Private exponent d */ 23817Sdinak if (rsa->d != NULL) { 23917Sdinak cryptodebug("converting RSA private key private exponent"); 24017Sdinak if ((rv = cvt_bn2bigint(rsa->d, &priexp)) != CKR_OK) { 24117Sdinak cryptoerror(LOG_STDERR, gettext("Unable to convert " 24217Sdinak "RSA private key private exponent.")); 24317Sdinak return (rv); 24417Sdinak } 24517Sdinak rsa_pri_attrs[i].type = CKA_PRIVATE_EXPONENT; 24617Sdinak copy_bigint_to_attr(priexp, &(rsa_pri_attrs[i++])); 24717Sdinak } else 24817Sdinak cryptodebug("no RSA private key private exponent"); 24917Sdinak 25017Sdinak /* Prime p */ 25117Sdinak if (rsa->p != NULL) { 25217Sdinak cryptodebug("converting RSA private key prime 1"); 25317Sdinak if ((rv = cvt_bn2bigint(rsa->p, &prime1)) != CKR_OK) { 25417Sdinak cryptoerror(LOG_STDERR, gettext( 25517Sdinak "Unable to convert RSA private key prime 1.")); 25617Sdinak return (rv); 25717Sdinak } 25817Sdinak rsa_pri_attrs[i].type = CKA_PRIME_1; 25917Sdinak copy_bigint_to_attr(prime1, &(rsa_pri_attrs[i++])); 26017Sdinak } else 26117Sdinak cryptodebug("no RSA private key prime 1"); 26217Sdinak 26317Sdinak /* Prime q */ 26417Sdinak if (rsa->q != NULL) { 26517Sdinak cryptodebug("converting RSA private key prime 2"); 26617Sdinak if ((rv = cvt_bn2bigint(rsa->q, &prime2)) != CKR_OK) { 26717Sdinak cryptoerror(LOG_STDERR, gettext( 26817Sdinak "Unable to convert RSA private key prime 2.")); 26917Sdinak return (rv); 27017Sdinak } 27117Sdinak rsa_pri_attrs[i].type = CKA_PRIME_2; 27217Sdinak copy_bigint_to_attr(prime2, &(rsa_pri_attrs[i++])); 27317Sdinak } else 27417Sdinak cryptodebug("no RSA private key prime 2"); 27517Sdinak 27617Sdinak /* Private exponent d modulo p-1 */ 27717Sdinak if (rsa->dmp1 != NULL) { 27817Sdinak cryptodebug("converting RSA private key exponent 1"); 27917Sdinak if ((rv = cvt_bn2bigint(rsa->dmp1, &exp1)) != CKR_OK) { 28017Sdinak cryptoerror(LOG_STDERR, gettext( 28117Sdinak "Unable to convert RSA private key exponent 1.")); 28217Sdinak return (rv); 28317Sdinak } 28417Sdinak rsa_pri_attrs[i].type = CKA_EXPONENT_1; 28517Sdinak copy_bigint_to_attr(exp1, &(rsa_pri_attrs[i++])); 28617Sdinak } else 28717Sdinak cryptodebug("no RSA private key exponent 1"); 28817Sdinak 28917Sdinak /* Private exponent d modulo q-1 */ 29017Sdinak if (rsa->dmq1 != NULL) { 29117Sdinak cryptodebug("converting RSA private key exponent 2"); 29217Sdinak if ((rv = cvt_bn2bigint(rsa->dmq1, &exp2)) != CKR_OK) { 29317Sdinak cryptoerror(LOG_STDERR, gettext( 29417Sdinak "Unable to convert RSA private key exponent 2.")); 29517Sdinak return (rv); 29617Sdinak } 29717Sdinak rsa_pri_attrs[i].type = CKA_EXPONENT_2; 29817Sdinak copy_bigint_to_attr(exp2, &(rsa_pri_attrs[i++])); 29917Sdinak } else 30017Sdinak cryptodebug("no RSA private key exponent 2"); 30117Sdinak 30217Sdinak /* CRT coefficient q-inverse mod p */ 30317Sdinak if (rsa->iqmp != NULL) { 30417Sdinak cryptodebug("converting RSA private key coefficient"); 30517Sdinak if ((rv = cvt_bn2bigint(rsa->iqmp, &coef)) != CKR_OK) { 30617Sdinak cryptoerror(LOG_STDERR, gettext( 30717Sdinak "Unable to convert RSA private key coefficient.")); 30817Sdinak return (rv); 30917Sdinak } 31017Sdinak rsa_pri_attrs[i].type = CKA_COEFFICIENT; 31117Sdinak copy_bigint_to_attr(coef, &(rsa_pri_attrs[i++])); 31217Sdinak } else 31317Sdinak cryptodebug("no RSA private key coefficient"); 31417Sdinak 31517Sdinak /* Indicates programming error: attributes overran the template */ 31617Sdinak if (i > count) { 31717Sdinak cryptodebug("error: more attributes found than accounted for"); 31817Sdinak i = count; 31917Sdinak } 32017Sdinak 32117Sdinak cryptodebug("calling C_CreateObject"); 32217Sdinak if ((rv = C_CreateObject(sess, rsa_pri_attrs, i, &obj)) != CKR_OK) { 32317Sdinak cryptoerror(LOG_STDERR, gettext( 32417Sdinak "Unable to create RSA private key object.")); 32517Sdinak return (rv); 32617Sdinak } 32717Sdinak 32817Sdinak return (CKR_OK); 32917Sdinak } 33017Sdinak 33117Sdinak /* 33217Sdinak * Write DSA private key to token. 33317Sdinak */ 33417Sdinak static CK_RV 33517Sdinak write_dsa_private(CK_SESSION_HANDLE sess, DSA *dsa, X509 *cert) 33617Sdinak { 33717Sdinak CK_RV rv = CKR_OK; 33817Sdinak int i = 0; 33917Sdinak static CK_OBJECT_CLASS objclass = CKO_PRIVATE_KEY; 34017Sdinak static CK_KEY_TYPE keytype = CKK_DSA; 34117Sdinak CK_BYTE *label = NULL; 34217Sdinak CK_ULONG label_len = 0; 34317Sdinak CK_BYTE *id = NULL; 34417Sdinak CK_ULONG id_len = 0; 34517Sdinak CK_DATE startdate = { "", "", "" }; 34617Sdinak CK_DATE enddate = { "", "", "" }; 34717Sdinak char tmpdate[8]; 34817Sdinak biginteger_t prime = { NULL, 0 }; /* required */ 34917Sdinak biginteger_t subprime = { NULL, 0 }; /* required */ 35017Sdinak biginteger_t base = { NULL, 0 }; /* required */ 35117Sdinak biginteger_t value = { NULL, 0 }; /* required */ 35217Sdinak CK_ATTRIBUTE dsa_pri_attrs[12] = { 35317Sdinak { CKA_CLASS, &objclass, sizeof (objclass) }, 35417Sdinak { CKA_KEY_TYPE, &keytype, sizeof (keytype) }, 35517Sdinak { CKA_PRIVATE, &pk_true, sizeof (pk_true) }, 35617Sdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 35717Sdinak { CKA_LABEL, NULL, 0 }, 35817Sdinak { CKA_ID, NULL, 0 }, 35917Sdinak { CKA_START_DATE, NULL, 0 }, 36017Sdinak { CKA_END_DATE, NULL, 0 }, 36117Sdinak { CKA_PRIME, NULL, 0 }, 36217Sdinak { CKA_SUBPRIME, NULL, 0 }, 36317Sdinak { CKA_BASE, NULL, 0 }, 36417Sdinak { CKA_VALUE, NULL, 0 } 36517Sdinak }; 36617Sdinak CK_ULONG count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE); 36717Sdinak CK_OBJECT_HANDLE obj; 36817Sdinak 36917Sdinak cryptodebug("inside write_dsa_private"); 37017Sdinak 37117Sdinak /* Attributes start at array index 4. */ 37217Sdinak i = 4; 37317Sdinak 37417Sdinak /* Recycle the certificate label for the private key label. */ 37517Sdinak cryptodebug("calling X509_alias_get0"); 37617Sdinak if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) { 37717Sdinak label = (CK_BYTE *)gettext("no label"); 37817Sdinak label_len = strlen((char *)label); 37917Sdinak } 38017Sdinak copy_string_to_attr(label, label_len, &(dsa_pri_attrs[i++])); 38117Sdinak 38217Sdinak /* Recycle the certificate id for the private key id. */ 38317Sdinak cryptodebug("calling PKTOOL_X509_keyid_get0"); 38417Sdinak if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) { 38517Sdinak id = (CK_BYTE *)gettext("no id"); 38617Sdinak id_len = strlen((char *)id); 38717Sdinak } 38817Sdinak copy_string_to_attr(id, id_len, &(dsa_pri_attrs[i++])); 38917Sdinak 39017Sdinak /* Recycle the certificate start and end dates for private key. */ 39117Sdinak cryptodebug("calling X509_get_notBefore"); 39217Sdinak if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) { 39317Sdinak (void) memcpy(&startdate, tmpdate, sizeof (startdate)); 39417Sdinak copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate), 39517Sdinak &(dsa_pri_attrs[i++])); 39617Sdinak } 39717Sdinak 39817Sdinak cryptodebug("calling X509_get_notAfter"); 39917Sdinak if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) { 40017Sdinak (void) memcpy(&enddate, tmpdate, sizeof (enddate)); 40117Sdinak copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate), 40217Sdinak &(dsa_pri_attrs[i++])); 40317Sdinak } 40417Sdinak 40517Sdinak /* Prime p */ 40617Sdinak cryptodebug("converting DSA private key prime"); 40717Sdinak if ((rv = cvt_bn2bigint(dsa->p, &prime)) != CKR_OK) { 40817Sdinak cryptoerror(LOG_STDERR, gettext( 40917Sdinak "Unable to convert DSA private key prime.")); 41017Sdinak return (rv); 41117Sdinak } 41217Sdinak copy_bigint_to_attr(prime, &(dsa_pri_attrs[i++])); 41317Sdinak 41417Sdinak /* Subprime q */ 41517Sdinak cryptodebug("converting DSA private key subprime"); 41617Sdinak if ((rv = cvt_bn2bigint(dsa->q, &subprime)) != CKR_OK) { 41717Sdinak cryptoerror(LOG_STDERR, gettext( 41817Sdinak "Unable to convert DSA private key subprime.")); 41917Sdinak return (rv); 42017Sdinak } 42117Sdinak copy_bigint_to_attr(subprime, &(dsa_pri_attrs[i++])); 42217Sdinak 42317Sdinak /* Base g */ 42417Sdinak cryptodebug("converting DSA private key base"); 42517Sdinak if ((rv = cvt_bn2bigint(dsa->g, &base)) != CKR_OK) { 42617Sdinak cryptoerror(LOG_STDERR, gettext( 42717Sdinak "Unable to convert DSA private key base.")); 42817Sdinak return (rv); 42917Sdinak } 43017Sdinak copy_bigint_to_attr(base, &(dsa_pri_attrs[i++])); 43117Sdinak 43217Sdinak /* Private key x */ 43317Sdinak cryptodebug("converting DSA private key value"); 43417Sdinak if ((rv = cvt_bn2bigint(dsa->priv_key, &value)) != CKR_OK) { 43517Sdinak cryptoerror(LOG_STDERR, gettext( 43617Sdinak "Unable to convert DSA private key value.")); 43717Sdinak return (rv); 43817Sdinak } 43917Sdinak copy_bigint_to_attr(value, &(dsa_pri_attrs[i++])); 44017Sdinak 44117Sdinak /* Indicates programming error: attributes overran the template */ 44217Sdinak if (i > count) { 44317Sdinak cryptodebug("error: more attributes found than accounted for"); 44417Sdinak i = count; 44517Sdinak } 44617Sdinak 44717Sdinak cryptodebug("calling C_CreateObject"); 44817Sdinak if ((rv = C_CreateObject(sess, dsa_pri_attrs, i, &obj)) != CKR_OK) { 44917Sdinak cryptoerror(LOG_STDERR, gettext( 45017Sdinak "Unable to create DSA private key object.")); 45117Sdinak return (rv); 45217Sdinak } 45317Sdinak 45417Sdinak return (CKR_OK); 45517Sdinak } 45617Sdinak 45717Sdinak /* 45817Sdinak * Write DH private key to token. 45917Sdinak */ 46017Sdinak static CK_RV 46117Sdinak write_dh_private(CK_SESSION_HANDLE sess, DH *dh, X509 *cert) 46217Sdinak { 46317Sdinak CK_RV rv = CKR_OK; 46417Sdinak int i = 0; 46517Sdinak static CK_OBJECT_CLASS objclass = CKO_PRIVATE_KEY; 46617Sdinak static CK_KEY_TYPE keytype = CKK_DH; 46717Sdinak CK_BYTE *label = NULL; 46817Sdinak CK_ULONG label_len = 0; 46917Sdinak CK_BYTE *id = NULL; 47017Sdinak CK_ULONG id_len = 0; 47117Sdinak CK_DATE startdate = { "", "", "" }; 47217Sdinak CK_DATE enddate = { "", "", "" }; 47317Sdinak char tmpdate[8]; 47417Sdinak biginteger_t prime = { NULL, 0 }; /* required */ 47517Sdinak biginteger_t base = { NULL, 0 }; /* required */ 47617Sdinak biginteger_t value = { NULL, 0 }; /* required */ 47717Sdinak CK_ATTRIBUTE dh_pri_attrs[11] = { 47817Sdinak { CKA_CLASS, &objclass, sizeof (objclass) }, 47917Sdinak { CKA_KEY_TYPE, &keytype, sizeof (keytype) }, 48017Sdinak { CKA_PRIVATE, &pk_true, sizeof (pk_true) }, 48117Sdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 48217Sdinak { CKA_LABEL, NULL, 0 }, 48317Sdinak { CKA_ID, NULL, 0 }, 48417Sdinak { CKA_START_DATE, NULL, 0 }, 48517Sdinak { CKA_END_DATE, NULL, 0 }, 48617Sdinak { CKA_PRIME, NULL, 0 }, 48717Sdinak { CKA_BASE, NULL, 0 }, 48817Sdinak { CKA_VALUE, NULL, 0 } 48917Sdinak }; 49017Sdinak CK_ULONG count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE); 49117Sdinak CK_OBJECT_HANDLE obj; 49217Sdinak 49317Sdinak cryptodebug("inside write_dh_private"); 49417Sdinak 49517Sdinak /* Attributes start at array index 4. */ 49617Sdinak i = 4; 49717Sdinak 49817Sdinak /* Recycle the certificate label for the private key label. */ 49917Sdinak cryptodebug("calling X509_alias_get0"); 50017Sdinak if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) { 50117Sdinak label = (CK_BYTE *)gettext("no label"); 50217Sdinak label_len = strlen((char *)label); 50317Sdinak } 50417Sdinak copy_string_to_attr(label, label_len, &(dh_pri_attrs[i++])); 50517Sdinak 50617Sdinak /* Recycle the certificate id for the private key id. */ 50717Sdinak cryptodebug("PKTOOL_X509_keyid_get0"); 50817Sdinak if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) { 50917Sdinak id = (CK_BYTE *)gettext("no id"); 51017Sdinak id_len = strlen((char *)id); 51117Sdinak } 51217Sdinak copy_string_to_attr(id, id_len, &(dh_pri_attrs[i++])); 51317Sdinak 51417Sdinak /* Recycle the certificate start and end dates for private key. */ 51517Sdinak cryptodebug("calling X509_get_notBefore"); 51617Sdinak if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) { 51717Sdinak (void) memcpy(&startdate, tmpdate, sizeof (startdate)); 51817Sdinak copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate), 51917Sdinak &(dh_pri_attrs[i++])); 52017Sdinak } 52117Sdinak 52217Sdinak cryptodebug("calling X509_get_notAfter"); 52317Sdinak if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) { 52417Sdinak (void) memcpy(&enddate, tmpdate, sizeof (enddate)); 52517Sdinak copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate), 52617Sdinak &(dh_pri_attrs[i++])); 52717Sdinak } 52817Sdinak 52917Sdinak /* Prime p */ 53017Sdinak cryptodebug("converting DH private key prime"); 53117Sdinak if ((rv = cvt_bn2bigint(dh->p, &prime)) != CKR_OK) { 53217Sdinak cryptoerror(LOG_STDERR, gettext( 53317Sdinak "Unable to convert DH private key prime.")); 53417Sdinak return (rv); 53517Sdinak } 53617Sdinak copy_bigint_to_attr(prime, &(dh_pri_attrs[i++])); 53717Sdinak 53817Sdinak /* Base g */ 53917Sdinak cryptodebug("converting DH private key base"); 54017Sdinak if ((rv = cvt_bn2bigint(dh->g, &base)) != CKR_OK) { 54117Sdinak cryptoerror(LOG_STDERR, gettext( 54217Sdinak "Unable to convert DH private key base.")); 54317Sdinak return (rv); 54417Sdinak } 54517Sdinak copy_bigint_to_attr(base, &(dh_pri_attrs[i++])); 54617Sdinak 54717Sdinak /* Private value x */ 54817Sdinak cryptodebug("converting DH private key value"); 54917Sdinak if ((rv = cvt_bn2bigint(dh->priv_key, &value)) != CKR_OK) { 55017Sdinak cryptoerror(LOG_STDERR, gettext( 55117Sdinak "Unable to convert DH private key value.")); 55217Sdinak return (rv); 55317Sdinak } 55417Sdinak copy_bigint_to_attr(value, &(dh_pri_attrs[i++])); 55517Sdinak 55617Sdinak /* Indicates programming error: attributes overran the template */ 55717Sdinak if (i > count) { 55817Sdinak cryptodebug("error: more attributes found than accounted for"); 55917Sdinak i = count; 56017Sdinak } 56117Sdinak 56217Sdinak cryptodebug("calling C_CreateObject"); 56317Sdinak if ((rv = C_CreateObject(sess, dh_pri_attrs, i, &obj)) != CKR_OK) { 56417Sdinak cryptoerror(LOG_STDERR, gettext( 56517Sdinak "Unable to create DH private key object.")); 56617Sdinak return (rv); 56717Sdinak } 56817Sdinak 56917Sdinak return (CKR_OK); 57017Sdinak } 57117Sdinak 57217Sdinak /* 57317Sdinak * Write certificate to token. 57417Sdinak */ 57517Sdinak static CK_RV 57617Sdinak write_cert(CK_SESSION_HANDLE sess, X509 *cert) 57717Sdinak { 57817Sdinak CK_RV rv = CKR_OK; 57917Sdinak int i = 0; 58017Sdinak static CK_OBJECT_CLASS objclass = CKO_CERTIFICATE; 58117Sdinak static CK_CERTIFICATE_TYPE certtype = CKC_X_509; 58217Sdinak CK_BYTE *subject = NULL; 58317Sdinak CK_ULONG subject_len = 0; 58417Sdinak CK_BYTE *value = NULL; 58517Sdinak CK_ULONG value_len = 0; 58617Sdinak CK_BYTE *label = NULL; 58717Sdinak CK_ULONG label_len = 0; 58817Sdinak CK_BYTE *id = NULL; 58917Sdinak CK_ULONG id_len = 0; 59017Sdinak CK_BYTE *issuer = NULL; 59117Sdinak CK_ULONG issuer_len = 0; 59217Sdinak CK_BYTE *serial = NULL; 59317Sdinak CK_ULONG serial_len = 0; 59417Sdinak CK_ATTRIBUTE cert_attrs[9] = { 59517Sdinak { CKA_CLASS, &objclass, sizeof (objclass) }, 59617Sdinak { CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) }, 59717Sdinak { CKA_TOKEN, &pk_true, sizeof (pk_true) }, 59817Sdinak { CKA_SUBJECT, NULL, 0 }, /* required */ 59917Sdinak { CKA_VALUE, NULL, 0 }, /* required */ 60017Sdinak { 0 /* CKA_LABEL */, NULL, 0 }, /* optional */ 60117Sdinak { 0 /* CKA_ID */, NULL, 0 }, /* optional */ 60217Sdinak { 0 /* CKA_ISSUER */, NULL, 0 }, /* optional */ 60317Sdinak { 0 /* CKA_SERIAL_NUMBER */, NULL, 0 } /* optional */ 60417Sdinak }; 60517Sdinak CK_ULONG count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE); 60617Sdinak CK_OBJECT_HANDLE obj; 60717Sdinak 60817Sdinak cryptodebug("inside write_cert"); 60917Sdinak 61017Sdinak /* Attributes start at array index 3. */ 61117Sdinak i = 3; 61217Sdinak 61317Sdinak /* 61417Sdinak * OpenSSL subject name and issuer (a little further below) are 61517Sdinak * actually stack structures that contain individual ASN.1 61617Sdinak * components. This stack of entries is packed into one DER string. 61717Sdinak */ 61817Sdinak cryptodebug("calling PKTOOL_X509_subject_name"); 61917Sdinak if ((subject = PKTOOL_X509_subject_name(cert, (int *)&subject_len)) == 62017Sdinak NULL) { 62117Sdinak subject = (CK_BYTE *)gettext("no subject name"); 62217Sdinak subject_len = strlen((char *)subject); 62317Sdinak } 62417Sdinak copy_string_to_attr(subject, subject_len, &(cert_attrs[i++])); 62517Sdinak 62617Sdinak /* Get cert value, but it has to be reconstructed from cert. */ 62717Sdinak cryptodebug("calling PKTOOL_X509_cert_value"); 62817Sdinak if ((value = PKTOOL_X509_cert_value(cert, (int *)&value_len)) == NULL) { 62917Sdinak value = (CK_BYTE *)gettext("no value"); 63017Sdinak value_len = strlen((char *)value); 63117Sdinak } 63217Sdinak copy_string_to_attr(value, value_len, &(cert_attrs[i++])); 63317Sdinak 63417Sdinak /* 63517Sdinak * Get certificate label which is "friendlyName" Netscape, 63617Sdinak * "alias" in OpenSSL. 63717Sdinak */ 63817Sdinak if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) { 63917Sdinak cryptodebug("no certificate label"); 64017Sdinak } else { 64117Sdinak cert_attrs[i].type = CKA_LABEL; 64217Sdinak copy_string_to_attr(label, label_len, &(cert_attrs[i++])); 64317Sdinak } 64417Sdinak 64517Sdinak /* Get the keyid for the cert. */ 64617Sdinak if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) { 64717Sdinak cryptodebug("no certificate id"); 64817Sdinak } else { 64917Sdinak cert_attrs[i].type = CKA_ID; 65017Sdinak copy_string_to_attr(id, id_len, &(cert_attrs[i++])); 65117Sdinak } 65217Sdinak 65317Sdinak /* Get the issuer name for the cert. */ 65417Sdinak if ((issuer = PKTOOL_X509_issuer_name(cert, (int *)&issuer_len)) == 65517Sdinak NULL) { 65617Sdinak cryptodebug("no certificate issuer name"); 65717Sdinak } else { 65817Sdinak cert_attrs[i].type = CKA_ISSUER; 65917Sdinak copy_string_to_attr(issuer, issuer_len, &(cert_attrs[i++])); 66017Sdinak } 66117Sdinak 66217Sdinak /* Get the cert serial number. */ 66317Sdinak if ((serial = PKTOOL_X509_serial_number(cert, (int *)&serial_len)) == 66417Sdinak NULL) { 66517Sdinak cryptodebug("no certificate serial number"); 66617Sdinak } else { 66717Sdinak cert_attrs[i].type = CKA_SERIAL_NUMBER; 66817Sdinak copy_string_to_attr(serial, serial_len, &(cert_attrs[i++])); 66917Sdinak } 67017Sdinak 67117Sdinak /* Indicates programming error: attributes overran the template */ 67217Sdinak if (i > count) { 67317Sdinak cryptodebug("error: more attributes found than accounted for"); 67417Sdinak i = count; 67517Sdinak } 67617Sdinak 67717Sdinak cryptodebug("calling C_CreateObject"); 67817Sdinak if ((rv = C_CreateObject(sess, cert_attrs, i, &obj)) != CKR_OK) { 67917Sdinak cryptoerror(LOG_STDERR, gettext( 68017Sdinak "Unable to create X.509 certificate object.")); 68117Sdinak return (rv); 68217Sdinak } 68317Sdinak 68417Sdinak return (CKR_OK); 68517Sdinak } 68617Sdinak 68717Sdinak /* 68817Sdinak * Helper function to write PKCS#12 items to token. Returns CKR_OK 68917Sdinak * or CKR_GENERAL_ERROR 69017Sdinak */ 69117Sdinak static CK_RV 69217Sdinak write_token_objs(CK_SESSION_HANDLE sess, EVP_PKEY *priv_key, X509 *cert, 69317Sdinak STACK_OF(X509) *ca, int *successes, int *failures) 69417Sdinak { 69517Sdinak int i; 69617Sdinak X509 *c; 69717Sdinak CK_RV rv = CKR_OK; 69817Sdinak 69917Sdinak cryptodebug("inside write_token_objs"); 70017Sdinak 70117Sdinak /* Do not reset *successes or *failures -- keep running totals. */ 70217Sdinak 70317Sdinak /* Import user key. */ 70417Sdinak switch (priv_key->type) { 70517Sdinak case EVP_PKEY_RSA: 70617Sdinak (void) fprintf(stdout, gettext("Writing RSA private key...\n")); 70717Sdinak if ((rv = write_rsa_private(sess, 70817Sdinak EVP_PKEY_get1_RSA(priv_key), cert)) != CKR_OK) { 70917Sdinak cryptoerror(LOG_STDERR, gettext( 71017Sdinak "Unable to write RSA private key (%s)."), 71117Sdinak pkcs11_strerror(rv)); 71217Sdinak (*failures)++; 71317Sdinak } else 71417Sdinak (*successes)++; 71517Sdinak break; 71617Sdinak case EVP_PKEY_DSA: 71717Sdinak (void) fprintf(stdout, gettext("Writing DSA private key...\n")); 71817Sdinak if ((rv = write_dsa_private(sess, 71917Sdinak EVP_PKEY_get1_DSA(priv_key), cert)) != CKR_OK) { 72017Sdinak cryptoerror(LOG_STDERR, gettext( 72117Sdinak "Unable to write DSA private key (%s)."), 72217Sdinak pkcs11_strerror(rv)); 72317Sdinak (*failures)++; 72417Sdinak } else 72517Sdinak (*successes)++; 72617Sdinak break; 72717Sdinak case EVP_PKEY_DH: 72817Sdinak (void) fprintf(stdout, gettext("Writing DH private key...\n")); 72917Sdinak if ((rv = write_dh_private(sess, 73017Sdinak EVP_PKEY_get1_DH(priv_key), cert)) != CKR_OK) { 73117Sdinak cryptoerror(LOG_STDERR, gettext( 73217Sdinak "Unable to write DH private key (%s)."), 73317Sdinak pkcs11_strerror(rv)); 73417Sdinak (*failures)++; 73517Sdinak } else 73617Sdinak (*successes)++; 73717Sdinak break; 73817Sdinak 73917Sdinak default: 74017Sdinak /* 74117Sdinak * Note that EVP_PKEY_DH for X9.42 is not implemented 74217Sdinak * in the OpenSSL library. 74317Sdinak */ 74417Sdinak cryptoerror(LOG_STDERR, gettext( 74517Sdinak "Private key type 0x%02x import not supported."), 74617Sdinak priv_key->type); 74717Sdinak (*failures)++; 74817Sdinak break; 74917Sdinak } 75017Sdinak 75117Sdinak /* Import user certificate. */ 75217Sdinak (void) fprintf(stdout, gettext("Writing user certificate...\n")); 75317Sdinak if ((rv = write_cert(sess, cert)) != CKR_OK) { 75417Sdinak cryptoerror(LOG_STDERR, gettext( 75517Sdinak "Unable to write user certificate (%s)."), 75617Sdinak pkcs11_strerror(rv)); 75717Sdinak (*failures)++; 75817Sdinak } else 75917Sdinak (*successes)++; 76017Sdinak 76117Sdinak /* Import as many stacks of authority certificates as possible. */ 76217Sdinak for (i = 0; i != sk_X509_num(ca); i++) { 76317Sdinak /* 76417Sdinak * sk_X509_value() is macro that embeds a cast to (X509 *). 76517Sdinak * Here it translates into ((X509 *)sk_value((ca), (i))). 76617Sdinak * Lint is complaining about the embedded casting, and 76717Sdinak * to fix it, you need to fix openssl header files. 76817Sdinak */ 76917Sdinak /* LINTED E_BAD_PTR_CAST_ALIGN */ 77017Sdinak c = sk_X509_value(ca, i); 77117Sdinak (void) fprintf(stdout, gettext( 77217Sdinak "Writing authority certificate...\n")); 77317Sdinak if ((rv = write_cert(sess, c)) != CKR_OK) { 77417Sdinak cryptoerror(LOG_STDERR, gettext( 77517Sdinak "Unable to write authority certificate (%s)."), 77617Sdinak pkcs11_strerror(rv)); 77717Sdinak (*failures)++; 77817Sdinak } else 77917Sdinak (*successes)++; 78017Sdinak } 78117Sdinak 78217Sdinak (void) fprintf(stdout, gettext("PKCS#12 element scan completed.\n")); 78317Sdinak return (*failures != 0 ? CKR_GENERAL_ERROR : CKR_OK); 78417Sdinak } 78517Sdinak 78617Sdinak /* 78717Sdinak * Import objects from PKCS#12 file into token. 78817Sdinak */ 78917Sdinak int 79017Sdinak pk_import(int argc, char *argv[]) 79117Sdinak { 792*864Sdinak int opt; 793*864Sdinak extern int optind_av; 794*864Sdinak extern char *optarg_av; 795*864Sdinak char *token_spec = NULL; 79617Sdinak char *token_name = NULL; 79717Sdinak char *manuf_id = NULL; 79817Sdinak char *serial_no = NULL; 79917Sdinak char full_name[FULL_NAME_LEN]; 80017Sdinak char *filename = NULL; 80117Sdinak struct stat statbuf; 80217Sdinak CK_SLOT_ID slot_id; 80317Sdinak CK_FLAGS pin_state; 80417Sdinak CK_UTF8CHAR_PTR pin = NULL; 80517Sdinak CK_ULONG pinlen = 0; 80617Sdinak CK_UTF8CHAR_PTR pk12pin = NULL; 80717Sdinak CK_ULONG pk12pinlen = 0; 80817Sdinak CK_SESSION_HANDLE sess; 80917Sdinak BIO *fbio = NULL; 81017Sdinak EVP_PKEY *priv_key = NULL; 81117Sdinak X509 *cert = NULL; 81217Sdinak STACK_OF(X509) *ca = NULL; 81317Sdinak CK_RV rv = CKR_OK; 81417Sdinak int i; 81517Sdinak int good_count = 0, bad_count = 0; /* running totals */ 81617Sdinak 81717Sdinak cryptodebug("inside pk_import"); 81817Sdinak 819*864Sdinak /* Parse command line options. Do NOT i18n/l10n. */ 820*864Sdinak while ((opt = getopt_av(argc, argv, "T:(token)i:(infile)")) != EOF) { 821*864Sdinak switch (opt) { 822*864Sdinak case 'T': /* token specifier */ 823*864Sdinak if (token_spec) 824*864Sdinak return (PK_ERR_USAGE); 825*864Sdinak token_spec = optarg_av; 826*864Sdinak break; 827*864Sdinak case 'i': /* input file name */ 828*864Sdinak if (filename) 829*864Sdinak return (PK_ERR_USAGE); 830*864Sdinak filename = optarg_av; 831*864Sdinak break; 832*864Sdinak default: 833*864Sdinak return (PK_ERR_USAGE); 834*864Sdinak break; 835*864Sdinak } 836*864Sdinak } 83717Sdinak 838*864Sdinak /* If nothing is specified, default is to use softtoken. */ 839*864Sdinak if (token_spec == NULL) { 840*864Sdinak token_name = SOFT_TOKEN_LABEL; 841*864Sdinak manuf_id = SOFT_MANUFACTURER_ID; 842*864Sdinak serial_no = SOFT_TOKEN_SERIAL; 843*864Sdinak } else { 844*864Sdinak /* 845*864Sdinak * Parse token specifier into token_name, manuf_id, serial_no. 846*864Sdinak * Token_name is required; manuf_id and serial_no are optional. 847*864Sdinak */ 848*864Sdinak if (parse_token_spec(token_spec, &token_name, &manuf_id, 849*864Sdinak &serial_no) < 0) 850*864Sdinak return (PK_ERR_USAGE); 851*864Sdinak } 852*864Sdinak 853*864Sdinak /* Filename arg is required. */ 854*864Sdinak if (filename == NULL) 85517Sdinak return (PK_ERR_USAGE); 85617Sdinak 857*864Sdinak /* No additional args allowed. */ 858*864Sdinak argc -= optind_av; 859*864Sdinak argv += optind_av; 860*864Sdinak if (argc) 861*864Sdinak return (PK_ERR_USAGE); 86217Sdinak /* Done parsing command line options. */ 86317Sdinak 86417Sdinak /* Check that the file exists and is non-empty. */ 86517Sdinak if (access(filename, R_OK) < 0) { 86617Sdinak cryptoerror(LOG_STDERR, gettext("File \"%s\" is unreadable " 86717Sdinak "(%s)."), filename, strerror(errno)); 86817Sdinak return (CKR_OK); 86917Sdinak } 87017Sdinak if (stat(filename, &statbuf) < 0) { 87117Sdinak cryptoerror(LOG_STDERR, gettext("Unable to get size of " 87217Sdinak "file \"%s\" (%s)."), filename, strerror(errno)); 87317Sdinak return (CKR_OK); 87417Sdinak } 87517Sdinak if (statbuf.st_size == 0) { 87617Sdinak cryptoerror(LOG_STDERR, gettext("File \"%s\" is empty."), 87717Sdinak filename); 87817Sdinak return (CKR_OK); 87917Sdinak } 88017Sdinak 88117Sdinak full_token_name(token_name, manuf_id, serial_no, full_name); 88217Sdinak 88317Sdinak /* Find the slot with token. */ 88417Sdinak if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id, 88517Sdinak &pin_state)) != CKR_OK) { 88617Sdinak cryptoerror(LOG_STDERR, gettext( 88717Sdinak "Unable to find token %s (%s)."), full_name, 88817Sdinak pkcs11_strerror(rv)); 88917Sdinak return (PK_ERR_PK11); 89017Sdinak } 89117Sdinak 89217Sdinak /* Get the user's PIN. */ 89317Sdinak if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin, 89417Sdinak &pinlen)) != CKR_OK) { 89517Sdinak cryptoerror(LOG_STDERR, gettext( 89617Sdinak "Unable to get token passphrase (%s)."), 89717Sdinak pkcs11_strerror(rv)); 89817Sdinak quick_finish(NULL); 89917Sdinak return (PK_ERR_PK11); 90017Sdinak } 90117Sdinak 90217Sdinak /* Assume user must be logged in R/W to import objects into token. */ 90317Sdinak if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) != 90417Sdinak CKR_OK) { 90517Sdinak cryptoerror(LOG_STDERR, 90617Sdinak gettext("Unable to log into token (%s)."), 90717Sdinak pkcs11_strerror(rv)); 90817Sdinak quick_finish(sess); 90917Sdinak return (PK_ERR_PK11); 91017Sdinak } 91117Sdinak 91217Sdinak /* Setup OpenSSL context. */ 91317Sdinak PKTOOL_setup_openssl(); 91417Sdinak 91517Sdinak /* Open PKCS#12 file. */ 91617Sdinak if ((open_pkcs12(filename, &fbio)) < 0) { 91717Sdinak cryptoerror(LOG_STDERR, gettext("Unable to open import file.")); 91817Sdinak quick_finish(sess); 91917Sdinak return (PK_ERR_SYSTEM); 92017Sdinak } 92117Sdinak 92217Sdinak /* Get the PIN for the PKCS#12 import file. */ 92317Sdinak if ((rv = get_pin(gettext("Enter import file passphrase:"), NULL, 92417Sdinak &pk12pin, &pk12pinlen)) != CKR_OK) { 92517Sdinak cryptoerror(LOG_STDERR, gettext( 92617Sdinak "Unable to get import file passphrase (%s)."), 92717Sdinak pkcs11_strerror(rv)); 92817Sdinak close_pkcs12(fbio); 92917Sdinak quick_finish(sess); 93017Sdinak return (PK_ERR_PK11); 93117Sdinak } 93217Sdinak 93317Sdinak /* PKCS#12 import file may have multiple elements, loop until done. */ 93417Sdinak for (i = 0; /* */; i++) { 93517Sdinak /* Extract the contents of the PKCS#12 import file. */ 93617Sdinak if ((rv = extract_pkcs12(fbio, pk12pin, pk12pinlen, &priv_key, 93717Sdinak &cert, &ca)) != CKR_OK) { 93817Sdinak cryptoerror(LOG_STDERR, gettext( 93917Sdinak "Unable to parse PKCS#12 element #%d " 94017Sdinak "in import file (%s)."), i+1, pkcs11_strerror(rv)); 94117Sdinak close_pkcs12(fbio); 94217Sdinak quick_finish(sess); 94317Sdinak return (PK_ERR_OPENSSL); 94417Sdinak } 94517Sdinak 94617Sdinak /* Reached end of import file? */ 94717Sdinak if (rv == CKR_OK && priv_key == NULL && cert == NULL && 94817Sdinak ca == NULL) 94917Sdinak break; 95017Sdinak 95117Sdinak (void) fprintf(stdout, gettext( 95217Sdinak "Scanning PKCS#12 element #%d for objects...\n"), i+1); 95317Sdinak 95417Sdinak /* Write the objects to the token. */ 95517Sdinak if ((rv = write_token_objs(sess, priv_key, cert, ca, 95617Sdinak &good_count, &bad_count)) != CKR_OK) { 95717Sdinak cryptoerror(LOG_STDERR, gettext( 95817Sdinak "Unable to write PKCS#12 element #%d to token %s."), 95917Sdinak i+1, full_name); 96017Sdinak close_pkcs12(fbio); 96117Sdinak quick_finish(sess); 96217Sdinak return (PK_ERR_PK11); 96317Sdinak } 96417Sdinak } 96517Sdinak 96617Sdinak (void) fprintf(stdout, gettext("%d PKCS#12 elements scanned: " 96717Sdinak "%d objects imported, %d errors occurred.\n"), i, 96817Sdinak good_count, bad_count); 96917Sdinak 97017Sdinak /* Close PKCS#12 file. */ 97117Sdinak close_pkcs12(fbio); 97217Sdinak 97317Sdinak /* Clean up. */ 97417Sdinak quick_finish(sess); 97517Sdinak return (0); 97617Sdinak } 977