kssladm_create.c revision 5536:865d075cefb7
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
23 * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
24 * Use is subject to license terms.
25 */
26
27#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <errno.h>
30#include <sys/sysmacros.h>
31#include <security/cryptoki.h>
32#include <security/pkcs11.h>
33#include <stdio.h>
34#include <strings.h>
35#include <sys/types.h>
36#include <sys/stat.h>
37#include <sys/socket.h>
38#include <netinet/in.h>
39#include <arpa/inet.h>
40#include <netdb.h>
41#include <fcntl.h>
42#include <inet/kssl/kssl.h>
43#include <cryptoutil.h>
44#include <libscf.h>
45#include "kssladm.h"
46
47#include <kmfapi.h>
48
49void
50usage_create(boolean_t do_print)
51{
52	if (do_print)
53		(void) fprintf(stderr, "Usage:\n");
54	(void) fprintf(stderr, "kssladm create"
55	    " -f pkcs11 [-d softtoken_directory] -T <token_label>"
56	    " -C <certificate_label> -x <proxy_port>"
57	    " [-h <ca_certchain_file>]"
58	    " [options] [<server_address>] [<server_port>]\n");
59
60	(void) fprintf(stderr, "kssladm create"
61	    " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
62	    " [options] [<server_address>] [<server_port>]\n");
63
64	(void) fprintf(stderr, "kssladm create"
65	    " -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
66	    " [options] [<server_address>] [<server_port>]\n");
67
68	(void) fprintf(stderr, "options are:\n"
69	    "\t[-c <ciphersuites>]\n"
70	    "\t[-p <password_file>]\n"
71	    "\t[-t <ssl_session_cache_timeout>]\n"
72	    "\t[-z <ssl_session_cache_size>]\n"
73	    "\t[-v]\n");
74}
75
76/*
77 * Everything is allocated in one single contiguous buffer.
78 * The layout is the following:
79 * . the kssl_params_t structure
80 * . optional buffer containing pin (if key is non extractable)
81 * . the array of key attribute structs, (value of ck_attrs)
82 * . the key attributes values (values of ck_attrs[i].ck_value);
83 * . the array of sizes of the certificates, (referred to as sc_sizes[])
84 * . the certificates values (referred to as sc_certs[])
85 *
86 * The address of the certs and key attributes values are offsets
87 * from the beginning of the big buffer. sc_sizes_offset points
88 * to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
89 */
90static kssl_params_t *
91kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts,
92	KMF_X509_DER_CERT *certs, int *paramsize,
93	char *token_label, KMF_DATA *idstr,
94	KMF_CREDENTIAL *creds)
95{
96	int i, tcsize;
97	kssl_params_t *kssl_params;
98	kssl_key_t *key;
99	char *buf;
100	uint32_t bufsize;
101	static CK_BBOOL true = TRUE;
102	static CK_BBOOL false = FALSE;
103	static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
104	static CK_KEY_TYPE keytype = CKK_RSA;
105	kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
106	CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = {
107		{CKA_TOKEN, &true, sizeof (true)},
108		{CKA_EXTRACTABLE, &false, sizeof (false)},
109		{CKA_CLASS,	&class, sizeof (class) },
110		{CKA_KEY_TYPE,	&keytype, sizeof (keytype) },
111		{CKA_ID,	NULL, 0}
112	};
113	kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = {
114		{SUN_CKA_MODULUS, NULL, 0},
115		{SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
116		{SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
117		{SUN_CKA_PRIME_1, NULL, 0},
118		{SUN_CKA_PRIME_2, NULL, 0},
119		{SUN_CKA_EXPONENT_1, NULL, 0},
120		{SUN_CKA_EXPONENT_2, NULL, 0},
121		{SUN_CKA_COEFFICIENT, NULL, 0}
122	};
123	KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT];
124	int attr_cnt;
125
126	if (nxkey && idstr != NULL) {
127		exkey_attrs[4].pValue = idstr->Data;
128		exkey_attrs[4].ulValueLen = idstr->Length;
129	}
130	tcsize = 0;
131	for (i = 0; i < ncerts; i++)
132		tcsize += certs[i].certificate.Length;
133
134	bufsize = sizeof (kssl_params_t);
135	bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t)));
136
137	if (!nxkey) {
138		bzero(priv_key_bignums, sizeof (KMF_BIGINT) *
139		    MAX_ATTR_CNT);
140		/* and the key attributes */
141		priv_key_bignums[0] = rsa->rawdata.rsa.mod;
142		priv_key_bignums[1] = rsa->rawdata.rsa.pubexp;
143		priv_key_bignums[2] = rsa->rawdata.rsa.priexp;
144		priv_key_bignums[3] = rsa->rawdata.rsa.prime1;
145		priv_key_bignums[4] = rsa->rawdata.rsa.prime2;
146		priv_key_bignums[5] = rsa->rawdata.rsa.exp1;
147		priv_key_bignums[6] = rsa->rawdata.rsa.exp2;
148		priv_key_bignums[7] = rsa->rawdata.rsa.coef;
149
150		if (rsa->rawdata.rsa.mod.val == NULL ||
151		    rsa->rawdata.rsa.priexp.val == NULL) {
152			(void) fprintf(stderr,
153			"missing required attributes in private key.\n");
154			return (NULL);
155		}
156
157		attr_cnt = 0;
158		for (i = 0; i < MAX_ATTR_CNT; i++) {
159			if (priv_key_bignums[i].val == NULL)
160				continue;
161			kssl_attrs[attr_cnt].ka_type =
162			    kssl_tmpl_attrs[i].ka_type;
163			kssl_attrs[attr_cnt].ka_value_len =
164			    priv_key_bignums[i].len;
165			bufsize += sizeof (crypto_object_attribute_t) +
166			    kssl_attrs[attr_cnt].ka_value_len;
167			attr_cnt++;
168		}
169	} else {
170		/*
171		 * Compute space for the attributes and values that the
172		 * kssl kernel module will need in order to search for
173		 * the private key.
174		 */
175		for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) {
176			bufsize += sizeof (crypto_object_attribute_t) +
177			    exkey_attrs[attr_cnt].ulValueLen;
178		}
179		if (creds)
180			bufsize += creds->credlen;
181	}
182
183	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
184	bufsize += sizeof (uint32_t);
185
186	/* Now the big memory allocation */
187	if ((buf = calloc(bufsize, 1)) == NULL) {
188		(void) fprintf(stderr,
189		    "Cannot allocate memory for the kssl_params "
190		    "and values\n");
191		return (NULL);
192	}
193
194	/* LINTED */
195	kssl_params = (kssl_params_t *)buf;
196
197	buf = (char *)(kssl_params + 1);
198
199	if (!nxkey) {
200		/* the keys attributes structs array */
201		key = &kssl_params->kssl_privkey;
202		key->ks_format = CRYPTO_KEY_ATTR_LIST;
203		key->ks_count = attr_cnt;
204		key->ks_attrs_offset = buf - (char *)kssl_params;
205		buf += attr_cnt * sizeof (kssl_object_attribute_t);
206
207		attr_cnt = 0;
208		/* then the key attributes values */
209		for (i = 0; i < MAX_ATTR_CNT; i++) {
210			if (priv_key_bignums[i].val == NULL)
211				continue;
212			(void) memcpy(buf, priv_key_bignums[i].val,
213			    priv_key_bignums[i].len);
214			kssl_attrs[attr_cnt].ka_value_offset =
215			    buf - (char *)kssl_params;
216			buf += kssl_attrs[attr_cnt].ka_value_len;
217			attr_cnt++;
218		}
219	} else {
220		char tlabel[CRYPTO_EXT_SIZE_LABEL];
221		bzero(tlabel, sizeof (tlabel));
222		(void) strlcpy(tlabel, token_label, sizeof (tlabel));
223
224		/*
225		 * For a non-extractable key, we must provide the PIN
226		 * so the kssl module can access the token to find
227		 * the key handle.
228		 */
229		kssl_params->kssl_is_nxkey = 1;
230		bcopy(tlabel, kssl_params->kssl_token.toklabel,
231		    CRYPTO_EXT_SIZE_LABEL);
232		kssl_params->kssl_token.pinlen = creds->credlen;
233		kssl_params->kssl_token.tokpin_offset =
234		    buf - (char *)kssl_params;
235		kssl_params->kssl_token.ck_rv = 0;
236		bcopy(creds->cred, buf, creds->credlen);
237		buf += creds->credlen;
238
239		/*
240		 * Next in the buffer, we must provide the attributes
241		 * that the kssl module will use to search in the
242		 * token to find the protected key handle.
243		 */
244		key = &kssl_params->kssl_privkey;
245		key->ks_format = CRYPTO_KEY_ATTR_LIST;
246		key->ks_count = attr_cnt;
247		key->ks_attrs_offset = buf - (char *)kssl_params;
248
249		buf += attr_cnt * sizeof (kssl_object_attribute_t);
250		for (i = 0; i < attr_cnt; i++) {
251			bcopy(exkey_attrs[i].pValue, buf,
252			    exkey_attrs[i].ulValueLen);
253
254			kssl_attrs[i].ka_type = exkey_attrs[i].type;
255			kssl_attrs[i].ka_value_offset =
256			    buf - (char *)kssl_params;
257			kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen;
258
259			buf += exkey_attrs[i].ulValueLen;
260		}
261	}
262	/* Copy the key attributes array here */
263	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
264	    attr_cnt * sizeof (kssl_object_attribute_t));
265
266	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
267
268	/*
269	 * Finally, add the certificate chain to the buffer.
270	 */
271	kssl_params->kssl_certs.sc_count = ncerts;
272
273	/* First, an array of certificate sizes */
274	for (i = 0; i < ncerts; i++) {
275		uint32_t certsz = (uint32_t)certs[i].certificate.Length;
276		char *p = buf + (i * sizeof (uint32_t));
277		bcopy(&certsz, p, sizeof (uint32_t));
278	}
279
280	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
281	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
282
283	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
284
285	/* Now add the certificate data (ASN.1 DER encoded) */
286	for (i = 0; i < ncerts; i++) {
287		bcopy(certs[i].certificate.Data, buf,
288		    certs[i].certificate.Length);
289		buf += certs[i].certificate.Length;
290	}
291
292	*paramsize = bufsize;
293	return (kssl_params);
294}
295
296/*
297 * Extract a sensitive key via wrap/unwrap operations.
298 *
299 * This function requires that we call PKCS#11 API directly since
300 * KMF does not yet support wrapping/unwrapping of keys.   By extracting
301 * a sensitive key in wrapped form, we then unwrap it into a session key
302 * object.  KMF is then used to find the session key and return it in
303 * KMF_RAW_KEY format which is then passed along to KSSL by the caller.
304 */
305static KMF_RETURN
306get_sensitive_key_data(KMF_HANDLE_T kmfh,
307	KMF_CREDENTIAL *creds, char *keylabel,
308	char *idstr, KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey)
309{
310	KMF_RETURN rv = KMF_OK;
311	static CK_BYTE aes_param[16];
312	static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
313	static CK_KEY_TYPE privkey_type = CKK_RSA;
314	static CK_BBOOL true = TRUE;
315	static CK_BBOOL false = FALSE;
316	boolean_t kmftrue = B_TRUE;
317	boolean_t kmffalse = B_FALSE;
318	char *err = NULL;
319	char wrapkey_label[BUFSIZ];
320	int fd;
321	uint32_t nkeys = 0;
322	CK_RV ckrv;
323	CK_SESSION_HANDLE pk11session;
324	CK_BYTE aes_key_val[16];
325	int numattr = 0;
326	int idx;
327	KMF_ATTRIBUTE attrlist[16];
328	KMF_KEYSTORE_TYPE kstype;
329	KMF_KEY_CLASS kclass;
330	KMF_ENCODE_FORMAT format;
331
332	CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param,
333		sizeof (aes_param)};
334	CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE;
335	CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE;
336	CK_BYTE *wrapped_privkey = NULL;
337	CK_ULONG wrapped_privkey_len = 0;
338
339	CK_ATTRIBUTE unwrap_tmpl[] = {
340		/* code below depends on the following attribute order */
341		{CKA_TOKEN, &false, sizeof (false)},
342		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
343		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
344		{CKA_SENSITIVE, &false, sizeof (false)},
345		{CKA_PRIVATE, &false, sizeof (false)},
346		{CKA_LABEL, NULL, 0}
347	};
348
349	/*
350	 * Create a wrap key with random data.
351	 */
352	fd = open("/dev/urandom", O_RDONLY);
353	if (fd == -1) {
354		perror("Error reading /dev/urandom");
355		return (KMF_ERR_INTERNAL);
356	}
357	if (read(fd, aes_key_val, sizeof (aes_key_val)) !=
358	    sizeof (aes_key_val)) {
359		perror("Error reading from /dev/urandom");
360		(void) close(fd);
361		return (KMF_ERR_INTERNAL);
362	}
363	(void) close(fd);
364
365	pk11session = kmf_get_pk11_handle(kmfh);
366
367	/*
368	 * Login to create the wrap key stuff.
369	 */
370	ckrv = C_Login(pk11session, CKU_USER,
371	    (CK_UTF8CHAR_PTR)creds->cred, creds->credlen);
372	if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) {
373		(void) fprintf(stderr,
374		    "Cannot login to the token. error = %s\n",
375		    pkcs11_strerror(ckrv));
376		return (KMF_ERR_INTERNAL);
377	}
378
379	/*
380	 * Turn the random key into a PKCS#11 session object.
381	 */
382	ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val,
383	    sizeof (aes_key_val), &aes_key_obj);
384	if (ckrv != CKR_OK) {
385		(void) fprintf(stderr,
386		    "Cannot create wrapping key. error = %s\n",
387		    pkcs11_strerror(ckrv));
388		return (KMF_ERR_INTERNAL);
389	}
390
391	/*
392	 * Find the original private key that we are going to wrap.
393	 */
394	kstype = KMF_KEYSTORE_PK11TOKEN;
395	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
396	    &kstype, sizeof (kstype));
397	numattr++;
398
399	kclass = KMF_ASYM_PRI;
400	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
401	    &kclass, sizeof (kclass));
402	numattr++;
403
404	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
405	    creds, sizeof (KMF_CREDENTIAL));
406	numattr++;
407
408	if (keylabel) {
409		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
410		    keylabel, strlen(keylabel));
411		numattr++;
412	}
413	if (idstr) {
414		kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
415		    idstr, strlen(idstr));
416		numattr++;
417	}
418	format = KMF_FORMAT_NATIVE;
419	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
420	    &format, sizeof (format));
421	numattr++;
422
423	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
424	    &kmftrue, sizeof (kmftrue));
425	numattr++;
426
427	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
428	    &kmftrue, sizeof (kmftrue));
429	numattr++;
430
431	nkeys = 1;
432	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
433	    &nkeys, sizeof (nkeys));
434	numattr++;
435
436	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
437	    key, sizeof (KMF_KEY_HANDLE));
438	numattr++;
439
440	rv = kmf_find_key(kmfh, numattr, attrlist);
441	if (rv != KMF_OK) {
442		REPORT_KMF_ERROR(rv, "Error finding private key", err);
443		goto out;
444	}
445
446	/*
447	 * Get the size of the wrapped private key.
448	 */
449	bzero(aes_param, sizeof (aes_param));
450	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
451	    aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
452	    NULL, &wrapped_privkey_len);
453	if (ckrv != CKR_OK) {
454		/*
455		 * Most common error here is that the token doesn't
456		 * support the wrapping mechanism or the key is
457		 * marked non-extractable.  Return an error and let
458		 * the caller deal with it gracefully.
459		 */
460		(void) fprintf(stderr,
461		    "Cannot get wrap key size. error = %s\n",
462		    pkcs11_strerror(ckrv));
463		rv = KMF_ERR_INTERNAL;
464		goto out;
465	}
466	wrapped_privkey = malloc(wrapped_privkey_len);
467	if (wrapped_privkey == NULL) {
468		rv = KMF_ERR_MEMORY;
469		goto out;
470	}
471	/*
472	 * Now get the actual wrapped key data.
473	 */
474	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
475	    aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
476	    wrapped_privkey, &wrapped_privkey_len);
477	if (ckrv != CKR_OK) {
478		(void) fprintf(stderr,
479		    "Cannot wrap private key. error = %s\n",
480		    pkcs11_strerror(ckrv));
481		rv = KMF_ERR_INTERNAL;
482		goto out;
483	}
484	/*
485	 * Create a label for the wrapped session key so we can find
486	 * it easier later.
487	 */
488	snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d",
489	    getpid());
490
491	unwrap_tmpl[5].pValue = wrapkey_label;
492	unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label);
493
494	/*
495	 * Unwrap the key into the template and create a temporary
496	 * session private key.
497	 */
498	ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj,
499	    wrapped_privkey, wrapped_privkey_len,
500	    unwrap_tmpl, 6, &sess_privkey_obj);
501	if (ckrv != CKR_OK) {
502		(void) fprintf(stderr,
503		    "Cannot unwrap private key. error = %s\n",
504		    pkcs11_strerror(ckrv));
505		rv = KMF_ERR_INTERNAL;
506		goto out;
507	}
508
509	/*
510	 * Use KMF to find the session key and return it as RAW data
511	 * so we can pass it along to KSSL.
512	 */
513	kclass = KMF_ASYM_PRI;
514	if ((idx = kmf_find_attr(KMF_KEYCLASS_ATTR, attrlist, numattr)) != -1) {
515		attrlist[idx].pValue = &kclass;
516	}
517
518	format = KMF_FORMAT_RAWKEY;
519	if ((idx = kmf_find_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
520	    numattr)) != -1) {
521		attrlist[idx].pValue = &format;
522	}
523	if (wrapkey_label != NULL &&
524	    (idx = kmf_find_attr(KMF_KEYLABEL_ATTR, attrlist, numattr)) != -1) {
525		attrlist[idx].pValue = wrapkey_label;
526		attrlist[idx].valueLen = strlen(wrapkey_label);
527	}
528
529	if ((idx = kmf_find_attr(KMF_PRIVATE_BOOL_ATTR, attrlist,
530	    numattr)) != -1) {
531		attrlist[idx].pValue = &kmffalse;
532	}
533	if ((idx = kmf_find_attr(KMF_TOKEN_BOOL_ATTR, attrlist,
534	    numattr)) != -1) {
535		attrlist[idx].pValue = &kmffalse;
536	}
537
538	if ((idx = kmf_find_attr(KMF_KEY_HANDLE_ATTR, attrlist,
539	    numattr)) != -1) {
540		attrlist[idx].pValue = rawkey;
541	}
542	/*
543	 * Clear the IDSTR attribute since it is not part of the
544	 * wrapped session key.
545	 */
546	if ((idx = kmf_find_attr(KMF_IDSTR_ATTR, attrlist,
547	    numattr)) != -1) {
548		attrlist[idx].pValue = NULL;
549		attrlist[idx].valueLen = 0;
550	}
551
552	/* The wrapped key should not be sensitive. */
553	kmf_set_attr_at_index(attrlist, numattr, KMF_SENSITIVE_BOOL_ATTR,
554	    &false, sizeof (false));
555	numattr++;
556
557	rv = kmf_find_key(kmfh, numattr, attrlist);
558	if (rv != KMF_OK) {
559		REPORT_KMF_ERROR(rv, "Error finding raw private key", err);
560		goto out;
561	}
562out:
563	if (wrapped_privkey)
564		free(wrapped_privkey);
565
566	if (aes_key_obj != CK_INVALID_HANDLE)
567		C_DestroyObject(pk11session, aes_key_obj);
568
569	if (sess_privkey_obj != CK_INVALID_HANDLE)
570		C_DestroyObject(pk11session, sess_privkey_obj);
571
572	return (rv);
573}
574
575static kssl_params_t *
576load_from_pkcs11(KMF_HANDLE_T kmfh,
577    const char *token_label, const char *password_file,
578    const char *certname, int *bufsize)
579{
580	KMF_RETURN rv;
581	KMF_X509_DER_CERT cert;
582	KMF_KEY_HANDLE key, rawkey;
583	KMF_CREDENTIAL creds;
584	KMF_DATA iddata = { NULL, 0 };
585	kssl_params_t *kssl_params = NULL;
586	uint32_t ncerts, nkeys;
587	char *err, *idstr = NULL;
588	char password_buf[1024];
589	int nxkey = 0;
590	int numattr = 0;
591	KMF_ATTRIBUTE attrlist[16];
592	KMF_KEYSTORE_TYPE kstype;
593	KMF_KEY_CLASS kclass;
594	KMF_ENCODE_FORMAT format;
595	boolean_t false = B_FALSE;
596	boolean_t true = B_TRUE;
597
598	if (get_passphrase(password_file, password_buf,
599	    sizeof (password_buf)) <= 0) {
600		perror("Unable to read passphrase");
601		goto done;
602	}
603	creds.cred = password_buf;
604	creds.credlen = strlen(password_buf);
605
606	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
607	(void) memset(&rawkey, 0, sizeof (KMF_KEY_HANDLE));
608
609	kstype = KMF_KEYSTORE_PK11TOKEN;
610	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
611	    &kstype, sizeof (kstype));
612	numattr++;
613
614	if (token_label && strlen(token_label)) {
615		kmf_set_attr_at_index(attrlist, numattr,
616		    KMF_TOKEN_LABEL_ATTR,
617		    (void *)token_label, strlen(token_label));
618		numattr++;
619	}
620
621	kmf_set_attr_at_index(attrlist, numattr, KMF_READONLY_ATTR,
622	    &false, sizeof (false));
623	numattr++;
624
625	rv = kmf_configure_keystore(kmfh, numattr, attrlist);
626	if (rv != KMF_OK) {
627		REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err);
628		goto done;
629	}
630
631	/*
632	 * Find the certificate matching the given label.
633	 */
634	numattr = 0;
635	kstype = KMF_KEYSTORE_PK11TOKEN;
636	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
637	    &kstype, sizeof (kstype));
638	numattr++;
639
640	if (certname) {
641		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
642		    (void *)certname, strlen(certname));
643		numattr++;
644	}
645	ncerts = 1;
646
647	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
648	    &ncerts, sizeof (ncerts));
649	numattr++;
650
651	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
652	    &cert, sizeof (cert));
653	numattr++;
654
655	rv = kmf_find_cert(kmfh, numattr, attrlist);
656	if (rv != KMF_OK || ncerts == 0)
657		goto done;
658
659	/*
660	 * Find the associated private key for this cert by
661	 * keying off of the label and the ASCII ID string.
662	 */
663	rv = kmf_get_cert_id_str(&cert.certificate, &idstr);
664	if (rv != KMF_OK)
665		goto done;
666
667	numattr = 1; /* attrlist[0] is already set to kstype */
668
669	kclass = KMF_ASYM_PRI;
670	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
671	    &kclass, sizeof (kclass));
672	numattr++;
673
674	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
675	    &creds, sizeof (KMF_CREDENTIAL));
676	numattr++;
677
678	format = KMF_FORMAT_RAWKEY;
679	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
680	    &format, sizeof (format));
681	numattr++;
682
683	if (certname) {
684		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
685		    (void *)certname, strlen(certname));
686		numattr++;
687	}
688	if (idstr) {
689		kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
690		    (void *)idstr, strlen(idstr));
691		numattr++;
692	}
693	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
694	    &true, sizeof (true));
695	numattr++;
696
697	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
698	    &true, sizeof (true));
699	numattr++;
700
701	/* We only expect to find 1 key at most */
702	nkeys = 1;
703	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
704	    &nkeys, sizeof (nkeys));
705	numattr++;
706
707	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
708	    &key, sizeof (KMF_KEY_HANDLE));
709	numattr++;
710
711	rv = kmf_find_key(kmfh, numattr, attrlist);
712	if (rv == KMF_ERR_SENSITIVE_KEY) {
713		kmf_free_kmf_key(kmfh, &key);
714		/*
715		 * Get a normal key handle and then do a wrap/unwrap
716		 * in order to get the necessary raw data fields needed
717		 * to send to KSSL.
718		 */
719		format = KMF_FORMAT_NATIVE;
720		rv = get_sensitive_key_data(kmfh, &creds,
721		    (char *)certname, idstr, &key, &rawkey);
722		if (rv == KMF_OK) {
723			/* Swap "key" for "rawkey" */
724			kmf_free_kmf_key(kmfh, &key);
725
726			key = rawkey;
727		} else {
728			kmf_free_kmf_key(kmfh, &key);
729
730			/* Let kssl try to find the key. */
731			nxkey = 1;
732			rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
733		}
734	} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
735		kmf_free_kmf_key(kmfh, &key);
736
737		/* Let kssl try to find the key. */
738		nxkey = 1;
739		rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
740	} else if (rv != KMF_OK || nkeys == 0)
741		goto done;
742
743	if (rv == KMF_OK)
744		kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp,
745		    1, &cert, bufsize, (char *)token_label, &iddata, &creds);
746done:
747	if (ncerts != 0)
748		kmf_free_kmf_cert(kmfh, &cert);
749	if (nkeys != 0)
750		kmf_free_kmf_key(kmfh, &key);
751	if (idstr)
752		free(idstr);
753
754	return (kssl_params);
755}
756
757/*
758 * add_cacerts
759 *
760 * Load a chain of certificates from a PEM file.
761 */
762static kssl_params_t *
763add_cacerts(KMF_HANDLE_T kmfh,
764	kssl_params_t *old_params, const char *cacert_chain_file)
765{
766	int i, newlen;
767	uint32_t certlen = 0, ncerts;
768	char *buf;
769	KMF_RETURN rv;
770	KMF_X509_DER_CERT *certs = NULL;
771	kssl_params_t *kssl_params;
772	char *err = NULL;
773	int numattr = 0;
774	KMF_ATTRIBUTE attrlist[16];
775	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
776
777	kstype = KMF_KEYSTORE_OPENSSL;
778
779	ncerts = 0;
780	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
781	    &kstype, sizeof (KMF_KEYSTORE_TYPE));
782	numattr++;
783
784	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
785	    (void *)cacert_chain_file, strlen(cacert_chain_file));
786	numattr++;
787
788	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
789	    &ncerts, sizeof (ncerts));
790	numattr++;
791
792	rv = kmf_find_cert(kmfh, numattr, attrlist);
793	if (rv != KMF_OK) {
794		REPORT_KMF_ERROR(rv, "Error finding CA certificates", err);
795		return (0);
796	}
797	certs = (KMF_X509_DER_CERT *)malloc(ncerts *
798	    sizeof (KMF_X509_DER_CERT));
799	if (certs == NULL) {
800		(void) fprintf(stderr, "memory allocation error.\n");
801		return (NULL);
802	}
803	bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT));
804
805	/* add new attribute for the cert list to be returned */
806	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
807	    certs, (ncerts * sizeof (KMF_X509_DER_CERT)));
808	numattr++;
809	rv = kmf_find_cert(kmfh, numattr, attrlist);
810
811	if (rv != KMF_OK || ncerts == 0) {
812		bzero(old_params, old_params->kssl_params_size);
813		free(old_params);
814		return (NULL);
815	}
816
817	if (verbose) {
818		(void) printf("%d certificates read successfully\n", ncerts);
819	}
820
821	newlen = old_params->kssl_params_size;
822	for (i = 0; i < ncerts; i++)
823		newlen += certs[i].certificate.Length;
824
825	/*
826	 * Get a bigger structure and update the
827	 * fields to account for the additional certs.
828	 */
829	kssl_params = realloc(old_params, newlen);
830
831	kssl_params->kssl_params_size = newlen;
832	kssl_params->kssl_certs.sc_count += ncerts;
833
834	/* Put the cert size info starting from sc_sizes[1] */
835	buf = (char *)kssl_params;
836	buf += kssl_params->kssl_certs.sc_sizes_offset;
837	bcopy(buf, &certlen, sizeof (uint32_t));
838	buf += sizeof (uint32_t);
839	for (i = 0; i < ncerts; i++) {
840		uint32_t size = (uint32_t)certs[i].certificate.Length;
841		bcopy(&size, buf, sizeof (uint32_t));
842		buf += sizeof (uint32_t);
843	}
844
845	/* Put the cert_bufs starting from sc_certs[1] */
846	buf = (char *)kssl_params;
847	buf += kssl_params->kssl_certs.sc_certs_offset;
848	buf += certlen;
849
850	/* now the certs values */
851	for (i = 0; i < ncerts; i++) {
852		bcopy(certs[i].certificate.Data, buf,
853		    certs[i].certificate.Length);
854		buf += certs[i].certificate.Length;
855	}
856
857	for (i = 0; i < ncerts; i++)
858		kmf_free_kmf_cert(kmfh, &certs[i]);
859	free(certs);
860
861	return (kssl_params);
862}
863
864/*
865 * Find a key and certificate(s) from a single PEM file.
866 */
867static kssl_params_t *
868load_from_pem(KMF_HANDLE_T kmfh, const char *filename,
869	const char *password_file, int *paramsize)
870{
871	int ncerts = 0, i;
872	kssl_params_t *kssl_params;
873	KMF_RAW_KEY_DATA *rsa = NULL;
874	KMF_X509_DER_CERT *certs = NULL;
875
876	ncerts = PEM_get_rsa_key_certs(kmfh,
877	    filename, (char *)password_file, &rsa, &certs);
878	if (rsa == NULL || certs == NULL || ncerts == 0) {
879		return (NULL);
880	}
881
882	if (verbose)
883		(void) printf("%d certificates read successfully\n", ncerts);
884
885	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
886	    NULL, NULL);
887
888	for (i = 0; i < ncerts; i++)
889		kmf_free_kmf_cert(kmfh, &certs[i]);
890	free(certs);
891	kmf_free_raw_key(rsa);
892
893	return (kssl_params);
894}
895
896/*
897 * Load a raw key and certificate(s) from a PKCS#12 file.
898 */
899static kssl_params_t *
900load_from_pkcs12(KMF_HANDLE_T kmfh, const char *filename,
901    const char *password_file, int *paramsize)
902{
903	KMF_RAW_KEY_DATA *rsa = NULL;
904	kssl_params_t *kssl_params;
905	KMF_X509_DER_CERT *certs = NULL;
906	int ncerts = 0, i;
907
908	ncerts = PKCS12_get_rsa_key_certs(kmfh, filename,
909	    password_file, &rsa, &certs);
910
911	if (certs == NULL || ncerts == 0) {
912		(void) fprintf(stderr,
913		    "Unable to read cert and/or key from %s\n", filename);
914		return (NULL);
915	}
916
917	if (verbose)
918		(void) printf("%d certificates read successfully\n", ncerts);
919
920	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
921	    NULL, NULL);
922
923	for (i = 0; i < ncerts; i++)
924		kmf_free_kmf_cert(kmfh, &certs[i]);
925	free(certs);
926
927	kmf_free_raw_key(rsa);
928	return (kssl_params);
929}
930
931int
932parse_and_set_addr(char *server_address, char *server_port,
933    struct sockaddr_in *addr)
934{
935	if (server_port == NULL) {
936		return (-1);
937	}
938
939	if (server_address == NULL) {
940		addr->sin_addr.s_addr = INADDR_ANY;
941	} else {
942		addr->sin_addr.s_addr = inet_addr(server_address);
943		if ((int)addr->sin_addr.s_addr == -1) {
944			struct hostent *hp;
945
946			if ((hp = gethostbyname(server_address)) == NULL) {
947				(void) fprintf(stderr,
948				    "Error: Unknown host: %s\n",
949				    server_address);
950				return (-1);
951			}
952
953			(void) memcpy(&addr->sin_addr.s_addr,
954			    hp->h_addr_list[0],
955			    sizeof (addr->sin_addr.s_addr));
956		}
957	}
958
959	errno = 0;
960	addr->sin_port = strtol(server_port, NULL, 10);
961	if (addr->sin_port == 0 || errno != 0) {
962		(void) fprintf(stderr, "Error: Invalid Port value: %s\n",
963		    server_port);
964		return (-1);
965	}
966
967	return (0);
968}
969
970/*
971 * The order of the ciphers is important. It is used as the
972 * default order (when -c is not specified).
973 */
974struct csuite {
975	const char *suite;
976	uint16_t val;
977	boolean_t seen;
978} cipher_suites[CIPHER_SUITE_COUNT - 1] = {
979	{"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE},
980	{"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE},
981	{"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE},
982	{"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE},
983};
984
985static int
986check_suites(char *suites, uint16_t *sarray)
987{
988	int i;
989	int err = 0;
990	char *suite;
991	int sindx = 0;
992
993	if (suites != NULL) {
994		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
995			sarray[i] = CIPHER_NOTSET;
996	} else {
997		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
998			sarray[i] = cipher_suites[i].val;
999		return (err);
1000	}
1001
1002	suite = strtok(suites, ",");
1003	do {
1004		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
1005			if (strcasecmp(suite, cipher_suites[i].suite) == 0) {
1006				if (!cipher_suites[i].seen) {
1007					sarray[sindx++] = cipher_suites[i].val;
1008					cipher_suites[i].seen = B_TRUE;
1009				}
1010				break;
1011			}
1012		}
1013
1014		if (i == (CIPHER_SUITE_COUNT - 1)) {
1015			(void) fprintf(stderr,
1016			    "Unknown Cipher suite name: %s\n", suite);
1017			err++;
1018		}
1019	} while ((suite = strtok(NULL, ",")) != NULL);
1020
1021	return (err);
1022}
1023
1024int
1025do_create(int argc, char *argv[])
1026{
1027	const char *softtoken_dir = NULL;
1028	const char *token_label = NULL;
1029	const char *password_file = NULL;
1030	const char *cert_key_file = NULL;
1031	const char *cacert_chain_file = NULL;
1032	const char *certname = NULL;
1033	char *suites = NULL;
1034	uint32_t timeout = DEFAULT_SID_TIMEOUT;
1035	uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES;
1036	uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
1037	int proxy_port = -1;
1038	struct sockaddr_in server_addr;
1039	char *format = NULL;
1040	char *port, *addr;
1041	char c;
1042	int pcnt;
1043	kssl_params_t *kssl_params;
1044	int bufsize;
1045	KMF_HANDLE_T kmfh = NULL;
1046	KMF_RETURN rv = KMF_OK;
1047	char *err = NULL;
1048
1049	argc -= 1;
1050	argv += 1;
1051
1052	while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) {
1053		switch (c) {
1054		case 'd':
1055			softtoken_dir = optarg;
1056			break;
1057		case 'c':
1058			suites = optarg;
1059			break;
1060		case 'C':
1061			certname = optarg;
1062			break;
1063		case 'f':
1064			format = optarg;
1065			break;
1066		case 'h':
1067			cacert_chain_file = optarg;
1068			break;
1069		case 'i':
1070			cert_key_file = optarg;
1071			break;
1072		case 'T':
1073			token_label = optarg;
1074			break;
1075		case 'p':
1076			password_file = optarg;
1077			break;
1078		case 't':
1079			timeout = atoi(optarg);
1080			break;
1081		case 'x':
1082			proxy_port = atoi(optarg);
1083			break;
1084		case 'v':
1085			verbose = B_TRUE;
1086			break;
1087		case 'z':
1088			scache_size = atoi(optarg);
1089			break;
1090		default:
1091			goto err;
1092		}
1093	}
1094
1095	pcnt = argc - optind;
1096	if (pcnt == 0) {
1097		port = "443";	/* default SSL port */
1098		addr = NULL;
1099	} else if (pcnt == 1) {
1100		port = argv[optind];
1101		addr = NULL;
1102	} else if (pcnt == 2) {
1103		addr = argv[optind];
1104		port = argv[optind + 1];
1105	} else {
1106		goto err;
1107	}
1108
1109	if (parse_and_set_addr(addr, port, &server_addr) < 0) {
1110		goto err;
1111	}
1112
1113	if (verbose) {
1114		(void) printf("addr=%s, port = %d\n",
1115		    inet_ntoa(server_addr.sin_addr), server_addr.sin_port);
1116	}
1117
1118	if (format == NULL || proxy_port == -1) {
1119		goto err;
1120	}
1121
1122	if (check_suites(suites, kssl_suites) != 0) {
1123		goto err;
1124	}
1125
1126	rv = kmf_initialize(&kmfh, NULL, NULL);
1127	if (rv != KMF_OK) {
1128		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
1129		return (0);
1130	}
1131
1132	if (strcmp(format, "pkcs11") == 0) {
1133		if (token_label == NULL || certname == NULL) {
1134			goto err;
1135		}
1136		if (softtoken_dir != NULL) {
1137			(void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1);
1138			if (verbose) {
1139				(void) printf(
1140				    "SOFTTOKEN_DIR=%s\n",
1141				    getenv("SOFTTOKEN_DIR"));
1142			}
1143		}
1144		kssl_params = load_from_pkcs11(kmfh,
1145		    token_label, password_file, certname, &bufsize);
1146	} else if (strcmp(format, "pkcs12") == 0) {
1147		if (cert_key_file == NULL) {
1148			goto err;
1149		}
1150		kssl_params = load_from_pkcs12(kmfh,
1151		    cert_key_file, password_file, &bufsize);
1152	} else if (strcmp(format, "pem") == 0) {
1153		if (cert_key_file == NULL) {
1154			goto err;
1155		}
1156		kssl_params = load_from_pem(kmfh,
1157		    cert_key_file, password_file, &bufsize);
1158	} else {
1159		(void) fprintf(stderr, "Unsupported cert format: %s\n", format);
1160		goto err;
1161	}
1162
1163	if (kssl_params == NULL) {
1164		(void) kmf_finalize(kmfh);
1165		return (FAILURE);
1166	}
1167
1168	/*
1169	 * Add the list of supported ciphers to the buffer.
1170	 */
1171	bcopy(kssl_suites, kssl_params->kssl_suites,
1172	    sizeof (kssl_params->kssl_suites));
1173	kssl_params->kssl_params_size = bufsize;
1174	kssl_params->kssl_addr = server_addr;
1175	kssl_params->kssl_session_cache_timeout = timeout;
1176	kssl_params->kssl_proxy_port = proxy_port;
1177	kssl_params->kssl_session_cache_size = scache_size;
1178
1179	if (cacert_chain_file != NULL) {
1180		kssl_params = add_cacerts(kmfh, kssl_params, cacert_chain_file);
1181		if (kssl_params == NULL) {
1182			bzero(kssl_params, bufsize);
1183			free(kssl_params);
1184			(void) kmf_finalize(kmfh);
1185			return (FAILURE);
1186		}
1187	}
1188
1189	if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) {
1190		int err = CRYPTO_FAILED;
1191
1192		if (kssl_params->kssl_is_nxkey)
1193			err = kssl_params->kssl_token.ck_rv;
1194		(void) fprintf(stderr,
1195		    "Error loading cert and key: 0x%x\n", err);
1196		bzero(kssl_params, bufsize);
1197		free(kssl_params);
1198		(void) kmf_finalize(kmfh);
1199		return (FAILURE);
1200	}
1201
1202	if (verbose)
1203		(void) printf("Successfully loaded cert and key\n");
1204
1205	bzero(kssl_params, bufsize);
1206	free(kssl_params);
1207	(void) kmf_finalize(kmfh);
1208	return (SUCCESS);
1209
1210err:
1211	usage_create(B_TRUE);
1212	(void) kmf_finalize(kmfh);
1213	return (SMF_EXIT_ERR_CONFIG);
1214}
1215