xref: /onnv-gate/usr/src/cmd/cmd-crypto/pktool/import.c (revision 17:003a85e6a25c)
1*17Sdinak /*
2*17Sdinak  * CDDL HEADER START
3*17Sdinak  *
4*17Sdinak  * The contents of this file are subject to the terms of the
5*17Sdinak  * Common Development and Distribution License, Version 1.0 only
6*17Sdinak  * (the "License").  You may not use this file except in compliance
7*17Sdinak  * with the License.
8*17Sdinak  *
9*17Sdinak  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*17Sdinak  * or http://www.opensolaris.org/os/licensing.
11*17Sdinak  * See the License for the specific language governing permissions
12*17Sdinak  * and limitations under the License.
13*17Sdinak  *
14*17Sdinak  * When distributing Covered Code, include this CDDL HEADER in each
15*17Sdinak  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*17Sdinak  * If applicable, add the following below this CDDL HEADER, with the
17*17Sdinak  * fields enclosed by brackets "[]" replaced with your own identifying
18*17Sdinak  * information: Portions Copyright [yyyy] [name of copyright owner]
19*17Sdinak  *
20*17Sdinak  * CDDL HEADER END
21*17Sdinak  */
22*17Sdinak /*
23*17Sdinak  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*17Sdinak  * Use is subject to license terms.
25*17Sdinak  */
26*17Sdinak 
27*17Sdinak #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*17Sdinak 
29*17Sdinak /*
30*17Sdinak  * This file implements the import operation for this tool.
31*17Sdinak  * The basic flow of the process is to decrypt the PKCS#12
32*17Sdinak  * input file if it has a password, parse the elements in
33*17Sdinak  * the file, find the soft token, log into it, import the
34*17Sdinak  * PKCS#11 objects into the soft token, and log out.
35*17Sdinak  */
36*17Sdinak 
37*17Sdinak #include <stdio.h>
38*17Sdinak #include <stdlib.h>
39*17Sdinak #include <string.h>
40*17Sdinak #include <errno.h>
41*17Sdinak #include <fcntl.h>
42*17Sdinak #include <sys/types.h>
43*17Sdinak #include <sys/stat.h>
44*17Sdinak #include <cryptoutil.h>
45*17Sdinak #include <security/cryptoki.h>
46*17Sdinak #include "common.h"
47*17Sdinak #include "biginteger.h"
48*17Sdinak #include "osslcommon.h"
49*17Sdinak #include "p12common.h"
50*17Sdinak #include <openssl/pkcs12.h>
51*17Sdinak #include <openssl/err.h>
52*17Sdinak 
53*17Sdinak /*
54*17Sdinak  * Helper function decrypt and parse PKCS#12 import file.
55*17Sdinak  */
56*17Sdinak static CK_RV
57*17Sdinak extract_pkcs12(BIO *fbio, CK_UTF8CHAR *pin, CK_ULONG pinlen,
58*17Sdinak 	EVP_PKEY **priv_key, X509 **cert, STACK_OF(X509) **ca)
59*17Sdinak /* ARGSUSED */
60*17Sdinak {
61*17Sdinak 	PKCS12		*pk12, *pk12_tmp;
62*17Sdinak 	EVP_PKEY	*temp_pkey = NULL;
63*17Sdinak 	X509		*temp_cert = NULL;
64*17Sdinak 	STACK_OF(X509)	*temp_ca = NULL;
65*17Sdinak 
66*17Sdinak 	cryptodebug("inside extract_pkcs12");
67*17Sdinak 
68*17Sdinak 	cryptodebug("calling PKCS12_new");
69*17Sdinak 	if ((pk12 = PKCS12_new()) == NULL) {
70*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
71*17Sdinak 		    "Unable to create PKCS#12 context."));
72*17Sdinak 		return (CKR_GENERAL_ERROR);
73*17Sdinak 	}
74*17Sdinak 
75*17Sdinak 	cryptodebug("calling d2i_PKCS12_bio");
76*17Sdinak 	if ((pk12_tmp = d2i_PKCS12_bio(fbio, &pk12)) == NULL) {
77*17Sdinak 		/* This is ok; it seems to mean there is no more to read. */
78*17Sdinak 		if (ERR_GET_LIB(ERR_peek_error()) == ERR_LIB_ASN1 &&
79*17Sdinak 		    ERR_GET_REASON(ERR_peek_error()) == ASN1_R_HEADER_TOO_LONG)
80*17Sdinak 			goto end_extract_pkcs12;
81*17Sdinak 
82*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
83*17Sdinak 		    "Unable to populate PKCS#12 context."));
84*17Sdinak 		PKCS12_free(pk12);
85*17Sdinak 		return (CKR_GENERAL_ERROR);
86*17Sdinak 	}
87*17Sdinak 	pk12 = pk12_tmp;
88*17Sdinak 
89*17Sdinak 	cryptodebug("calling PKCS12_parse");
90*17Sdinak 	if (PKCS12_parse(pk12, (char *)pin, &temp_pkey, &temp_cert,
91*17Sdinak 	    &temp_ca) <= 0) {
92*17Sdinak 		cryptoerror(LOG_STDERR,
93*17Sdinak 		    gettext("Unable to parse import file."));
94*17Sdinak 		PKCS12_free(pk12);
95*17Sdinak 		return (CKR_GENERAL_ERROR);
96*17Sdinak 	}
97*17Sdinak 
98*17Sdinak end_extract_pkcs12:
99*17Sdinak 
100*17Sdinak 	*priv_key = temp_pkey;
101*17Sdinak 	*cert = temp_cert;
102*17Sdinak 	*ca = temp_ca;
103*17Sdinak 
104*17Sdinak 	PKCS12_free(pk12);
105*17Sdinak 	return (CKR_OK);
106*17Sdinak }
107*17Sdinak 
108*17Sdinak /*
109*17Sdinak  * Converts OpenSSL BIGNUM into PKCS#11 biginteger_t format.
110*17Sdinak  */
111*17Sdinak static CK_RV
112*17Sdinak cvt_bn2bigint(BIGNUM *from, biginteger_t *to)
113*17Sdinak {
114*17Sdinak 	CK_BYTE		*temp;
115*17Sdinak 	CK_ULONG	temp_alloc_sz, temp_cvt_sz;
116*17Sdinak 
117*17Sdinak 	cryptodebug("inside cvt_bn2bigint");
118*17Sdinak 
119*17Sdinak 	if (from == NULL || to == NULL)
120*17Sdinak 		return (CKR_ARGUMENTS_BAD);
121*17Sdinak 
122*17Sdinak 	cryptodebug("calling BN_num_bytes");
123*17Sdinak 	temp_alloc_sz = BN_num_bytes(from);
124*17Sdinak 	if ((temp = malloc(temp_alloc_sz)) == NULL)
125*17Sdinak 		return (CKR_HOST_MEMORY);
126*17Sdinak 
127*17Sdinak 	cryptodebug("calling BN_bn2bin");
128*17Sdinak 	temp_cvt_sz = BN_bn2bin(from, (unsigned char *)temp);
129*17Sdinak 	if (temp_cvt_sz != temp_alloc_sz)
130*17Sdinak 		return (CKR_GENERAL_ERROR);
131*17Sdinak 
132*17Sdinak 	to->big_value = temp;
133*17Sdinak 	to->big_value_len = temp_cvt_sz;
134*17Sdinak 	return (CKR_OK);
135*17Sdinak }
136*17Sdinak 
137*17Sdinak /*
138*17Sdinak  * Write RSA private key to token.
139*17Sdinak  */
140*17Sdinak static CK_RV
141*17Sdinak write_rsa_private(CK_SESSION_HANDLE sess, RSA *rsa, X509 *cert)
142*17Sdinak {
143*17Sdinak 	CK_RV		rv = CKR_OK;
144*17Sdinak 	int		i = 0;
145*17Sdinak 	static CK_OBJECT_CLASS	objclass = CKO_PRIVATE_KEY;
146*17Sdinak 	static CK_KEY_TYPE	keytype = CKK_RSA;
147*17Sdinak 	CK_BYTE		*label = NULL;
148*17Sdinak 	CK_ULONG	label_len = 0;
149*17Sdinak 	CK_BYTE		*id = NULL;
150*17Sdinak 	CK_ULONG	id_len = 0;
151*17Sdinak 	CK_DATE		startdate = { "", "", "" };
152*17Sdinak 	CK_DATE		enddate = { "", "", "" };
153*17Sdinak 	char		tmpdate[8];
154*17Sdinak 	biginteger_t	mod = { NULL, 0 };	/* required */
155*17Sdinak 	biginteger_t	pubexp = { NULL, 0 };	/* required */
156*17Sdinak 	biginteger_t	priexp = { NULL, 0 };	/* optional */
157*17Sdinak 	biginteger_t	prime1 = { NULL, 0 };	/* optional */
158*17Sdinak 	biginteger_t	prime2 = { NULL, 0 };	/* optional */
159*17Sdinak 	biginteger_t	exp1 = { NULL, 0 };	/* optional */
160*17Sdinak 	biginteger_t	exp2 = { NULL, 0 };	/* optional */
161*17Sdinak 	biginteger_t	coef = { NULL, 0 };	/* optional */
162*17Sdinak 	CK_ATTRIBUTE	rsa_pri_attrs[16] = {
163*17Sdinak 		{ CKA_CLASS, &objclass, sizeof (objclass) },
164*17Sdinak 		{ CKA_KEY_TYPE, &keytype, sizeof (keytype) },
165*17Sdinak 		{ CKA_PRIVATE, &pk_true, sizeof (pk_true) },
166*17Sdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
167*17Sdinak 		{ CKA_LABEL, NULL, 0 },
168*17Sdinak 		{ CKA_ID, NULL, 0 },
169*17Sdinak 		{ CKA_START_DATE, NULL, 0 },
170*17Sdinak 		{ CKA_END_DATE, NULL, 0 },
171*17Sdinak 		{ CKA_MODULUS, NULL, 0 },
172*17Sdinak 		{ CKA_PUBLIC_EXPONENT, NULL, 0 },
173*17Sdinak 		{ 0 /* CKA_PRIVATE_EXPONENT */, NULL, 0 },	/* optional */
174*17Sdinak 		{ 0 /* CKA_PRIME_1 */, NULL, 0 },		/*  |  */
175*17Sdinak 		{ 0 /* CKA_PRIME_2 */, NULL, 0 },		/*  |  */
176*17Sdinak 		{ 0 /* CKA_EXPONENT_1 */, NULL, 0 },		/*  |  */
177*17Sdinak 		{ 0 /* CKA_EXPONENT_2 */, NULL, 0 },		/*  |  */
178*17Sdinak 		{ 0 /* CKA_COEFFICIENT */, NULL, 0 }		/*  V  */
179*17Sdinak 	    };
180*17Sdinak 	CK_ULONG	count = sizeof (rsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
181*17Sdinak 	CK_OBJECT_HANDLE	obj;
182*17Sdinak 
183*17Sdinak 	cryptodebug("inside write_rsa_private");
184*17Sdinak 
185*17Sdinak 	/* Attributes start at array index 4. */
186*17Sdinak 	i = 4;
187*17Sdinak 
188*17Sdinak 	/* Recycle the certificate label for the private key label. */
189*17Sdinak 	cryptodebug("calling X509_alias_get0");
190*17Sdinak 	if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
191*17Sdinak 		label = (CK_BYTE *)gettext("no label");
192*17Sdinak 		label_len = strlen((char *)label);
193*17Sdinak 	}
194*17Sdinak 	copy_string_to_attr(label, label_len, &(rsa_pri_attrs[i++]));
195*17Sdinak 
196*17Sdinak 	/* Recycle the certificate id for the private key id. */
197*17Sdinak 	cryptodebug("calling PKTOOL_X509_keyid_get0");
198*17Sdinak 	if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
199*17Sdinak 		id = (CK_BYTE *)gettext("no id");
200*17Sdinak 		id_len = strlen((char *)id);
201*17Sdinak 	}
202*17Sdinak 	copy_string_to_attr(id, id_len, &(rsa_pri_attrs[i++]));
203*17Sdinak 
204*17Sdinak 	/* Recycle the certificate start and end dates for private key.  */
205*17Sdinak 	cryptodebug("calling X509_get_notBefore");
206*17Sdinak 	if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) {
207*17Sdinak 		(void) memcpy(&startdate, tmpdate, sizeof (startdate));
208*17Sdinak 		copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate),
209*17Sdinak 		    &(rsa_pri_attrs[i++]));
210*17Sdinak 	}
211*17Sdinak 
212*17Sdinak 	cryptodebug("calling X509_get_notAfter");
213*17Sdinak 	if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) {
214*17Sdinak 		(void) memcpy(&enddate, tmpdate, sizeof (enddate));
215*17Sdinak 		copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate),
216*17Sdinak 		    &(rsa_pri_attrs[i++]));
217*17Sdinak 	}
218*17Sdinak 
219*17Sdinak 	/* Modulus n */
220*17Sdinak 	cryptodebug("converting RSA private key modulus");
221*17Sdinak 	if ((rv = cvt_bn2bigint(rsa->n, &mod)) != CKR_OK) {
222*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
223*17Sdinak 		    "Unable to convert RSA private key modulus."));
224*17Sdinak 		return (rv);
225*17Sdinak 	}
226*17Sdinak 	copy_bigint_to_attr(mod, &(rsa_pri_attrs[i++]));
227*17Sdinak 
228*17Sdinak 	/* Public exponent e */
229*17Sdinak 	cryptodebug("converting RSA private key public exponent");
230*17Sdinak 	if ((rv = cvt_bn2bigint(rsa->e, &pubexp)) != CKR_OK) {
231*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
232*17Sdinak 		    "Unable to convert RSA private key public exponent."));
233*17Sdinak 		return (rv);
234*17Sdinak 	}
235*17Sdinak 	copy_bigint_to_attr(pubexp, &(rsa_pri_attrs[i++]));
236*17Sdinak 
237*17Sdinak 	/* Private exponent d */
238*17Sdinak 	if (rsa->d != NULL) {
239*17Sdinak 		cryptodebug("converting RSA private key private exponent");
240*17Sdinak 		if ((rv = cvt_bn2bigint(rsa->d, &priexp)) != CKR_OK) {
241*17Sdinak 			cryptoerror(LOG_STDERR, gettext("Unable to convert "
242*17Sdinak 			    "RSA private key private exponent."));
243*17Sdinak 			return (rv);
244*17Sdinak 		}
245*17Sdinak 		rsa_pri_attrs[i].type = CKA_PRIVATE_EXPONENT;
246*17Sdinak 		copy_bigint_to_attr(priexp, &(rsa_pri_attrs[i++]));
247*17Sdinak 	} else
248*17Sdinak 		cryptodebug("no RSA private key private exponent");
249*17Sdinak 
250*17Sdinak 	/* Prime p */
251*17Sdinak 	if (rsa->p != NULL) {
252*17Sdinak 		cryptodebug("converting RSA private key prime 1");
253*17Sdinak 		if ((rv = cvt_bn2bigint(rsa->p, &prime1)) != CKR_OK) {
254*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
255*17Sdinak 			    "Unable to convert RSA private key prime 1."));
256*17Sdinak 			return (rv);
257*17Sdinak 		}
258*17Sdinak 		rsa_pri_attrs[i].type = CKA_PRIME_1;
259*17Sdinak 		copy_bigint_to_attr(prime1, &(rsa_pri_attrs[i++]));
260*17Sdinak 	} else
261*17Sdinak 		cryptodebug("no RSA private key prime 1");
262*17Sdinak 
263*17Sdinak 	/* Prime q */
264*17Sdinak 	if (rsa->q != NULL) {
265*17Sdinak 		cryptodebug("converting RSA private key prime 2");
266*17Sdinak 		if ((rv = cvt_bn2bigint(rsa->q, &prime2)) != CKR_OK) {
267*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
268*17Sdinak 			    "Unable to convert RSA private key prime 2."));
269*17Sdinak 			return (rv);
270*17Sdinak 		}
271*17Sdinak 		rsa_pri_attrs[i].type = CKA_PRIME_2;
272*17Sdinak 		copy_bigint_to_attr(prime2, &(rsa_pri_attrs[i++]));
273*17Sdinak 	} else
274*17Sdinak 		cryptodebug("no RSA private key prime 2");
275*17Sdinak 
276*17Sdinak 	/* Private exponent d modulo p-1 */
277*17Sdinak 	if (rsa->dmp1 != NULL) {
278*17Sdinak 		cryptodebug("converting RSA private key exponent 1");
279*17Sdinak 		if ((rv = cvt_bn2bigint(rsa->dmp1, &exp1)) != CKR_OK) {
280*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
281*17Sdinak 			    "Unable to convert RSA private key exponent 1."));
282*17Sdinak 			return (rv);
283*17Sdinak 		}
284*17Sdinak 		rsa_pri_attrs[i].type = CKA_EXPONENT_1;
285*17Sdinak 		copy_bigint_to_attr(exp1, &(rsa_pri_attrs[i++]));
286*17Sdinak 	} else
287*17Sdinak 		cryptodebug("no RSA private key exponent 1");
288*17Sdinak 
289*17Sdinak 	/* Private exponent d modulo q-1 */
290*17Sdinak 	if (rsa->dmq1 != NULL) {
291*17Sdinak 		cryptodebug("converting RSA private key exponent 2");
292*17Sdinak 		if ((rv = cvt_bn2bigint(rsa->dmq1, &exp2)) != CKR_OK) {
293*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
294*17Sdinak 			    "Unable to convert RSA private key exponent 2."));
295*17Sdinak 			return (rv);
296*17Sdinak 		}
297*17Sdinak 		rsa_pri_attrs[i].type = CKA_EXPONENT_2;
298*17Sdinak 		copy_bigint_to_attr(exp2, &(rsa_pri_attrs[i++]));
299*17Sdinak 	} else
300*17Sdinak 		cryptodebug("no RSA private key exponent 2");
301*17Sdinak 
302*17Sdinak 	/* CRT coefficient q-inverse mod p */
303*17Sdinak 	if (rsa->iqmp != NULL) {
304*17Sdinak 		cryptodebug("converting RSA private key coefficient");
305*17Sdinak 		if ((rv = cvt_bn2bigint(rsa->iqmp, &coef)) != CKR_OK) {
306*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
307*17Sdinak 			    "Unable to convert RSA private key coefficient."));
308*17Sdinak 			return (rv);
309*17Sdinak 		}
310*17Sdinak 		rsa_pri_attrs[i].type = CKA_COEFFICIENT;
311*17Sdinak 		copy_bigint_to_attr(coef, &(rsa_pri_attrs[i++]));
312*17Sdinak 	} else
313*17Sdinak 		cryptodebug("no RSA private key coefficient");
314*17Sdinak 
315*17Sdinak 	/* Indicates programming error:  attributes overran the template */
316*17Sdinak 	if (i > count) {
317*17Sdinak 		cryptodebug("error: more attributes found than accounted for");
318*17Sdinak 		i = count;
319*17Sdinak 	}
320*17Sdinak 
321*17Sdinak 	cryptodebug("calling C_CreateObject");
322*17Sdinak 	if ((rv = C_CreateObject(sess, rsa_pri_attrs, i, &obj)) != CKR_OK) {
323*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
324*17Sdinak 		    "Unable to create RSA private key object."));
325*17Sdinak 		return (rv);
326*17Sdinak 	}
327*17Sdinak 
328*17Sdinak 	return (CKR_OK);
329*17Sdinak }
330*17Sdinak 
331*17Sdinak /*
332*17Sdinak  * Write DSA private key to token.
333*17Sdinak  */
334*17Sdinak static CK_RV
335*17Sdinak write_dsa_private(CK_SESSION_HANDLE sess, DSA *dsa, X509 *cert)
336*17Sdinak {
337*17Sdinak 	CK_RV		rv = CKR_OK;
338*17Sdinak 	int		i = 0;
339*17Sdinak 	static CK_OBJECT_CLASS	objclass = CKO_PRIVATE_KEY;
340*17Sdinak 	static CK_KEY_TYPE	keytype = CKK_DSA;
341*17Sdinak 	CK_BYTE		*label = NULL;
342*17Sdinak 	CK_ULONG	label_len = 0;
343*17Sdinak 	CK_BYTE		*id = NULL;
344*17Sdinak 	CK_ULONG	id_len = 0;
345*17Sdinak 	CK_DATE		startdate = { "", "", "" };
346*17Sdinak 	CK_DATE		enddate = { "", "", "" };
347*17Sdinak 	char		tmpdate[8];
348*17Sdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
349*17Sdinak 	biginteger_t	subprime = { NULL, 0 };	/* required */
350*17Sdinak 	biginteger_t	base = { NULL, 0 };	/* required */
351*17Sdinak 	biginteger_t	value = { NULL, 0 };	/* required */
352*17Sdinak 	CK_ATTRIBUTE	dsa_pri_attrs[12] = {
353*17Sdinak 		{ CKA_CLASS, &objclass, sizeof (objclass) },
354*17Sdinak 		{ CKA_KEY_TYPE, &keytype, sizeof (keytype) },
355*17Sdinak 		{ CKA_PRIVATE, &pk_true, sizeof (pk_true) },
356*17Sdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
357*17Sdinak 		{ CKA_LABEL, NULL, 0 },
358*17Sdinak 		{ CKA_ID, NULL, 0 },
359*17Sdinak 		{ CKA_START_DATE, NULL, 0 },
360*17Sdinak 		{ CKA_END_DATE, NULL, 0 },
361*17Sdinak 		{ CKA_PRIME, NULL, 0 },
362*17Sdinak 		{ CKA_SUBPRIME, NULL, 0 },
363*17Sdinak 		{ CKA_BASE, NULL, 0 },
364*17Sdinak 		{ CKA_VALUE, NULL, 0 }
365*17Sdinak 	    };
366*17Sdinak 	CK_ULONG	count = sizeof (dsa_pri_attrs) / sizeof (CK_ATTRIBUTE);
367*17Sdinak 	CK_OBJECT_HANDLE	obj;
368*17Sdinak 
369*17Sdinak 	cryptodebug("inside write_dsa_private");
370*17Sdinak 
371*17Sdinak 	/* Attributes start at array index 4. */
372*17Sdinak 	i = 4;
373*17Sdinak 
374*17Sdinak 	/* Recycle the certificate label for the private key label. */
375*17Sdinak 	cryptodebug("calling X509_alias_get0");
376*17Sdinak 	if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
377*17Sdinak 		label = (CK_BYTE *)gettext("no label");
378*17Sdinak 		label_len = strlen((char *)label);
379*17Sdinak 	}
380*17Sdinak 	copy_string_to_attr(label, label_len, &(dsa_pri_attrs[i++]));
381*17Sdinak 
382*17Sdinak 	/* Recycle the certificate id for the private key id. */
383*17Sdinak 	cryptodebug("calling PKTOOL_X509_keyid_get0");
384*17Sdinak 	if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
385*17Sdinak 		id = (CK_BYTE *)gettext("no id");
386*17Sdinak 		id_len = strlen((char *)id);
387*17Sdinak 	}
388*17Sdinak 	copy_string_to_attr(id, id_len, &(dsa_pri_attrs[i++]));
389*17Sdinak 
390*17Sdinak 	/* Recycle the certificate start and end dates for private key.  */
391*17Sdinak 	cryptodebug("calling X509_get_notBefore");
392*17Sdinak 	if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) {
393*17Sdinak 		(void) memcpy(&startdate, tmpdate, sizeof (startdate));
394*17Sdinak 		copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate),
395*17Sdinak 		    &(dsa_pri_attrs[i++]));
396*17Sdinak 	}
397*17Sdinak 
398*17Sdinak 	cryptodebug("calling X509_get_notAfter");
399*17Sdinak 	if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) {
400*17Sdinak 		(void) memcpy(&enddate, tmpdate, sizeof (enddate));
401*17Sdinak 		copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate),
402*17Sdinak 		    &(dsa_pri_attrs[i++]));
403*17Sdinak 	}
404*17Sdinak 
405*17Sdinak 	/* Prime p */
406*17Sdinak 	cryptodebug("converting DSA private key prime");
407*17Sdinak 	if ((rv = cvt_bn2bigint(dsa->p, &prime)) != CKR_OK) {
408*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
409*17Sdinak 		    "Unable to convert DSA private key prime."));
410*17Sdinak 		return (rv);
411*17Sdinak 	}
412*17Sdinak 	copy_bigint_to_attr(prime, &(dsa_pri_attrs[i++]));
413*17Sdinak 
414*17Sdinak 	/* Subprime q */
415*17Sdinak 	cryptodebug("converting DSA private key subprime");
416*17Sdinak 	if ((rv = cvt_bn2bigint(dsa->q, &subprime)) != CKR_OK) {
417*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
418*17Sdinak 		    "Unable to convert DSA private key subprime."));
419*17Sdinak 		return (rv);
420*17Sdinak 	}
421*17Sdinak 	copy_bigint_to_attr(subprime, &(dsa_pri_attrs[i++]));
422*17Sdinak 
423*17Sdinak 	/* Base g */
424*17Sdinak 	cryptodebug("converting DSA private key base");
425*17Sdinak 	if ((rv = cvt_bn2bigint(dsa->g, &base)) != CKR_OK) {
426*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
427*17Sdinak 		    "Unable to convert DSA private key base."));
428*17Sdinak 		return (rv);
429*17Sdinak 	}
430*17Sdinak 	copy_bigint_to_attr(base, &(dsa_pri_attrs[i++]));
431*17Sdinak 
432*17Sdinak 	/* Private key x */
433*17Sdinak 	cryptodebug("converting DSA private key value");
434*17Sdinak 	if ((rv = cvt_bn2bigint(dsa->priv_key, &value)) != CKR_OK) {
435*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
436*17Sdinak 		    "Unable to convert DSA private key value."));
437*17Sdinak 		return (rv);
438*17Sdinak 	}
439*17Sdinak 	copy_bigint_to_attr(value, &(dsa_pri_attrs[i++]));
440*17Sdinak 
441*17Sdinak 	/* Indicates programming error:  attributes overran the template */
442*17Sdinak 	if (i > count) {
443*17Sdinak 		cryptodebug("error: more attributes found than accounted for");
444*17Sdinak 		i = count;
445*17Sdinak 	}
446*17Sdinak 
447*17Sdinak 	cryptodebug("calling C_CreateObject");
448*17Sdinak 	if ((rv = C_CreateObject(sess, dsa_pri_attrs, i, &obj)) != CKR_OK) {
449*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
450*17Sdinak 		    "Unable to create DSA private key object."));
451*17Sdinak 		return (rv);
452*17Sdinak 	}
453*17Sdinak 
454*17Sdinak 	return (CKR_OK);
455*17Sdinak }
456*17Sdinak 
457*17Sdinak /*
458*17Sdinak  * Write DH private key to token.
459*17Sdinak  */
460*17Sdinak static CK_RV
461*17Sdinak write_dh_private(CK_SESSION_HANDLE sess, DH *dh, X509 *cert)
462*17Sdinak {
463*17Sdinak 	CK_RV		rv = CKR_OK;
464*17Sdinak 	int		i = 0;
465*17Sdinak 	static CK_OBJECT_CLASS	objclass = CKO_PRIVATE_KEY;
466*17Sdinak 	static CK_KEY_TYPE	keytype = CKK_DH;
467*17Sdinak 	CK_BYTE		*label = NULL;
468*17Sdinak 	CK_ULONG	label_len = 0;
469*17Sdinak 	CK_BYTE		*id = NULL;
470*17Sdinak 	CK_ULONG	id_len = 0;
471*17Sdinak 	CK_DATE		startdate = { "", "", "" };
472*17Sdinak 	CK_DATE		enddate = { "", "", "" };
473*17Sdinak 	char		tmpdate[8];
474*17Sdinak 	biginteger_t	prime = { NULL, 0 };	/* required */
475*17Sdinak 	biginteger_t	base = { NULL, 0 };	/* required */
476*17Sdinak 	biginteger_t	value = { NULL, 0 };	/* required */
477*17Sdinak 	CK_ATTRIBUTE	dh_pri_attrs[11] = {
478*17Sdinak 		{ CKA_CLASS, &objclass, sizeof (objclass) },
479*17Sdinak 		{ CKA_KEY_TYPE, &keytype, sizeof (keytype) },
480*17Sdinak 		{ CKA_PRIVATE, &pk_true, sizeof (pk_true) },
481*17Sdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
482*17Sdinak 		{ CKA_LABEL, NULL, 0 },
483*17Sdinak 		{ CKA_ID, NULL, 0 },
484*17Sdinak 		{ CKA_START_DATE, NULL, 0 },
485*17Sdinak 		{ CKA_END_DATE, NULL, 0 },
486*17Sdinak 		{ CKA_PRIME, NULL, 0 },
487*17Sdinak 		{ CKA_BASE, NULL, 0 },
488*17Sdinak 		{ CKA_VALUE, NULL, 0 }
489*17Sdinak 	    };
490*17Sdinak 	CK_ULONG	count = sizeof (dh_pri_attrs) / sizeof (CK_ATTRIBUTE);
491*17Sdinak 	CK_OBJECT_HANDLE	obj;
492*17Sdinak 
493*17Sdinak 	cryptodebug("inside write_dh_private");
494*17Sdinak 
495*17Sdinak 	/* Attributes start at array index 4. */
496*17Sdinak 	i = 4;
497*17Sdinak 
498*17Sdinak 	/* Recycle the certificate label for the private key label. */
499*17Sdinak 	cryptodebug("calling X509_alias_get0");
500*17Sdinak 	if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
501*17Sdinak 		label = (CK_BYTE *)gettext("no label");
502*17Sdinak 		label_len = strlen((char *)label);
503*17Sdinak 	}
504*17Sdinak 	copy_string_to_attr(label, label_len, &(dh_pri_attrs[i++]));
505*17Sdinak 
506*17Sdinak 	/* Recycle the certificate id for the private key id. */
507*17Sdinak 	cryptodebug("PKTOOL_X509_keyid_get0");
508*17Sdinak 	if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
509*17Sdinak 		id = (CK_BYTE *)gettext("no id");
510*17Sdinak 		id_len = strlen((char *)id);
511*17Sdinak 	}
512*17Sdinak 	copy_string_to_attr(id, id_len, &(dh_pri_attrs[i++]));
513*17Sdinak 
514*17Sdinak 	/* Recycle the certificate start and end dates for private key.  */
515*17Sdinak 	cryptodebug("calling X509_get_notBefore");
516*17Sdinak 	if (PKTOOL_cvt_ossltime(X509_get_notBefore(cert), tmpdate)) {
517*17Sdinak 		(void) memcpy(&startdate, tmpdate, sizeof (startdate));
518*17Sdinak 		copy_string_to_attr((CK_BYTE *)&startdate, sizeof (startdate),
519*17Sdinak 		    &(dh_pri_attrs[i++]));
520*17Sdinak 	}
521*17Sdinak 
522*17Sdinak 	cryptodebug("calling X509_get_notAfter");
523*17Sdinak 	if (PKTOOL_cvt_ossltime(X509_get_notAfter(cert), tmpdate)) {
524*17Sdinak 		(void) memcpy(&enddate, tmpdate, sizeof (enddate));
525*17Sdinak 		copy_string_to_attr((CK_BYTE *)&enddate, sizeof (enddate),
526*17Sdinak 		    &(dh_pri_attrs[i++]));
527*17Sdinak 	}
528*17Sdinak 
529*17Sdinak 	/* Prime p */
530*17Sdinak 	cryptodebug("converting DH private key prime");
531*17Sdinak 	if ((rv = cvt_bn2bigint(dh->p, &prime)) != CKR_OK) {
532*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
533*17Sdinak 		    "Unable to convert DH private key prime."));
534*17Sdinak 		return (rv);
535*17Sdinak 	}
536*17Sdinak 	copy_bigint_to_attr(prime, &(dh_pri_attrs[i++]));
537*17Sdinak 
538*17Sdinak 	/* Base g */
539*17Sdinak 	cryptodebug("converting DH private key base");
540*17Sdinak 	if ((rv = cvt_bn2bigint(dh->g, &base)) != CKR_OK) {
541*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
542*17Sdinak 		    "Unable to convert DH private key base."));
543*17Sdinak 		return (rv);
544*17Sdinak 	}
545*17Sdinak 	copy_bigint_to_attr(base, &(dh_pri_attrs[i++]));
546*17Sdinak 
547*17Sdinak 	/* Private value x */
548*17Sdinak 	cryptodebug("converting DH private key value");
549*17Sdinak 	if ((rv = cvt_bn2bigint(dh->priv_key, &value)) != CKR_OK) {
550*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
551*17Sdinak 		    "Unable to convert DH private key value."));
552*17Sdinak 		return (rv);
553*17Sdinak 	}
554*17Sdinak 	copy_bigint_to_attr(value, &(dh_pri_attrs[i++]));
555*17Sdinak 
556*17Sdinak 	/* Indicates programming error:  attributes overran the template */
557*17Sdinak 	if (i > count) {
558*17Sdinak 		cryptodebug("error: more attributes found than accounted for");
559*17Sdinak 		i = count;
560*17Sdinak 	}
561*17Sdinak 
562*17Sdinak 	cryptodebug("calling C_CreateObject");
563*17Sdinak 	if ((rv = C_CreateObject(sess, dh_pri_attrs, i, &obj)) != CKR_OK) {
564*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
565*17Sdinak 		    "Unable to create DH private key object."));
566*17Sdinak 		return (rv);
567*17Sdinak 	}
568*17Sdinak 
569*17Sdinak 	return (CKR_OK);
570*17Sdinak }
571*17Sdinak 
572*17Sdinak /*
573*17Sdinak  * Write certificate to token.
574*17Sdinak  */
575*17Sdinak static CK_RV
576*17Sdinak write_cert(CK_SESSION_HANDLE sess, X509 *cert)
577*17Sdinak {
578*17Sdinak 	CK_RV		rv = CKR_OK;
579*17Sdinak 	int		i = 0;
580*17Sdinak 	static CK_OBJECT_CLASS	objclass = CKO_CERTIFICATE;
581*17Sdinak 	static CK_CERTIFICATE_TYPE	certtype = CKC_X_509;
582*17Sdinak 	CK_BYTE		*subject = NULL;
583*17Sdinak 	CK_ULONG	subject_len = 0;
584*17Sdinak 	CK_BYTE		*value = NULL;
585*17Sdinak 	CK_ULONG	value_len = 0;
586*17Sdinak 	CK_BYTE		*label = NULL;
587*17Sdinak 	CK_ULONG	label_len = 0;
588*17Sdinak 	CK_BYTE		*id = NULL;
589*17Sdinak 	CK_ULONG	id_len = 0;
590*17Sdinak 	CK_BYTE		*issuer = NULL;
591*17Sdinak 	CK_ULONG	issuer_len = 0;
592*17Sdinak 	CK_BYTE		*serial = NULL;
593*17Sdinak 	CK_ULONG	serial_len = 0;
594*17Sdinak 	CK_ATTRIBUTE	cert_attrs[9] = {
595*17Sdinak 		{ CKA_CLASS, &objclass, sizeof (objclass) },
596*17Sdinak 		{ CKA_CERTIFICATE_TYPE, &certtype, sizeof (certtype) },
597*17Sdinak 		{ CKA_TOKEN, &pk_true, sizeof (pk_true) },
598*17Sdinak 		{ CKA_SUBJECT, NULL, 0 },		/* required */
599*17Sdinak 		{ CKA_VALUE, NULL, 0 },			/* required */
600*17Sdinak 		{ 0 /* CKA_LABEL */, NULL, 0 },		/* optional */
601*17Sdinak 		{ 0 /* CKA_ID */, NULL, 0 },		/* optional */
602*17Sdinak 		{ 0 /* CKA_ISSUER */, NULL, 0 },	/* optional */
603*17Sdinak 		{ 0 /* CKA_SERIAL_NUMBER */, NULL, 0 }	/* optional */
604*17Sdinak 	    };
605*17Sdinak 	CK_ULONG	count = sizeof (cert_attrs) / sizeof (CK_ATTRIBUTE);
606*17Sdinak 	CK_OBJECT_HANDLE	obj;
607*17Sdinak 
608*17Sdinak 	cryptodebug("inside write_cert");
609*17Sdinak 
610*17Sdinak 	/* Attributes start at array index 3. */
611*17Sdinak 	i = 3;
612*17Sdinak 
613*17Sdinak 	/*
614*17Sdinak 	 * OpenSSL subject name and issuer (a little further below) are
615*17Sdinak 	 * actually stack structures that contain individual ASN.1
616*17Sdinak 	 * components.  This stack of entries is packed into one DER string.
617*17Sdinak 	 */
618*17Sdinak 	cryptodebug("calling PKTOOL_X509_subject_name");
619*17Sdinak 	if ((subject = PKTOOL_X509_subject_name(cert, (int *)&subject_len)) ==
620*17Sdinak 	    NULL) {
621*17Sdinak 		subject = (CK_BYTE *)gettext("no subject name");
622*17Sdinak 		subject_len = strlen((char *)subject);
623*17Sdinak 	}
624*17Sdinak 	copy_string_to_attr(subject, subject_len, &(cert_attrs[i++]));
625*17Sdinak 
626*17Sdinak 	/* Get cert value, but it has to be reconstructed from cert.  */
627*17Sdinak 	cryptodebug("calling PKTOOL_X509_cert_value");
628*17Sdinak 	if ((value = PKTOOL_X509_cert_value(cert, (int *)&value_len)) == NULL) {
629*17Sdinak 		value = (CK_BYTE *)gettext("no value");
630*17Sdinak 		value_len = strlen((char *)value);
631*17Sdinak 	}
632*17Sdinak 	copy_string_to_attr(value, value_len, &(cert_attrs[i++]));
633*17Sdinak 
634*17Sdinak 	/*
635*17Sdinak 	 * Get certificate label which is "friendlyName" Netscape,
636*17Sdinak 	 * "alias" in OpenSSL.
637*17Sdinak 	 */
638*17Sdinak 	if ((label = X509_alias_get0(cert, (int *)&label_len)) == NULL) {
639*17Sdinak 		cryptodebug("no certificate label");
640*17Sdinak 	} else {
641*17Sdinak 		cert_attrs[i].type = CKA_LABEL;
642*17Sdinak 		copy_string_to_attr(label, label_len, &(cert_attrs[i++]));
643*17Sdinak 	}
644*17Sdinak 
645*17Sdinak 	/* Get the keyid for the cert. */
646*17Sdinak 	if ((id = PKTOOL_X509_keyid_get0(cert, (int *)&id_len)) == NULL) {
647*17Sdinak 		cryptodebug("no certificate id");
648*17Sdinak 	} else {
649*17Sdinak 		cert_attrs[i].type = CKA_ID;
650*17Sdinak 		copy_string_to_attr(id, id_len, &(cert_attrs[i++]));
651*17Sdinak 	}
652*17Sdinak 
653*17Sdinak 	/* Get the issuer name for the cert. */
654*17Sdinak 	if ((issuer = PKTOOL_X509_issuer_name(cert, (int *)&issuer_len)) ==
655*17Sdinak 	    NULL) {
656*17Sdinak 		cryptodebug("no certificate issuer name");
657*17Sdinak 	} else {
658*17Sdinak 		cert_attrs[i].type = CKA_ISSUER;
659*17Sdinak 		copy_string_to_attr(issuer, issuer_len, &(cert_attrs[i++]));
660*17Sdinak 	}
661*17Sdinak 
662*17Sdinak 	/* Get the cert serial number. */
663*17Sdinak 	if ((serial  = PKTOOL_X509_serial_number(cert, (int *)&serial_len)) ==
664*17Sdinak 	    NULL) {
665*17Sdinak 		cryptodebug("no certificate serial number");
666*17Sdinak 	} else {
667*17Sdinak 		cert_attrs[i].type = CKA_SERIAL_NUMBER;
668*17Sdinak 		copy_string_to_attr(serial, serial_len, &(cert_attrs[i++]));
669*17Sdinak 	}
670*17Sdinak 
671*17Sdinak 	/* Indicates programming error:  attributes overran the template */
672*17Sdinak 	if (i > count) {
673*17Sdinak 		cryptodebug("error: more attributes found than accounted for");
674*17Sdinak 		i = count;
675*17Sdinak 	}
676*17Sdinak 
677*17Sdinak 	cryptodebug("calling C_CreateObject");
678*17Sdinak 	if ((rv = C_CreateObject(sess, cert_attrs, i, &obj)) != CKR_OK) {
679*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
680*17Sdinak 		    "Unable to create X.509 certificate object."));
681*17Sdinak 		return (rv);
682*17Sdinak 	}
683*17Sdinak 
684*17Sdinak 	return (CKR_OK);
685*17Sdinak }
686*17Sdinak 
687*17Sdinak /*
688*17Sdinak  * Helper function to write PKCS#12 items to token.  Returns CKR_OK
689*17Sdinak  * or CKR_GENERAL_ERROR
690*17Sdinak  */
691*17Sdinak static CK_RV
692*17Sdinak write_token_objs(CK_SESSION_HANDLE sess, EVP_PKEY *priv_key, X509 *cert,
693*17Sdinak 	    STACK_OF(X509) *ca, int *successes, int *failures)
694*17Sdinak {
695*17Sdinak 	int		i;
696*17Sdinak 	X509		*c;
697*17Sdinak 	CK_RV		rv = CKR_OK;
698*17Sdinak 
699*17Sdinak 	cryptodebug("inside write_token_objs");
700*17Sdinak 
701*17Sdinak 	/* Do not reset *successes or *failures -- keep running totals. */
702*17Sdinak 
703*17Sdinak 	/* Import user key. */
704*17Sdinak 	switch (priv_key->type) {
705*17Sdinak 	case EVP_PKEY_RSA:
706*17Sdinak 		(void) fprintf(stdout, gettext("Writing RSA private key...\n"));
707*17Sdinak 		if ((rv = write_rsa_private(sess,
708*17Sdinak 		    EVP_PKEY_get1_RSA(priv_key), cert)) != CKR_OK) {
709*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
710*17Sdinak 			    "Unable to write RSA private key (%s)."),
711*17Sdinak 			    pkcs11_strerror(rv));
712*17Sdinak 			(*failures)++;
713*17Sdinak 		} else
714*17Sdinak 			(*successes)++;
715*17Sdinak 		break;
716*17Sdinak 	case EVP_PKEY_DSA:
717*17Sdinak 		(void) fprintf(stdout, gettext("Writing DSA private key...\n"));
718*17Sdinak 		if ((rv = write_dsa_private(sess,
719*17Sdinak 		    EVP_PKEY_get1_DSA(priv_key), cert)) != CKR_OK) {
720*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
721*17Sdinak 			    "Unable to write DSA private key (%s)."),
722*17Sdinak 			    pkcs11_strerror(rv));
723*17Sdinak 			(*failures)++;
724*17Sdinak 		} else
725*17Sdinak 			(*successes)++;
726*17Sdinak 		break;
727*17Sdinak 	case EVP_PKEY_DH:
728*17Sdinak 		(void) fprintf(stdout, gettext("Writing DH private key...\n"));
729*17Sdinak 		if ((rv = write_dh_private(sess,
730*17Sdinak 		    EVP_PKEY_get1_DH(priv_key), cert)) != CKR_OK) {
731*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
732*17Sdinak 			    "Unable to write DH private key (%s)."),
733*17Sdinak 			    pkcs11_strerror(rv));
734*17Sdinak 			(*failures)++;
735*17Sdinak 		} else
736*17Sdinak 			(*successes)++;
737*17Sdinak 		break;
738*17Sdinak 
739*17Sdinak 	default:
740*17Sdinak 		/*
741*17Sdinak 		 * Note that EVP_PKEY_DH for X9.42 is not implemented
742*17Sdinak 		 * in the OpenSSL library.
743*17Sdinak 		 */
744*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
745*17Sdinak 		    "Private key type 0x%02x import not supported."),
746*17Sdinak 		    priv_key->type);
747*17Sdinak 		(*failures)++;
748*17Sdinak 		break;
749*17Sdinak 	}
750*17Sdinak 
751*17Sdinak 	/* Import user certificate. */
752*17Sdinak 	(void) fprintf(stdout, gettext("Writing user certificate...\n"));
753*17Sdinak 	if ((rv = write_cert(sess, cert)) != CKR_OK) {
754*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
755*17Sdinak 		    "Unable to write user certificate (%s)."),
756*17Sdinak 		    pkcs11_strerror(rv));
757*17Sdinak 		(*failures)++;
758*17Sdinak 	} else
759*17Sdinak 		(*successes)++;
760*17Sdinak 
761*17Sdinak 	/* Import as many stacks of authority certificates as possible. */
762*17Sdinak 	for (i = 0; i != sk_X509_num(ca); i++) {
763*17Sdinak 		/*
764*17Sdinak 		 * sk_X509_value() is macro that embeds a cast to (X509 *).
765*17Sdinak 		 * Here it translates into ((X509 *)sk_value((ca), (i))).
766*17Sdinak 		 * Lint is complaining about the embedded casting, and
767*17Sdinak 		 * to fix it, you need to fix openssl header files.
768*17Sdinak 		 */
769*17Sdinak 		/* LINTED E_BAD_PTR_CAST_ALIGN */
770*17Sdinak 		c = sk_X509_value(ca, i);
771*17Sdinak 		(void) fprintf(stdout, gettext(
772*17Sdinak 		    "Writing authority certificate...\n"));
773*17Sdinak 		if ((rv = write_cert(sess, c)) != CKR_OK) {
774*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
775*17Sdinak 			    "Unable to write authority certificate (%s)."),
776*17Sdinak 			    pkcs11_strerror(rv));
777*17Sdinak 			(*failures)++;
778*17Sdinak 		} else
779*17Sdinak 			(*successes)++;
780*17Sdinak 	}
781*17Sdinak 
782*17Sdinak 	(void) fprintf(stdout, gettext("PKCS#12 element scan completed.\n"));
783*17Sdinak 	return (*failures != 0 ? CKR_GENERAL_ERROR : CKR_OK);
784*17Sdinak }
785*17Sdinak 
786*17Sdinak /*
787*17Sdinak  * Import objects from PKCS#12 file into token.
788*17Sdinak  */
789*17Sdinak int
790*17Sdinak pk_import(int argc, char *argv[])
791*17Sdinak {
792*17Sdinak 	char		*token_name = NULL;
793*17Sdinak 	char		*manuf_id = NULL;
794*17Sdinak 	char		*serial_no = NULL;
795*17Sdinak 	char		full_name[FULL_NAME_LEN];
796*17Sdinak 	char		*filename = NULL;
797*17Sdinak 	struct stat	statbuf;
798*17Sdinak 	CK_SLOT_ID	slot_id;
799*17Sdinak 	CK_FLAGS	pin_state;
800*17Sdinak 	CK_UTF8CHAR_PTR	pin = NULL;
801*17Sdinak 	CK_ULONG	pinlen = 0;
802*17Sdinak 	CK_UTF8CHAR_PTR	pk12pin = NULL;
803*17Sdinak 	CK_ULONG	pk12pinlen = 0;
804*17Sdinak 	CK_SESSION_HANDLE	sess;
805*17Sdinak 	BIO		*fbio = NULL;
806*17Sdinak 	EVP_PKEY	*priv_key = NULL;
807*17Sdinak 	X509		*cert = NULL;
808*17Sdinak 	STACK_OF(X509)	*ca = NULL;
809*17Sdinak 	CK_RV		rv = CKR_OK;
810*17Sdinak 	int		i;
811*17Sdinak 	int		good_count = 0, bad_count = 0;	/* running totals */
812*17Sdinak 
813*17Sdinak 	cryptodebug("inside pk_import");
814*17Sdinak 
815*17Sdinak 	/* Get rid of subcommand word "import". */
816*17Sdinak 	argc--;
817*17Sdinak 	argv++;
818*17Sdinak 
819*17Sdinak 	/* One additional arg required:  filename. */
820*17Sdinak 	if (argc != 1)
821*17Sdinak 		return (PK_ERR_USAGE);
822*17Sdinak 
823*17Sdinak 	filename = argv[0];
824*17Sdinak 	/* Done parsing command line options. */
825*17Sdinak 
826*17Sdinak 	/* Check that the file exists and is non-empty. */
827*17Sdinak 	if (access(filename, R_OK) < 0) {
828*17Sdinak 		cryptoerror(LOG_STDERR, gettext("File \"%s\" is unreadable "
829*17Sdinak 		    "(%s)."), filename, strerror(errno));
830*17Sdinak 		return (CKR_OK);
831*17Sdinak 	}
832*17Sdinak 	if (stat(filename, &statbuf) < 0) {
833*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to get size of "
834*17Sdinak 		    "file \"%s\" (%s)."), filename, strerror(errno));
835*17Sdinak 		return (CKR_OK);
836*17Sdinak 	}
837*17Sdinak 	if (statbuf.st_size == 0) {
838*17Sdinak 		cryptoerror(LOG_STDERR, gettext("File \"%s\" is empty."),
839*17Sdinak 		    filename);
840*17Sdinak 		return (CKR_OK);
841*17Sdinak 	}
842*17Sdinak 
843*17Sdinak 	/* Import operation only supported on softtoken. */
844*17Sdinak 	if (token_name == NULL)
845*17Sdinak 		token_name = SOFT_TOKEN_LABEL;
846*17Sdinak 	if (manuf_id == NULL)
847*17Sdinak 		manuf_id = SOFT_MANUFACTURER_ID;
848*17Sdinak 	if (serial_no == NULL)
849*17Sdinak 		serial_no = SOFT_TOKEN_SERIAL;
850*17Sdinak 	full_token_name(token_name, manuf_id, serial_no, full_name);
851*17Sdinak 
852*17Sdinak 	/* Find the slot with token. */
853*17Sdinak 	if ((rv = find_token_slot(token_name, manuf_id, serial_no, &slot_id,
854*17Sdinak 	    &pin_state)) != CKR_OK) {
855*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
856*17Sdinak 		    "Unable to find token %s (%s)."), full_name,
857*17Sdinak 		    pkcs11_strerror(rv));
858*17Sdinak 		return (PK_ERR_PK11);
859*17Sdinak 	}
860*17Sdinak 
861*17Sdinak 	/* Get the user's PIN. */
862*17Sdinak 	if ((rv = get_pin(gettext("Enter token passphrase:"), NULL, &pin,
863*17Sdinak 	    &pinlen)) != CKR_OK) {
864*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
865*17Sdinak 		    "Unable to get token passphrase (%s)."),
866*17Sdinak 		    pkcs11_strerror(rv));
867*17Sdinak 		quick_finish(NULL);
868*17Sdinak 		return (PK_ERR_PK11);
869*17Sdinak 	}
870*17Sdinak 
871*17Sdinak 	/* Assume user must be logged in R/W to import objects into token. */
872*17Sdinak 	if ((rv = quick_start(slot_id, CKF_RW_SESSION, pin, pinlen, &sess)) !=
873*17Sdinak 	    CKR_OK) {
874*17Sdinak 		cryptoerror(LOG_STDERR,
875*17Sdinak 		    gettext("Unable to log into token (%s)."),
876*17Sdinak 		    pkcs11_strerror(rv));
877*17Sdinak 		quick_finish(sess);
878*17Sdinak 		return (PK_ERR_PK11);
879*17Sdinak 	}
880*17Sdinak 
881*17Sdinak 	/* Setup OpenSSL context. */
882*17Sdinak 	PKTOOL_setup_openssl();
883*17Sdinak 
884*17Sdinak 	/* Open PKCS#12 file. */
885*17Sdinak 	if ((open_pkcs12(filename, &fbio)) < 0) {
886*17Sdinak 		cryptoerror(LOG_STDERR, gettext("Unable to open import file."));
887*17Sdinak 		quick_finish(sess);
888*17Sdinak 		return (PK_ERR_SYSTEM);
889*17Sdinak 	}
890*17Sdinak 
891*17Sdinak 	/* Get the PIN for the PKCS#12 import file. */
892*17Sdinak 	if ((rv = get_pin(gettext("Enter import file passphrase:"), NULL,
893*17Sdinak 	    &pk12pin, &pk12pinlen)) != CKR_OK) {
894*17Sdinak 		cryptoerror(LOG_STDERR, gettext(
895*17Sdinak 		    "Unable to get import file passphrase (%s)."),
896*17Sdinak 		    pkcs11_strerror(rv));
897*17Sdinak 		close_pkcs12(fbio);
898*17Sdinak 		quick_finish(sess);
899*17Sdinak 		return (PK_ERR_PK11);
900*17Sdinak 	}
901*17Sdinak 
902*17Sdinak 	/* PKCS#12 import file may have multiple elements, loop until done. */
903*17Sdinak 	for (i = 0; /* */; i++) {
904*17Sdinak 		/* Extract the contents of the PKCS#12 import file. */
905*17Sdinak 		if ((rv = extract_pkcs12(fbio, pk12pin, pk12pinlen, &priv_key,
906*17Sdinak 		    &cert, &ca)) != CKR_OK) {
907*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
908*17Sdinak 			    "Unable to parse PKCS#12 element #%d "
909*17Sdinak 			    "in import file (%s)."), i+1, pkcs11_strerror(rv));
910*17Sdinak 			close_pkcs12(fbio);
911*17Sdinak 			quick_finish(sess);
912*17Sdinak 			return (PK_ERR_OPENSSL);
913*17Sdinak 		}
914*17Sdinak 
915*17Sdinak 		/* Reached end of import file? */
916*17Sdinak 		if (rv == CKR_OK && priv_key == NULL && cert == NULL &&
917*17Sdinak 		    ca == NULL)
918*17Sdinak 			break;
919*17Sdinak 
920*17Sdinak 		(void) fprintf(stdout, gettext(
921*17Sdinak 		    "Scanning PKCS#12 element #%d for objects...\n"), i+1);
922*17Sdinak 
923*17Sdinak 		/* Write the objects to the token. */
924*17Sdinak 		if ((rv = write_token_objs(sess, priv_key, cert, ca,
925*17Sdinak 		    &good_count, &bad_count)) != CKR_OK) {
926*17Sdinak 			cryptoerror(LOG_STDERR, gettext(
927*17Sdinak 			    "Unable to write PKCS#12 element #%d to token %s."),
928*17Sdinak 			    i+1, full_name);
929*17Sdinak 			close_pkcs12(fbio);
930*17Sdinak 			quick_finish(sess);
931*17Sdinak 			return (PK_ERR_PK11);
932*17Sdinak 		}
933*17Sdinak 	}
934*17Sdinak 
935*17Sdinak 	(void) fprintf(stdout, gettext("%d PKCS#12 elements scanned: "
936*17Sdinak 		"%d objects imported, %d errors occurred.\n"), i,
937*17Sdinak 		good_count, bad_count);
938*17Sdinak 
939*17Sdinak 	/* Close PKCS#12 file. */
940*17Sdinak 	close_pkcs12(fbio);
941*17Sdinak 
942*17Sdinak 	/* Clean up. */
943*17Sdinak 	quick_finish(sess);
944*17Sdinak 	return (0);
945*17Sdinak }
946