import.c revision 49e212991a3065f7e499a4b29ae8d8eaf33f3135
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* This file implements the import operation for this tool.
* The basic flow of the process is to decrypt the PKCS#12
* input file if it has a password, parse the elements in
* the file, find the soft token, log into it, import the
* PKCS#11 objects into the soft token, and log out.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <cryptoutil.h>
#include <security/cryptoki.h>
#include "common.h"
#include "biginteger.h"
#include "osslcommon.h"
#include "p12common.h"
/*
* Helper function decrypt and parse PKCS#12 import file.
*/
static CK_RV
/* ARGSUSED */
{
cryptodebug("inside extract_pkcs12");
cryptodebug("calling PKCS12_new");
"Unable to create PKCS#12 context."));
return (CKR_GENERAL_ERROR);
}
cryptodebug("calling d2i_PKCS12_bio");
/* This is ok; it seems to mean there is no more to read. */
goto end_extract_pkcs12;
"Unable to populate PKCS#12 context."));
return (CKR_GENERAL_ERROR);
}
cryptodebug("calling PKCS12_parse");
&temp_ca) <= 0) {
gettext("Unable to parse import file."));
return (CKR_GENERAL_ERROR);
}
return (CKR_OK);
}
/*
* Converts OpenSSL BIGNUM into PKCS#11 biginteger_t format.
*/
static CK_RV
{
cryptodebug("inside cvt_bn2bigint");
return (CKR_ARGUMENTS_BAD);
cryptodebug("calling BN_num_bytes");
return (CKR_HOST_MEMORY);
cryptodebug("calling BN_bn2bin");
if (temp_cvt_sz != temp_alloc_sz)
return (CKR_GENERAL_ERROR);
return (CKR_OK);
}
/*
* Write RSA private key to token.
*/
static CK_RV
{
int i = 0;
char tmpdate[8];
{ CKA_START_DATE, NULL, 0 },
{ CKA_END_DATE, NULL, 0 },
{ CKA_MODULUS, NULL, 0 },
{ CKA_PUBLIC_EXPONENT, NULL, 0 },
};
cryptodebug("inside write_rsa_private");
/* Attributes start at array index 4. */
i = 4;
/* Recycle the certificate label for the private key label. */
cryptodebug("calling X509_alias_get0");
}
/* Recycle the certificate id for the private key id. */
cryptodebug("calling PKTOOL_X509_keyid_get0");
}
/* Recycle the certificate start and end dates for private key. */
cryptodebug("calling X509_get_notBefore");
&(rsa_pri_attrs[i++]));
}
cryptodebug("calling X509_get_notAfter");
&(rsa_pri_attrs[i++]));
}
/* Modulus n */
cryptodebug("converting RSA private key modulus");
"Unable to convert RSA private key modulus."));
return (rv);
}
/* Public exponent e */
cryptodebug("converting RSA private key public exponent");
"Unable to convert RSA private key public exponent."));
return (rv);
}
/* Private exponent d */
cryptodebug("converting RSA private key private exponent");
"RSA private key private exponent."));
return (rv);
}
} else
cryptodebug("no RSA private key private exponent");
/* Prime p */
cryptodebug("converting RSA private key prime 1");
"Unable to convert RSA private key prime 1."));
return (rv);
}
} else
cryptodebug("no RSA private key prime 1");
/* Prime q */
cryptodebug("converting RSA private key prime 2");
"Unable to convert RSA private key prime 2."));
return (rv);
}
} else
cryptodebug("no RSA private key prime 2");
/* Private exponent d modulo p-1 */
cryptodebug("converting RSA private key exponent 1");
"Unable to convert RSA private key exponent 1."));
return (rv);
}
} else
cryptodebug("no RSA private key exponent 1");
/* Private exponent d modulo q-1 */
cryptodebug("converting RSA private key exponent 2");
"Unable to convert RSA private key exponent 2."));
return (rv);
}
} else
cryptodebug("no RSA private key exponent 2");
/* CRT coefficient q-inverse mod p */
cryptodebug("converting RSA private key coefficient");
"Unable to convert RSA private key coefficient."));
return (rv);
}
} else
cryptodebug("no RSA private key coefficient");
/* Indicates programming error: attributes overran the template */
if (i > count) {
cryptodebug("error: more attributes found than accounted for");
i = count;
}
cryptodebug("calling C_CreateObject");
"Unable to create RSA private key object."));
return (rv);
}
return (CKR_OK);
}
/*
* Write DSA private key to token.
*/
static CK_RV
{
int i = 0;
char tmpdate[8];
{ CKA_START_DATE, NULL, 0 },
{ CKA_END_DATE, NULL, 0 },
{ CKA_SUBPRIME, NULL, 0 },
};
cryptodebug("inside write_dsa_private");
/* Attributes start at array index 4. */
i = 4;
/* Recycle the certificate label for the private key label. */
cryptodebug("calling X509_alias_get0");
}
/* Recycle the certificate id for the private key id. */
cryptodebug("calling PKTOOL_X509_keyid_get0");
}
/* Recycle the certificate start and end dates for private key. */
cryptodebug("calling X509_get_notBefore");
&(dsa_pri_attrs[i++]));
}
cryptodebug("calling X509_get_notAfter");
&(dsa_pri_attrs[i++]));
}
/* Prime p */
cryptodebug("converting DSA private key prime");
"Unable to convert DSA private key prime."));
return (rv);
}
/* Subprime q */
cryptodebug("converting DSA private key subprime");
"Unable to convert DSA private key subprime."));
return (rv);
}
/* Base g */
cryptodebug("converting DSA private key base");
"Unable to convert DSA private key base."));
return (rv);
}
/* Private key x */
cryptodebug("converting DSA private key value");
"Unable to convert DSA private key value."));
return (rv);
}
/* Indicates programming error: attributes overran the template */
if (i > count) {
cryptodebug("error: more attributes found than accounted for");
i = count;
}
cryptodebug("calling C_CreateObject");
"Unable to create DSA private key object."));
return (rv);
}
return (CKR_OK);
}
/*
* Write DH private key to token.
*/
static CK_RV
{
int i = 0;
char tmpdate[8];
{ CKA_START_DATE, NULL, 0 },
{ CKA_END_DATE, NULL, 0 },
};
cryptodebug("inside write_dh_private");
/* Attributes start at array index 4. */
i = 4;
/* Recycle the certificate label for the private key label. */
cryptodebug("calling X509_alias_get0");
}
/* Recycle the certificate id for the private key id. */
cryptodebug("PKTOOL_X509_keyid_get0");
}
/* Recycle the certificate start and end dates for private key. */
cryptodebug("calling X509_get_notBefore");
&(dh_pri_attrs[i++]));
}
cryptodebug("calling X509_get_notAfter");
&(dh_pri_attrs[i++]));
}
/* Prime p */
cryptodebug("converting DH private key prime");
"Unable to convert DH private key prime."));
return (rv);
}
/* Base g */
cryptodebug("converting DH private key base");
"Unable to convert DH private key base."));
return (rv);
}
/* Private value x */
cryptodebug("converting DH private key value");
"Unable to convert DH private key value."));
return (rv);
}
/* Indicates programming error: attributes overran the template */
if (i > count) {
cryptodebug("error: more attributes found than accounted for");
i = count;
}
cryptodebug("calling C_CreateObject");
"Unable to create DH private key object."));
return (rv);
}
return (CKR_OK);
}
/*
* Write certificate to token.
*/
static CK_RV
{
int i = 0;
CK_ULONG subject_len = 0;
CK_ULONG issuer_len = 0;
CK_ULONG serial_len = 0;
};
cryptodebug("inside write_cert");
/* Attributes start at array index 3. */
i = 3;
/*
* OpenSSL subject name and issuer (a little further below) are
* actually stack structures that contain individual ASN.1
* components. This stack of entries is packed into one DER string.
*/
cryptodebug("calling PKTOOL_X509_subject_name");
NULL) {
}
/* Get cert value, but it has to be reconstructed from cert. */
cryptodebug("calling PKTOOL_X509_cert_value");
}
/*
* Get certificate label which is "friendlyName" Netscape,
* "alias" in OpenSSL.
*/
cryptodebug("no certificate label");
} else {
}
/* Get the keyid for the cert. */
cryptodebug("no certificate id");
} else {
}
/* Get the issuer name for the cert. */
NULL) {
cryptodebug("no certificate issuer name");
} else {
}
/* Get the cert serial number. */
NULL) {
cryptodebug("no certificate serial number");
} else {
}
/* Indicates programming error: attributes overran the template */
if (i > count) {
cryptodebug("error: more attributes found than accounted for");
i = count;
}
cryptodebug("calling C_CreateObject");
"Unable to create X.509 certificate object."));
return (rv);
}
return (CKR_OK);
}
/*
* Helper function to write PKCS#12 items to token. Returns CKR_OK
* or CKR_GENERAL_ERROR
*/
static CK_RV
{
int i;
X509 *c;
cryptodebug("inside write_token_objs");
/* Do not reset *successes or *failures -- keep running totals. */
/* Import user key. */
case EVP_PKEY_RSA:
"Unable to write RSA private key (%s)."),
(*failures)++;
} else
(*successes)++;
break;
case EVP_PKEY_DSA:
"Unable to write DSA private key (%s)."),
(*failures)++;
} else
(*successes)++;
break;
case EVP_PKEY_DH:
"Unable to write DH private key (%s)."),
(*failures)++;
} else
(*successes)++;
break;
default:
/*
* Note that EVP_PKEY_DH for X9.42 is not implemented
* in the OpenSSL library.
*/
"Private key type 0x%02x import not supported."),
(*failures)++;
break;
}
/* Import user certificate. */
"Unable to write user certificate (%s)."),
(*failures)++;
} else
(*successes)++;
/* Import as many stacks of authority certificates as possible. */
for (i = 0; i != sk_X509_num(ca); i++) {
/*
* sk_X509_value() is macro that embeds a cast to (X509 *).
* Here it translates into ((X509 *)sk_value((ca), (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 */
c = sk_X509_value(ca, i);
"Writing authority certificate...\n"));
"Unable to write authority certificate (%s)."),
(*failures)++;
} else
(*successes)++;
}
}
/*
* Import objects from PKCS#12 file into token.
*/
int
{
int opt;
extern int optind_av;
extern char *optarg_av;
char *token_spec = NULL;
char *token_name = NULL;
char full_name[FULL_NAME_LEN];
CK_ULONG pk12pinlen = 0;
int i;
cryptodebug("inside pk_import");
switch (opt) {
case 'T': /* token specifier */
if (token_spec)
return (PK_ERR_USAGE);
break;
case 'i': /* input file name */
if (filename)
return (PK_ERR_USAGE);
break;
default:
return (PK_ERR_USAGE);
break;
}
}
/* If nothing is specified, default is to use softtoken. */
if (token_spec == NULL) {
} else {
/*
* Parse token specifier into token_name, manuf_id, serial_no.
* Token_name is required; manuf_id and serial_no are optional.
*/
&serial_no) < 0)
return (PK_ERR_USAGE);
}
/* Filename arg is required. */
return (PK_ERR_USAGE);
/* No additional args allowed. */
if (argc)
return (PK_ERR_USAGE);
/* Done parsing command line options. */
/* Check that the file exists and is non-empty. */
return (CKR_OK);
}
return (CKR_OK);
}
filename);
return (CKR_OK);
}
/* Find the slot with token. */
"Unable to find token %s (%s)."), full_name,
return (PK_ERR_PK11);
}
/* Get the user's PIN. */
"Unable to get token passphrase (%s)."),
return (PK_ERR_PK11);
}
/* Assume user must be logged in R/W to import objects into token. */
CKR_OK) {
gettext("Unable to log into token (%s)."),
return (PK_ERR_PK11);
}
/* Setup OpenSSL context. */
/* Open PKCS#12 file. */
return (PK_ERR_SYSTEM);
}
/* Get the PIN for the PKCS#12 import file. */
"Unable to get import file passphrase (%s)."),
return (PK_ERR_PK11);
}
/* PKCS#12 import file may have multiple elements, loop until done. */
for (i = 0; /* */; i++) {
/* Extract the contents of the PKCS#12 import file. */
"Unable to parse PKCS#12 element #%d "
return (PK_ERR_OPENSSL);
}
/* Reached end of import file? */
break;
"Scanning PKCS#12 element #%d for objects...\n"), i+1);
/* Write the objects to the token. */
"Unable to write PKCS#12 element #%d to token %s."),
i+1, full_name);
return (PK_ERR_PK11);
}
}
"%d objects imported, %d errors occurred.\n"), i,
/* Close PKCS#12 file. */
/* Clean up. */
return (0);
}