1898Skais /*
2898Skais  * CDDL HEADER START
3898Skais  *
4898Skais  * The contents of this file are subject to the terms of the
51933Skrishna  * Common Development and Distribution License (the "License").
61933Skrishna  * You may not use this file except in compliance with the License.
7898Skais  *
8898Skais  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9898Skais  * or http://www.opensolaris.org/os/licensing.
10898Skais  * See the License for the specific language governing permissions
11898Skais  * and limitations under the License.
12898Skais  *
13898Skais  * When distributing Covered Code, include this CDDL HEADER in each
14898Skais  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15898Skais  * If applicable, add the following below this CDDL HEADER, with the
16898Skais  * fields enclosed by brackets "[]" replaced with your own identifying
17898Skais  * information: Portions Copyright [yyyy] [name of copyright owner]
18898Skais  *
19898Skais  * CDDL HEADER END
20898Skais  */
211933Skrishna 
22898Skais /*
23*12381SVladimir.Kotal@Sun.COM  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
24898Skais  */
25898Skais 
26898Skais #include <errno.h>
271933Skrishna #include <sys/sysmacros.h>
28898Skais #include <security/cryptoki.h>
29898Skais #include <security/pkcs11.h>
30898Skais #include <stdio.h>
31898Skais #include <strings.h>
323408Swyllys #include <sys/types.h>
333408Swyllys #include <sys/stat.h>
34898Skais #include <sys/socket.h>
353408Swyllys #include <netinet/in.h>
363408Swyllys #include <arpa/inet.h>
373408Swyllys #include <netdb.h>
383408Swyllys #include <fcntl.h>
393408Swyllys #include <inet/kssl/kssl.h>
403408Swyllys #include <cryptoutil.h>
41898Skais #include <libscf.h>
42898Skais #include "kssladm.h"
43898Skais 
443408Swyllys #include <kmfapi.h>
453408Swyllys 
46898Skais void
usage_create(boolean_t do_print)47898Skais usage_create(boolean_t do_print)
48898Skais {
49898Skais 	if (do_print)
50898Skais 		(void) fprintf(stderr, "Usage:\n");
51898Skais 	(void) fprintf(stderr, "kssladm create"
525051Swyllys 	    " -f pkcs11 [-d softtoken_directory] -T <token_label>"
535051Swyllys 	    " -C <certificate_label> -x <proxy_port>"
545051Swyllys 	    " [-h <ca_certchain_file>]"
555051Swyllys 	    " [options] [<server_address>] [<server_port>]\n");
56898Skais 
57898Skais 	(void) fprintf(stderr, "kssladm create"
585051Swyllys 	    " -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
595051Swyllys 	    " [options] [<server_address>] [<server_port>]\n");
60898Skais 
61898Skais 	(void) fprintf(stderr, "kssladm create"
625051Swyllys 	    " -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
635051Swyllys 	    " [options] [<server_address>] [<server_port>]\n");
64898Skais 
65898Skais 	(void) fprintf(stderr, "options are:\n"
665051Swyllys 	    "\t[-c <ciphersuites>]\n"
675051Swyllys 	    "\t[-p <password_file>]\n"
685051Swyllys 	    "\t[-t <ssl_session_cache_timeout>]\n"
695051Swyllys 	    "\t[-z <ssl_session_cache_size>]\n"
705051Swyllys 	    "\t[-v]\n");
71898Skais }
72898Skais 
73898Skais /*
74898Skais  * Everything is allocated in one single contiguous buffer.
75898Skais  * The layout is the following:
76898Skais  * . the kssl_params_t structure
772800Skrishna  * . optional buffer containing pin (if key is non extractable)
78898Skais  * . the array of key attribute structs, (value of ck_attrs)
79898Skais  * . the key attributes values (values of ck_attrs[i].ck_value);
801933Skrishna  * . the array of sizes of the certificates, (referred to as sc_sizes[])
811933Skrishna  * . the certificates values (referred to as sc_certs[])
82898Skais  *
83898Skais  * The address of the certs and key attributes values are offsets
841933Skrishna  * from the beginning of the big buffer. sc_sizes_offset points
851933Skrishna  * to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
86898Skais  */
87898Skais static kssl_params_t *
kmf_to_kssl(int nxkey,KMF_RAW_KEY_DATA * rsa,int ncerts,KMF_X509_DER_CERT * certs,int * paramsize,char * token_label,KMF_DATA * idstr,KMF_CREDENTIAL * creds)883408Swyllys kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts,
895536Swyllys 	KMF_X509_DER_CERT *certs, int *paramsize,
905536Swyllys 	char *token_label, KMF_DATA *idstr,
913408Swyllys 	KMF_CREDENTIAL *creds)
92898Skais {
931933Skrishna 	int i, tcsize;
94898Skais 	kssl_params_t *kssl_params;
95898Skais 	kssl_key_t *key;
96898Skais 	char *buf;
97898Skais 	uint32_t bufsize;
983408Swyllys 	static CK_BBOOL true = TRUE;
993408Swyllys 	static CK_BBOOL false = FALSE;
1003408Swyllys 	static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
1013408Swyllys 	static CK_KEY_TYPE keytype = CKK_RSA;
1023408Swyllys 	kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
1033408Swyllys 	CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = {
1043408Swyllys 		{CKA_TOKEN, &true, sizeof (true)},
1053408Swyllys 		{CKA_EXTRACTABLE, &false, sizeof (false)},
1063408Swyllys 		{CKA_CLASS,	&class, sizeof (class) },
1073408Swyllys 		{CKA_KEY_TYPE,	&keytype, sizeof (keytype) },
1083408Swyllys 		{CKA_ID,	NULL, 0}
1093408Swyllys 	};
1103408Swyllys 	kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = {
111898Skais 		{SUN_CKA_MODULUS, NULL, 0},
112898Skais 		{SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
113898Skais 		{SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
114898Skais 		{SUN_CKA_PRIME_1, NULL, 0},
115898Skais 		{SUN_CKA_PRIME_2, NULL, 0},
116898Skais 		{SUN_CKA_EXPONENT_1, NULL, 0},
117898Skais 		{SUN_CKA_EXPONENT_2, NULL, 0},
118898Skais 		{SUN_CKA_COEFFICIENT, NULL, 0}
119898Skais 	};
1203408Swyllys 	KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT];
121898Skais 	int attr_cnt;
122898Skais 
1233408Swyllys 	if (nxkey && idstr != NULL) {
1243408Swyllys 		exkey_attrs[4].pValue = idstr->Data;
1253408Swyllys 		exkey_attrs[4].ulValueLen = idstr->Length;
1263408Swyllys 	}
1271933Skrishna 	tcsize = 0;
1281933Skrishna 	for (i = 0; i < ncerts; i++)
1295536Swyllys 		tcsize += certs[i].certificate.Length;
1301933Skrishna 
131898Skais 	bufsize = sizeof (kssl_params_t);
1323408Swyllys 	bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t)));
133898Skais 
1343408Swyllys 	if (!nxkey) {
1353408Swyllys 		bzero(priv_key_bignums, sizeof (KMF_BIGINT) *
1365051Swyllys 		    MAX_ATTR_CNT);
1373408Swyllys 		/* and the key attributes */
1383408Swyllys 		priv_key_bignums[0] = rsa->rawdata.rsa.mod;
1393408Swyllys 		priv_key_bignums[1] = rsa->rawdata.rsa.pubexp;
1403408Swyllys 		priv_key_bignums[2] = rsa->rawdata.rsa.priexp;
1413408Swyllys 		priv_key_bignums[3] = rsa->rawdata.rsa.prime1;
1423408Swyllys 		priv_key_bignums[4] = rsa->rawdata.rsa.prime2;
1433408Swyllys 		priv_key_bignums[5] = rsa->rawdata.rsa.exp1;
1443408Swyllys 		priv_key_bignums[6] = rsa->rawdata.rsa.exp2;
1453408Swyllys 		priv_key_bignums[7] = rsa->rawdata.rsa.coef;
1463408Swyllys 
1473408Swyllys 		if (rsa->rawdata.rsa.mod.val == NULL ||
1485051Swyllys 		    rsa->rawdata.rsa.priexp.val == NULL) {
1493408Swyllys 			(void) fprintf(stderr,
1505051Swyllys 			"missing required attributes in private key.\n");
1513408Swyllys 			return (NULL);
1523408Swyllys 		}
153898Skais 
1543408Swyllys 		attr_cnt = 0;
1553408Swyllys 		for (i = 0; i < MAX_ATTR_CNT; i++) {
1563408Swyllys 			if (priv_key_bignums[i].val == NULL)
1573408Swyllys 				continue;
1583408Swyllys 			kssl_attrs[attr_cnt].ka_type =
1595051Swyllys 			    kssl_tmpl_attrs[i].ka_type;
1603408Swyllys 			kssl_attrs[attr_cnt].ka_value_len =
1615051Swyllys 			    priv_key_bignums[i].len;
1623408Swyllys 			bufsize += sizeof (crypto_object_attribute_t) +
1633408Swyllys 			    kssl_attrs[attr_cnt].ka_value_len;
1643408Swyllys 			attr_cnt++;
1653408Swyllys 		}
1663408Swyllys 	} else {
1673408Swyllys 		/*
1683408Swyllys 		 * Compute space for the attributes and values that the
1693408Swyllys 		 * kssl kernel module will need in order to search for
1703408Swyllys 		 * the private key.
1713408Swyllys 		 */
1723408Swyllys 		for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) {
1733408Swyllys 			bufsize += sizeof (crypto_object_attribute_t) +
1745051Swyllys 			    exkey_attrs[attr_cnt].ulValueLen;
1753408Swyllys 		}
1763408Swyllys 		if (creds)
1773408Swyllys 			bufsize += creds->credlen;
178898Skais 	}
179898Skais 
1802800Skrishna 	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
1811933Skrishna 	bufsize += sizeof (uint32_t);
1821933Skrishna 
183898Skais 	/* Now the big memory allocation */
184898Skais 	if ((buf = calloc(bufsize, 1)) == NULL) {
185898Skais 		(void) fprintf(stderr,
186898Skais 		    "Cannot allocate memory for the kssl_params "
187898Skais 		    "and values\n");
188898Skais 		return (NULL);
189898Skais 	}
190898Skais 
191898Skais 	/* LINTED */
192898Skais 	kssl_params = (kssl_params_t *)buf;
193898Skais 
194898Skais 	buf = (char *)(kssl_params + 1);
195898Skais 
1963408Swyllys 	if (!nxkey) {
1973408Swyllys 		/* the keys attributes structs array */
1983408Swyllys 		key = &kssl_params->kssl_privkey;
1993408Swyllys 		key->ks_format = CRYPTO_KEY_ATTR_LIST;
2003408Swyllys 		key->ks_count = attr_cnt;
2013408Swyllys 		key->ks_attrs_offset = buf - (char *)kssl_params;
2023408Swyllys 		buf += attr_cnt * sizeof (kssl_object_attribute_t);
2033408Swyllys 
2043408Swyllys 		attr_cnt = 0;
2053408Swyllys 		/* then the key attributes values */
2063408Swyllys 		for (i = 0; i < MAX_ATTR_CNT; i++) {
2073408Swyllys 			if (priv_key_bignums[i].val == NULL)
2083408Swyllys 				continue;
2093408Swyllys 			(void) memcpy(buf, priv_key_bignums[i].val,
2105051Swyllys 			    priv_key_bignums[i].len);
2113408Swyllys 			kssl_attrs[attr_cnt].ka_value_offset =
2123408Swyllys 			    buf - (char *)kssl_params;
2133408Swyllys 			buf += kssl_attrs[attr_cnt].ka_value_len;
2143408Swyllys 			attr_cnt++;
2153408Swyllys 		}
2163408Swyllys 	} else {
2173408Swyllys 		char tlabel[CRYPTO_EXT_SIZE_LABEL];
2183408Swyllys 		bzero(tlabel, sizeof (tlabel));
2193408Swyllys 		(void) strlcpy(tlabel, token_label, sizeof (tlabel));
2203408Swyllys 
2213408Swyllys 		/*
2223408Swyllys 		 * For a non-extractable key, we must provide the PIN
2233408Swyllys 		 * so the kssl module can access the token to find
2243408Swyllys 		 * the key handle.
2253408Swyllys 		 */
2263408Swyllys 		kssl_params->kssl_is_nxkey = 1;
2273408Swyllys 		bcopy(tlabel, kssl_params->kssl_token.toklabel,
2285051Swyllys 		    CRYPTO_EXT_SIZE_LABEL);
2293408Swyllys 		kssl_params->kssl_token.pinlen = creds->credlen;
2303408Swyllys 		kssl_params->kssl_token.tokpin_offset =
2315051Swyllys 		    buf - (char *)kssl_params;
2323408Swyllys 		kssl_params->kssl_token.ck_rv = 0;
2333408Swyllys 		bcopy(creds->cred, buf, creds->credlen);
2343408Swyllys 		buf += creds->credlen;
235898Skais 
2363408Swyllys 		/*
2373408Swyllys 		 * Next in the buffer, we must provide the attributes
2383408Swyllys 		 * that the kssl module will use to search in the
2393408Swyllys 		 * token to find the protected key handle.
2403408Swyllys 		 */
2413408Swyllys 		key = &kssl_params->kssl_privkey;
2423408Swyllys 		key->ks_format = CRYPTO_KEY_ATTR_LIST;
2433408Swyllys 		key->ks_count = attr_cnt;
2443408Swyllys 		key->ks_attrs_offset = buf - (char *)kssl_params;
2453408Swyllys 
2463408Swyllys 		buf += attr_cnt * sizeof (kssl_object_attribute_t);
2473408Swyllys 		for (i = 0; i < attr_cnt; i++) {
2483408Swyllys 			bcopy(exkey_attrs[i].pValue, buf,
2495051Swyllys 			    exkey_attrs[i].ulValueLen);
2503408Swyllys 
2513408Swyllys 			kssl_attrs[i].ka_type = exkey_attrs[i].type;
2523408Swyllys 			kssl_attrs[i].ka_value_offset =
2535051Swyllys 			    buf - (char *)kssl_params;
2543408Swyllys 			kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen;
2553408Swyllys 
2563408Swyllys 			buf += exkey_attrs[i].ulValueLen;
2573408Swyllys 		}
2583408Swyllys 	}
2593408Swyllys 	/* Copy the key attributes array here */
2603408Swyllys 	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
2615051Swyllys 	    attr_cnt * sizeof (kssl_object_attribute_t));
2623408Swyllys 
2633408Swyllys 	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
2643408Swyllys 
2653408Swyllys 	/*
2663408Swyllys 	 * Finally, add the certificate chain to the buffer.
2673408Swyllys 	 */
2683408Swyllys 	kssl_params->kssl_certs.sc_count = ncerts;
2693408Swyllys 
2703408Swyllys 	/* First, an array of certificate sizes */
2713408Swyllys 	for (i = 0; i < ncerts; i++) {
2725536Swyllys 		uint32_t certsz = (uint32_t)certs[i].certificate.Length;
2733408Swyllys 		char *p = buf + (i * sizeof (uint32_t));
2743408Swyllys 		bcopy(&certsz, p, sizeof (uint32_t));
275898Skais 	}
276898Skais 
2771933Skrishna 	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
2781933Skrishna 	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
2791933Skrishna 
2801933Skrishna 	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
2813408Swyllys 
2823408Swyllys 	/* Now add the certificate data (ASN.1 DER encoded) */
2831933Skrishna 	for (i = 0; i < ncerts; i++) {
2845536Swyllys 		bcopy(certs[i].certificate.Data, buf,
2855536Swyllys 		    certs[i].certificate.Length);
2865536Swyllys 		buf += certs[i].certificate.Length;
2871933Skrishna 	}
2881933Skrishna 
289898Skais 	*paramsize = bufsize;
290898Skais 	return (kssl_params);
291898Skais }
292898Skais 
2933408Swyllys /*
2943408Swyllys  * Extract a sensitive key via wrap/unwrap operations.
2953408Swyllys  *
2963408Swyllys  * This function requires that we call PKCS#11 API directly since
2973408Swyllys  * KMF does not yet support wrapping/unwrapping of keys.   By extracting
2983408Swyllys  * a sensitive key in wrapped form, we then unwrap it into a session key
2993408Swyllys  * object.  KMF is then used to find the session key and return it in
3003408Swyllys  * KMF_RAW_KEY format which is then passed along to KSSL by the caller.
3013408Swyllys  */
3023408Swyllys static KMF_RETURN
get_sensitive_key_data(KMF_HANDLE_T kmfh,KMF_CREDENTIAL * creds,char * keylabel,char * idstr,KMF_KEY_HANDLE * key,KMF_KEY_HANDLE * rawkey)3035051Swyllys get_sensitive_key_data(KMF_HANDLE_T kmfh,
3045051Swyllys 	KMF_CREDENTIAL *creds, char *keylabel,
3055051Swyllys 	char *idstr, KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey)
3061933Skrishna {
3073408Swyllys 	KMF_RETURN rv = KMF_OK;
3083408Swyllys 	static CK_BYTE aes_param[16];
3093408Swyllys 	static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
3103408Swyllys 	static CK_KEY_TYPE privkey_type = CKK_RSA;
3113408Swyllys 	static CK_BBOOL false = FALSE;
3125051Swyllys 	boolean_t kmftrue = B_TRUE;
3135051Swyllys 	boolean_t kmffalse = B_FALSE;
3143408Swyllys 	char *err = NULL;
3153408Swyllys 	char wrapkey_label[BUFSIZ];
3163408Swyllys 	int fd;
3173408Swyllys 	uint32_t nkeys = 0;
3183408Swyllys 	CK_RV ckrv;
3193408Swyllys 	CK_SESSION_HANDLE pk11session;
3203408Swyllys 	CK_BYTE aes_key_val[16];
3215051Swyllys 	int numattr = 0;
3225051Swyllys 	int idx;
3235051Swyllys 	KMF_ATTRIBUTE attrlist[16];
3245051Swyllys 	KMF_KEYSTORE_TYPE kstype;
3255051Swyllys 	KMF_KEY_CLASS kclass;
3265051Swyllys 	KMF_ENCODE_FORMAT format;
3273408Swyllys 
3283408Swyllys 	CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param,
3293408Swyllys 		sizeof (aes_param)};
3303408Swyllys 	CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE;
3313408Swyllys 	CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE;
3323408Swyllys 	CK_BYTE *wrapped_privkey = NULL;
3333408Swyllys 	CK_ULONG wrapped_privkey_len = 0;
3343408Swyllys 
3353408Swyllys 	CK_ATTRIBUTE unwrap_tmpl[] = {
3363408Swyllys 		/* code below depends on the following attribute order */
3373408Swyllys 		{CKA_TOKEN, &false, sizeof (false)},
3383408Swyllys 		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
3393408Swyllys 		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
3403408Swyllys 		{CKA_SENSITIVE, &false, sizeof (false)},
3413408Swyllys 		{CKA_PRIVATE, &false, sizeof (false)},
3423408Swyllys 		{CKA_LABEL, NULL, 0}
3433408Swyllys 	};
3443408Swyllys 
3453408Swyllys 	/*
3463408Swyllys 	 * Create a wrap key with random data.
3473408Swyllys 	 */
3483408Swyllys 	fd = open("/dev/urandom", O_RDONLY);
3493408Swyllys 	if (fd == -1) {
3503408Swyllys 		perror("Error reading /dev/urandom");
3513408Swyllys 		return (KMF_ERR_INTERNAL);
3523408Swyllys 	}
3533408Swyllys 	if (read(fd, aes_key_val, sizeof (aes_key_val)) !=
3545051Swyllys 	    sizeof (aes_key_val)) {
3553408Swyllys 		perror("Error reading from /dev/urandom");
3563408Swyllys 		(void) close(fd);
3573408Swyllys 		return (KMF_ERR_INTERNAL);
3583408Swyllys 	}
3593408Swyllys 	(void) close(fd);
3603408Swyllys 
3615051Swyllys 	pk11session = kmf_get_pk11_handle(kmfh);
3623408Swyllys 
3633408Swyllys 	/*
3643408Swyllys 	 * Login to create the wrap key stuff.
3653408Swyllys 	 */
3663408Swyllys 	ckrv = C_Login(pk11session, CKU_USER,
3675051Swyllys 	    (CK_UTF8CHAR_PTR)creds->cred, creds->credlen);
3683408Swyllys 	if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) {
3693408Swyllys 		(void) fprintf(stderr,
3705051Swyllys 		    "Cannot login to the token. error = %s\n",
3715051Swyllys 		    pkcs11_strerror(ckrv));
3723408Swyllys 		return (KMF_ERR_INTERNAL);
3733408Swyllys 	}
3743408Swyllys 
3753408Swyllys 	/*
3763408Swyllys 	 * Turn the random key into a PKCS#11 session object.
3773408Swyllys 	 */
3783408Swyllys 	ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val,
3795051Swyllys 	    sizeof (aes_key_val), &aes_key_obj);
3803408Swyllys 	if (ckrv != CKR_OK) {
3813408Swyllys 		(void) fprintf(stderr,
3825051Swyllys 		    "Cannot create wrapping key. error = %s\n",
3835051Swyllys 		    pkcs11_strerror(ckrv));
3843408Swyllys 		return (KMF_ERR_INTERNAL);
3853408Swyllys 	}
3863408Swyllys 
3873408Swyllys 	/*
3883408Swyllys 	 * Find the original private key that we are going to wrap.
3893408Swyllys 	 */
3905051Swyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
3915051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
3925051Swyllys 	    &kstype, sizeof (kstype));
3935051Swyllys 	numattr++;
3945051Swyllys 
3955051Swyllys 	kclass = KMF_ASYM_PRI;
3965051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
3975051Swyllys 	    &kclass, sizeof (kclass));
3985051Swyllys 	numattr++;
3995051Swyllys 
4005051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
4015051Swyllys 	    creds, sizeof (KMF_CREDENTIAL));
4025051Swyllys 	numattr++;
4035051Swyllys 
4045051Swyllys 	if (keylabel) {
4055051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
4065051Swyllys 		    keylabel, strlen(keylabel));
4075051Swyllys 		numattr++;
4085051Swyllys 	}
4095051Swyllys 	if (idstr) {
4105051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
4115051Swyllys 		    idstr, strlen(idstr));
4125051Swyllys 		numattr++;
4135051Swyllys 	}
4145051Swyllys 	format = KMF_FORMAT_NATIVE;
4155051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
4165051Swyllys 	    &format, sizeof (format));
4175051Swyllys 	numattr++;
4185051Swyllys 
4195051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
4205051Swyllys 	    &kmftrue, sizeof (kmftrue));
4215051Swyllys 	numattr++;
4225051Swyllys 
4235051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
4245051Swyllys 	    &kmftrue, sizeof (kmftrue));
4255051Swyllys 	numattr++;
4265051Swyllys 
4275051Swyllys 	nkeys = 1;
4285051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
4295051Swyllys 	    &nkeys, sizeof (nkeys));
4305051Swyllys 	numattr++;
4315051Swyllys 
4325051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
4335051Swyllys 	    key, sizeof (KMF_KEY_HANDLE));
4345051Swyllys 	numattr++;
4355051Swyllys 
4365051Swyllys 	rv = kmf_find_key(kmfh, numattr, attrlist);
4373408Swyllys 	if (rv != KMF_OK) {
4383408Swyllys 		REPORT_KMF_ERROR(rv, "Error finding private key", err);
4393408Swyllys 		goto out;
4403408Swyllys 	}
4413408Swyllys 
4423408Swyllys 	/*
4433408Swyllys 	 * Get the size of the wrapped private key.
4443408Swyllys 	 */
4453408Swyllys 	bzero(aes_param, sizeof (aes_param));
4463408Swyllys 	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
4475051Swyllys 	    aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
4485051Swyllys 	    NULL, &wrapped_privkey_len);
4493408Swyllys 	if (ckrv != CKR_OK) {
4503408Swyllys 		/*
4513408Swyllys 		 * Most common error here is that the token doesn't
4523408Swyllys 		 * support the wrapping mechanism or the key is
4533408Swyllys 		 * marked non-extractable.  Return an error and let
4543408Swyllys 		 * the caller deal with it gracefully.
4553408Swyllys 		 */
4563408Swyllys 		(void) fprintf(stderr,
4575051Swyllys 		    "Cannot get wrap key size. error = %s\n",
4585051Swyllys 		    pkcs11_strerror(ckrv));
4593408Swyllys 		rv = KMF_ERR_INTERNAL;
4603408Swyllys 		goto out;
4613408Swyllys 	}
4623408Swyllys 	wrapped_privkey = malloc(wrapped_privkey_len);
4633408Swyllys 	if (wrapped_privkey == NULL) {
4643408Swyllys 		rv = KMF_ERR_MEMORY;
4653408Swyllys 		goto out;
4663408Swyllys 	}
4673408Swyllys 	/*
4683408Swyllys 	 * Now get the actual wrapped key data.
4693408Swyllys 	 */
4703408Swyllys 	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
4715051Swyllys 	    aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
4725051Swyllys 	    wrapped_privkey, &wrapped_privkey_len);
4733408Swyllys 	if (ckrv != CKR_OK) {
4743408Swyllys 		(void) fprintf(stderr,
4755051Swyllys 		    "Cannot wrap private key. error = %s\n",
4765051Swyllys 		    pkcs11_strerror(ckrv));
4773408Swyllys 		rv = KMF_ERR_INTERNAL;
4783408Swyllys 		goto out;
4793408Swyllys 	}
4803408Swyllys 	/*
4813408Swyllys 	 * Create a label for the wrapped session key so we can find
4823408Swyllys 	 * it easier later.
4833408Swyllys 	 */
48410520SBhargava.Yenduri@Sun.COM 	(void) snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d",
4855051Swyllys 	    getpid());
4863408Swyllys 
4873408Swyllys 	unwrap_tmpl[5].pValue = wrapkey_label;
4883408Swyllys 	unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label);
4893408Swyllys 
4903408Swyllys 	/*
4913408Swyllys 	 * Unwrap the key into the template and create a temporary
4923408Swyllys 	 * session private key.
4933408Swyllys 	 */
4943408Swyllys 	ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj,
4955051Swyllys 	    wrapped_privkey, wrapped_privkey_len,
4965051Swyllys 	    unwrap_tmpl, 6, &sess_privkey_obj);
4973408Swyllys 	if (ckrv != CKR_OK) {
4983408Swyllys 		(void) fprintf(stderr,
4995051Swyllys 		    "Cannot unwrap private key. error = %s\n",
5005051Swyllys 		    pkcs11_strerror(ckrv));
5013408Swyllys 		rv = KMF_ERR_INTERNAL;
5023408Swyllys 		goto out;
5033408Swyllys 	}
5043408Swyllys 
5053408Swyllys 	/*
5063408Swyllys 	 * Use KMF to find the session key and return it as RAW data
5073408Swyllys 	 * so we can pass it along to KSSL.
5083408Swyllys 	 */
5095051Swyllys 	kclass = KMF_ASYM_PRI;
5105051Swyllys 	if ((idx = kmf_find_attr(KMF_KEYCLASS_ATTR, attrlist, numattr)) != -1) {
5115051Swyllys 		attrlist[idx].pValue = &kclass;
5125051Swyllys 	}
5135051Swyllys 
5145051Swyllys 	format = KMF_FORMAT_RAWKEY;
5155051Swyllys 	if ((idx = kmf_find_attr(KMF_ENCODE_FORMAT_ATTR, attrlist,
5165051Swyllys 	    numattr)) != -1) {
5175051Swyllys 		attrlist[idx].pValue = &format;
5185051Swyllys 	}
5195051Swyllys 	if (wrapkey_label != NULL &&
5205051Swyllys 	    (idx = kmf_find_attr(KMF_KEYLABEL_ATTR, attrlist, numattr)) != -1) {
5215051Swyllys 		attrlist[idx].pValue = wrapkey_label;
5225051Swyllys 		attrlist[idx].valueLen = strlen(wrapkey_label);
5235051Swyllys 	}
5243408Swyllys 
5255051Swyllys 	if ((idx = kmf_find_attr(KMF_PRIVATE_BOOL_ATTR, attrlist,
5265051Swyllys 	    numattr)) != -1) {
5275051Swyllys 		attrlist[idx].pValue = &kmffalse;
5285051Swyllys 	}
5295051Swyllys 	if ((idx = kmf_find_attr(KMF_TOKEN_BOOL_ATTR, attrlist,
5305051Swyllys 	    numattr)) != -1) {
5315051Swyllys 		attrlist[idx].pValue = &kmffalse;
5325051Swyllys 	}
5335051Swyllys 
5345051Swyllys 	if ((idx = kmf_find_attr(KMF_KEY_HANDLE_ATTR, attrlist,
5355051Swyllys 	    numattr)) != -1) {
5365051Swyllys 		attrlist[idx].pValue = rawkey;
5375051Swyllys 	}
5385051Swyllys 	/*
5395051Swyllys 	 * Clear the IDSTR attribute since it is not part of the
5405051Swyllys 	 * wrapped session key.
5415051Swyllys 	 */
5425051Swyllys 	if ((idx = kmf_find_attr(KMF_IDSTR_ATTR, attrlist,
5435051Swyllys 	    numattr)) != -1) {
5445051Swyllys 		attrlist[idx].pValue = NULL;
5455051Swyllys 		attrlist[idx].valueLen = 0;
5465051Swyllys 	}
5475051Swyllys 
5485051Swyllys 	/* The wrapped key should not be sensitive. */
5495051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_SENSITIVE_BOOL_ATTR,
5505051Swyllys 	    &false, sizeof (false));
5515051Swyllys 	numattr++;
5525051Swyllys 
5535051Swyllys 	rv = kmf_find_key(kmfh, numattr, attrlist);
5543408Swyllys 	if (rv != KMF_OK) {
5553408Swyllys 		REPORT_KMF_ERROR(rv, "Error finding raw private key", err);
5563408Swyllys 		goto out;
5573408Swyllys 	}
5583408Swyllys out:
5593408Swyllys 	if (wrapped_privkey)
5603408Swyllys 		free(wrapped_privkey);
5613408Swyllys 
5623408Swyllys 	if (aes_key_obj != CK_INVALID_HANDLE)
56310520SBhargava.Yenduri@Sun.COM 		(void) C_DestroyObject(pk11session, aes_key_obj);
5643408Swyllys 
5653408Swyllys 	if (sess_privkey_obj != CK_INVALID_HANDLE)
56610520SBhargava.Yenduri@Sun.COM 		(void) C_DestroyObject(pk11session, sess_privkey_obj);
5673408Swyllys 
5683408Swyllys 	return (rv);
5693408Swyllys }
5703408Swyllys 
5713408Swyllys static kssl_params_t *
load_from_pkcs11(KMF_HANDLE_T kmfh,const char * token_label,const char * password_file,const char * certname,int * bufsize)5725536Swyllys load_from_pkcs11(KMF_HANDLE_T kmfh,
5735536Swyllys     const char *token_label, const char *password_file,
5743408Swyllys     const char *certname, int *bufsize)
5753408Swyllys {
5763408Swyllys 	KMF_RETURN rv;
5773408Swyllys 	KMF_X509_DER_CERT cert;
5783408Swyllys 	KMF_KEY_HANDLE key, rawkey;
5793408Swyllys 	KMF_CREDENTIAL creds;
5803408Swyllys 	KMF_DATA iddata = { NULL, 0 };
5813408Swyllys 	kssl_params_t *kssl_params = NULL;
5823408Swyllys 	uint32_t ncerts, nkeys;
5833408Swyllys 	char *err, *idstr = NULL;
5843408Swyllys 	char password_buf[1024];
5853408Swyllys 	int nxkey = 0;
5865051Swyllys 	int numattr = 0;
5875051Swyllys 	KMF_ATTRIBUTE attrlist[16];
5885051Swyllys 	KMF_KEYSTORE_TYPE kstype;
5895051Swyllys 	KMF_KEY_CLASS kclass;
5905051Swyllys 	KMF_ENCODE_FORMAT format;
5915051Swyllys 	boolean_t false = B_FALSE;
5925051Swyllys 	boolean_t true = B_TRUE;
5933408Swyllys 
5943408Swyllys 	if (get_passphrase(password_file, password_buf,
5955051Swyllys 	    sizeof (password_buf)) <= 0) {
5963408Swyllys 		perror("Unable to read passphrase");
5973408Swyllys 		goto done;
5983408Swyllys 	}
5993408Swyllys 	creds.cred = password_buf;
6003408Swyllys 	creds.credlen = strlen(password_buf);
6013408Swyllys 
6025051Swyllys 	(void) memset(&key, 0, sizeof (KMF_KEY_HANDLE));
6035051Swyllys 	(void) memset(&rawkey, 0, sizeof (KMF_KEY_HANDLE));
6045051Swyllys 
6055051Swyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
6065051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6075051Swyllys 	    &kstype, sizeof (kstype));
6085051Swyllys 	numattr++;
6093408Swyllys 
6105051Swyllys 	if (token_label && strlen(token_label)) {
6115051Swyllys 		kmf_set_attr_at_index(attrlist, numattr,
6125051Swyllys 		    KMF_TOKEN_LABEL_ATTR,
6135051Swyllys 		    (void *)token_label, strlen(token_label));
6145051Swyllys 		numattr++;
6155051Swyllys 	}
6163408Swyllys 
6175051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_READONLY_ATTR,
6185051Swyllys 	    &false, sizeof (false));
6195051Swyllys 	numattr++;
6205051Swyllys 
6215051Swyllys 	rv = kmf_configure_keystore(kmfh, numattr, attrlist);
6223408Swyllys 	if (rv != KMF_OK) {
6233408Swyllys 		REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err);
6243408Swyllys 		goto done;
6253408Swyllys 	}
6263408Swyllys 
6273408Swyllys 	/*
6283408Swyllys 	 * Find the certificate matching the given label.
6293408Swyllys 	 */
6305051Swyllys 	numattr = 0;
6315051Swyllys 	kstype = KMF_KEYSTORE_PK11TOKEN;
6325051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
6335051Swyllys 	    &kstype, sizeof (kstype));
6345051Swyllys 	numattr++;
6355051Swyllys 
6365051Swyllys 	if (certname) {
6375051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_LABEL_ATTR,
6385051Swyllys 		    (void *)certname, strlen(certname));
6395051Swyllys 		numattr++;
6405051Swyllys 	}
6415051Swyllys 	ncerts = 1;
6425051Swyllys 
6435051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
6445051Swyllys 	    &ncerts, sizeof (ncerts));
6455051Swyllys 	numattr++;
6465051Swyllys 
6475051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
6485051Swyllys 	    &cert, sizeof (cert));
6495051Swyllys 	numattr++;
6505051Swyllys 
6515051Swyllys 	rv = kmf_find_cert(kmfh, numattr, attrlist);
6523408Swyllys 	if (rv != KMF_OK || ncerts == 0)
6533408Swyllys 		goto done;
6543408Swyllys 
6553408Swyllys 	/*
6563408Swyllys 	 * Find the associated private key for this cert by
6573408Swyllys 	 * keying off of the label and the ASCII ID string.
6583408Swyllys 	 */
6595051Swyllys 	rv = kmf_get_cert_id_str(&cert.certificate, &idstr);
6603408Swyllys 	if (rv != KMF_OK)
6613408Swyllys 		goto done;
6623408Swyllys 
6635051Swyllys 	numattr = 1; /* attrlist[0] is already set to kstype */
6645051Swyllys 
6655051Swyllys 	kclass = KMF_ASYM_PRI;
6665051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYCLASS_ATTR,
6675051Swyllys 	    &kclass, sizeof (kclass));
6685051Swyllys 	numattr++;
6695051Swyllys 
6705051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CREDENTIAL_ATTR,
6715051Swyllys 	    &creds, sizeof (KMF_CREDENTIAL));
6725051Swyllys 	numattr++;
6735051Swyllys 
6745051Swyllys 	format = KMF_FORMAT_RAWKEY;
6755051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_ENCODE_FORMAT_ATTR,
6765051Swyllys 	    &format, sizeof (format));
6775051Swyllys 	numattr++;
6783408Swyllys 
6795051Swyllys 	if (certname) {
6805051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_KEYLABEL_ATTR,
6815051Swyllys 		    (void *)certname, strlen(certname));
6825051Swyllys 		numattr++;
6835051Swyllys 	}
6845051Swyllys 	if (idstr) {
6855051Swyllys 		kmf_set_attr_at_index(attrlist, numattr, KMF_IDSTR_ATTR,
6865051Swyllys 		    (void *)idstr, strlen(idstr));
6875051Swyllys 		numattr++;
6885051Swyllys 	}
6895051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_TOKEN_BOOL_ATTR,
6905051Swyllys 	    &true, sizeof (true));
6915051Swyllys 	numattr++;
6925051Swyllys 
6935051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_PRIVATE_BOOL_ATTR,
6945051Swyllys 	    &true, sizeof (true));
6955051Swyllys 	numattr++;
6965051Swyllys 
6975051Swyllys 	/* We only expect to find 1 key at most */
6985051Swyllys 	nkeys = 1;
6995051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
7005051Swyllys 	    &nkeys, sizeof (nkeys));
7015051Swyllys 	numattr++;
7025051Swyllys 
7035051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEY_HANDLE_ATTR,
7045051Swyllys 	    &key, sizeof (KMF_KEY_HANDLE));
7055051Swyllys 	numattr++;
7065051Swyllys 
7075051Swyllys 	rv = kmf_find_key(kmfh, numattr, attrlist);
7083408Swyllys 	if (rv == KMF_ERR_SENSITIVE_KEY) {
7095051Swyllys 		kmf_free_kmf_key(kmfh, &key);
7103408Swyllys 		/*
7113408Swyllys 		 * Get a normal key handle and then do a wrap/unwrap
7123408Swyllys 		 * in order to get the necessary raw data fields needed
7133408Swyllys 		 * to send to KSSL.
7143408Swyllys 		 */
7155051Swyllys 		format = KMF_FORMAT_NATIVE;
7165051Swyllys 		rv = get_sensitive_key_data(kmfh, &creds,
7175051Swyllys 		    (char *)certname, idstr, &key, &rawkey);
7183408Swyllys 		if (rv == KMF_OK) {
7193408Swyllys 			/* Swap "key" for "rawkey" */
7205051Swyllys 			kmf_free_kmf_key(kmfh, &key);
7213408Swyllys 
7223408Swyllys 			key = rawkey;
7233408Swyllys 		} else {
7245051Swyllys 			kmf_free_kmf_key(kmfh, &key);
7253408Swyllys 
7263408Swyllys 			/* Let kssl try to find the key. */
7273408Swyllys 			nxkey = 1;
7285051Swyllys 			rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
7293408Swyllys 		}
7303408Swyllys 	} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
7315051Swyllys 		kmf_free_kmf_key(kmfh, &key);
7323408Swyllys 
7335051Swyllys 		/* Let kssl try to find the key. */
7345051Swyllys 		nxkey = 1;
7355051Swyllys 		rv = kmf_get_cert_id_data(&cert.certificate, &iddata);
7363408Swyllys 	} else if (rv != KMF_OK || nkeys == 0)
7373408Swyllys 		goto done;
7383408Swyllys 
7393408Swyllys 	if (rv == KMF_OK)
7403408Swyllys 		kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp,
7415536Swyllys 		    1, &cert, bufsize, (char *)token_label, &iddata, &creds);
7423408Swyllys done:
7433408Swyllys 	if (ncerts != 0)
7445051Swyllys 		kmf_free_kmf_cert(kmfh, &cert);
7453408Swyllys 	if (nkeys != 0)
7465051Swyllys 		kmf_free_kmf_key(kmfh, &key);
7473408Swyllys 	if (idstr)
7483408Swyllys 		free(idstr);
7493408Swyllys 
7503408Swyllys 	return (kssl_params);
7513408Swyllys }
7523408Swyllys 
7533408Swyllys /*
7543408Swyllys  * add_cacerts
7553408Swyllys  *
7563408Swyllys  * Load a chain of certificates from a PEM file.
7573408Swyllys  */
7583408Swyllys static kssl_params_t *
add_cacerts(KMF_HANDLE_T kmfh,kssl_params_t * old_params,const char * cacert_chain_file)7595536Swyllys add_cacerts(KMF_HANDLE_T kmfh,
7605536Swyllys 	kssl_params_t *old_params, const char *cacert_chain_file)
7613408Swyllys {
7623408Swyllys 	int i, newlen;
7633408Swyllys 	uint32_t certlen = 0, ncerts;
7641933Skrishna 	char *buf;
7653408Swyllys 	KMF_RETURN rv;
7663408Swyllys 	KMF_X509_DER_CERT *certs = NULL;
7671933Skrishna 	kssl_params_t *kssl_params;
7683408Swyllys 	char *err = NULL;
7695051Swyllys 	int numattr = 0;
7705051Swyllys 	KMF_ATTRIBUTE attrlist[16];
7715051Swyllys 	KMF_KEYSTORE_TYPE kstype = KMF_KEYSTORE_OPENSSL;
7723408Swyllys 
7735051Swyllys 	kstype = KMF_KEYSTORE_OPENSSL;
7741933Skrishna 
7755051Swyllys 	ncerts = 0;
7765051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_KEYSTORE_TYPE_ATTR,
7775051Swyllys 	    &kstype, sizeof (KMF_KEYSTORE_TYPE));
7785051Swyllys 	numattr++;
7795051Swyllys 
7805051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_CERT_FILENAME_ATTR,
7815051Swyllys 	    (void *)cacert_chain_file, strlen(cacert_chain_file));
7825051Swyllys 	numattr++;
7835051Swyllys 
7845051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_COUNT_ATTR,
7855051Swyllys 	    &ncerts, sizeof (ncerts));
7865051Swyllys 	numattr++;
7875051Swyllys 
7885051Swyllys 	rv = kmf_find_cert(kmfh, numattr, attrlist);
7893408Swyllys 	if (rv != KMF_OK) {
7903408Swyllys 		REPORT_KMF_ERROR(rv, "Error finding CA certificates", err);
7913408Swyllys 		return (0);
7923408Swyllys 	}
7933408Swyllys 	certs = (KMF_X509_DER_CERT *)malloc(ncerts *
7945051Swyllys 	    sizeof (KMF_X509_DER_CERT));
7953408Swyllys 	if (certs == NULL) {
7963408Swyllys 		(void) fprintf(stderr, "memory allocation error.\n");
7973408Swyllys 		return (NULL);
7983408Swyllys 	}
7993408Swyllys 	bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT));
8003408Swyllys 
8015051Swyllys 	/* add new attribute for the cert list to be returned */
8025051Swyllys 	kmf_set_attr_at_index(attrlist, numattr, KMF_X509_DER_CERT_ATTR,
8035051Swyllys 	    certs, (ncerts * sizeof (KMF_X509_DER_CERT)));
8045051Swyllys 	numattr++;
8055051Swyllys 	rv = kmf_find_cert(kmfh, numattr, attrlist);
8065051Swyllys 
8073408Swyllys 	if (rv != KMF_OK || ncerts == 0) {
8082800Skrishna 		bzero(old_params, old_params->kssl_params_size);
8091933Skrishna 		free(old_params);
8101933Skrishna 		return (NULL);
8111933Skrishna 	}
8121933Skrishna 
8131933Skrishna 	if (verbose) {
8141933Skrishna 		(void) printf("%d certificates read successfully\n", ncerts);
8151933Skrishna 	}
8161933Skrishna 
8171933Skrishna 	newlen = old_params->kssl_params_size;
8181933Skrishna 	for (i = 0; i < ncerts; i++)
8193408Swyllys 		newlen += certs[i].certificate.Length;
8201933Skrishna 
8211933Skrishna 	/*
8221933Skrishna 	 * Get a bigger structure and update the
8231933Skrishna 	 * fields to account for the additional certs.
8241933Skrishna 	 */
8251933Skrishna 	kssl_params = realloc(old_params, newlen);
8261933Skrishna 
8271933Skrishna 	kssl_params->kssl_params_size = newlen;
8281933Skrishna 	kssl_params->kssl_certs.sc_count += ncerts;
8291933Skrishna 
8303408Swyllys 	/* Put the cert size info starting from sc_sizes[1] */
8311933Skrishna 	buf = (char *)kssl_params;
8321933Skrishna 	buf += kssl_params->kssl_certs.sc_sizes_offset;
8331933Skrishna 	bcopy(buf, &certlen, sizeof (uint32_t));
8341933Skrishna 	buf += sizeof (uint32_t);
8353408Swyllys 	for (i = 0; i < ncerts; i++) {
8363408Swyllys 		uint32_t size = (uint32_t)certs[i].certificate.Length;
8373408Swyllys 		bcopy(&size, buf, sizeof (uint32_t));
8383408Swyllys 		buf += sizeof (uint32_t);
8393408Swyllys 	}
8401933Skrishna 
8411933Skrishna 	/* Put the cert_bufs starting from sc_certs[1] */
8421933Skrishna 	buf = (char *)kssl_params;
8431933Skrishna 	buf += kssl_params->kssl_certs.sc_certs_offset;
8441933Skrishna 	buf += certlen;
8451933Skrishna 
8461933Skrishna 	/* now the certs values */
8471933Skrishna 	for (i = 0; i < ncerts; i++) {
8483408Swyllys 		bcopy(certs[i].certificate.Data, buf,
8495051Swyllys 		    certs[i].certificate.Length);
8503408Swyllys 		buf += certs[i].certificate.Length;
8511933Skrishna 	}
8521933Skrishna 
8531933Skrishna 	for (i = 0; i < ncerts; i++)
8545051Swyllys 		kmf_free_kmf_cert(kmfh, &certs[i]);
8553408Swyllys 	free(certs);
8561933Skrishna 
8571933Skrishna 	return (kssl_params);
8581933Skrishna }
8591933Skrishna 
8603408Swyllys /*
8613408Swyllys  * Find a key and certificate(s) from a single PEM file.
8623408Swyllys  */
8631933Skrishna static kssl_params_t *
load_from_pem(KMF_HANDLE_T kmfh,const char * filename,const char * password_file,int * paramsize)8645536Swyllys load_from_pem(KMF_HANDLE_T kmfh, const char *filename,
8655536Swyllys 	const char *password_file, int *paramsize)
866898Skais {
8673408Swyllys 	int ncerts = 0, i;
868898Skais 	kssl_params_t *kssl_params;
8693408Swyllys 	KMF_RAW_KEY_DATA *rsa = NULL;
8705536Swyllys 	KMF_X509_DER_CERT *certs = NULL;
871898Skais 
8725536Swyllys 	ncerts = PEM_get_rsa_key_certs(kmfh,
8735536Swyllys 	    filename, (char *)password_file, &rsa, &certs);
8743408Swyllys 	if (rsa == NULL || certs == NULL || ncerts == 0) {
875898Skais 		return (NULL);
876898Skais 	}
877898Skais 
878898Skais 	if (verbose)
8791933Skrishna 		(void) printf("%d certificates read successfully\n", ncerts);
880898Skais 
8813408Swyllys 	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
8825051Swyllys 	    NULL, NULL);
883898Skais 
8841933Skrishna 	for (i = 0; i < ncerts; i++)
8855536Swyllys 		kmf_free_kmf_cert(kmfh, &certs[i]);
8863408Swyllys 	free(certs);
8875051Swyllys 	kmf_free_raw_key(rsa);
8883408Swyllys 
889898Skais 	return (kssl_params);
890898Skais }
891898Skais 
8923408Swyllys /*
8933408Swyllys  * Load a raw key and certificate(s) from a PKCS#12 file.
8943408Swyllys  */
8951933Skrishna static kssl_params_t *
load_from_pkcs12(KMF_HANDLE_T kmfh,const char * filename,const char * password_file,int * paramsize)8965536Swyllys load_from_pkcs12(KMF_HANDLE_T kmfh, const char *filename,
8975536Swyllys     const char *password_file, int *paramsize)
898898Skais {
8993408Swyllys 	KMF_RAW_KEY_DATA *rsa = NULL;
900898Skais 	kssl_params_t *kssl_params;
9015536Swyllys 	KMF_X509_DER_CERT *certs = NULL;
9023408Swyllys 	int ncerts = 0, i;
903898Skais 
9045536Swyllys 	ncerts = PKCS12_get_rsa_key_certs(kmfh, filename,
9055051Swyllys 	    password_file, &rsa, &certs);
9063408Swyllys 
9073408Swyllys 	if (certs == NULL || ncerts == 0) {
908898Skais 		(void) fprintf(stderr,
909898Skais 		    "Unable to read cert and/or key from %s\n", filename);
910898Skais 		return (NULL);
911898Skais 	}
912898Skais 
913898Skais 	if (verbose)
9141933Skrishna 		(void) printf("%d certificates read successfully\n", ncerts);
9151933Skrishna 
9163408Swyllys 	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
9175051Swyllys 	    NULL, NULL);
918898Skais 
9191933Skrishna 	for (i = 0; i < ncerts; i++)
9205536Swyllys 		kmf_free_kmf_cert(kmfh, &certs[i]);
9213408Swyllys 	free(certs);
922898Skais 
9235051Swyllys 	kmf_free_raw_key(rsa);
924898Skais 	return (kssl_params);
925898Skais }
926898Skais 
927898Skais int
parse_and_set_addr(char * server_address,char * server_port,struct sockaddr_in6 * addr)928898Skais parse_and_set_addr(char *server_address, char *server_port,
92910520SBhargava.Yenduri@Sun.COM     struct sockaddr_in6 *addr)
930898Skais {
931*12381SVladimir.Kotal@Sun.COM 	long long tmp_port;
932*12381SVladimir.Kotal@Sun.COM 	char *ep;
933*12381SVladimir.Kotal@Sun.COM 
934898Skais 	if (server_port == NULL) {
935898Skais 		return (-1);
936898Skais 	}
937898Skais 
938898Skais 	if (server_address == NULL) {
93910520SBhargava.Yenduri@Sun.COM 		addr->sin6_addr = in6addr_any;
940898Skais 	} else {
94110520SBhargava.Yenduri@Sun.COM 		struct hostent *hp;
94210520SBhargava.Yenduri@Sun.COM 		int error_num;
943898Skais 
94410520SBhargava.Yenduri@Sun.COM 		if ((hp = (getipnodebyname(server_address, AF_INET6,
94510520SBhargava.Yenduri@Sun.COM 		    AI_DEFAULT, &error_num))) == NULL) {
94610520SBhargava.Yenduri@Sun.COM 			(void) fprintf(stderr, "Error: Unknown host: %s\n",
94710520SBhargava.Yenduri@Sun.COM 			    server_address);
94810520SBhargava.Yenduri@Sun.COM 			return (-1);
94910520SBhargava.Yenduri@Sun.COM 		}
950898Skais 
95110520SBhargava.Yenduri@Sun.COM 		(void) memcpy((caddr_t)&addr->sin6_addr, hp->h_addr,
95210520SBhargava.Yenduri@Sun.COM 		    hp->h_length);
95310520SBhargava.Yenduri@Sun.COM 		freehostent(hp);
954898Skais 	}
955898Skais 
956898Skais 	errno = 0;
957*12381SVladimir.Kotal@Sun.COM 	tmp_port = strtoll(server_port, &ep, 10);
958*12381SVladimir.Kotal@Sun.COM 	if (server_port == ep || *ep != '\0' || errno != 0) {
959898Skais 		(void) fprintf(stderr, "Error: Invalid Port value: %s\n",
960898Skais 		    server_port);
961898Skais 		return (-1);
962898Skais 	}
963*12381SVladimir.Kotal@Sun.COM 	if (tmp_port < 1 || tmp_port > 65535) {
964*12381SVladimir.Kotal@Sun.COM 		(void) fprintf(stderr, "Error: Port out of range: %s\n",
965*12381SVladimir.Kotal@Sun.COM 		    server_port);
966*12381SVladimir.Kotal@Sun.COM 		return (-1);
967*12381SVladimir.Kotal@Sun.COM 	}
968*12381SVladimir.Kotal@Sun.COM 	/* It is safe to convert since the value is inside the boundaries. */
969*12381SVladimir.Kotal@Sun.COM 	addr->sin6_port = tmp_port;
970898Skais 
971898Skais 	return (0);
972898Skais }
973898Skais 
974898Skais /*
975898Skais  * The order of the ciphers is important. It is used as the
976898Skais  * default order (when -c is not specified).
977898Skais  */
978898Skais struct csuite {
979898Skais 	const char *suite;
980898Skais 	uint16_t val;
981898Skais 	boolean_t seen;
982898Skais } cipher_suites[CIPHER_SUITE_COUNT - 1] = {
983898Skais 	{"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE},
984898Skais 	{"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE},
9856788Skrishna 	{"rsa_aes_256_cbc_sha", TLS_RSA_WITH_AES_256_CBC_SHA, B_FALSE},
9866788Skrishna 	{"rsa_aes_128_cbc_sha", TLS_RSA_WITH_AES_128_CBC_SHA, B_FALSE},
987898Skais 	{"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE},
988898Skais 	{"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE},
989898Skais };
990898Skais 
9911933Skrishna static int
check_suites(char * suites,uint16_t * sarray)992898Skais check_suites(char *suites, uint16_t *sarray)
993898Skais {
994898Skais 	int i;
995898Skais 	int err = 0;
996898Skais 	char *suite;
997898Skais 	int sindx = 0;
998898Skais 
999898Skais 	if (suites != NULL) {
1000898Skais 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
1001898Skais 			sarray[i] = CIPHER_NOTSET;
1002898Skais 	} else {
1003898Skais 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
1004898Skais 			sarray[i] = cipher_suites[i].val;
1005898Skais 		return (err);
1006898Skais 	}
1007898Skais 
1008898Skais 	suite = strtok(suites, ",");
1009898Skais 	do {
1010898Skais 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
1011898Skais 			if (strcasecmp(suite, cipher_suites[i].suite) == 0) {
1012898Skais 				if (!cipher_suites[i].seen) {
1013898Skais 					sarray[sindx++] = cipher_suites[i].val;
1014898Skais 					cipher_suites[i].seen = B_TRUE;
1015898Skais 				}
1016898Skais 				break;
1017898Skais 			}
1018898Skais 		}
1019898Skais 
1020898Skais 		if (i == (CIPHER_SUITE_COUNT - 1)) {
1021898Skais 			(void) fprintf(stderr,
1022898Skais 			    "Unknown Cipher suite name: %s\n", suite);
1023898Skais 			err++;
1024898Skais 		}
1025898Skais 	} while ((suite = strtok(NULL, ",")) != NULL);
1026898Skais 
1027898Skais 	return (err);
1028898Skais }
1029898Skais 
1030898Skais int
do_create(int argc,char * argv[])1031898Skais do_create(int argc, char *argv[])
1032898Skais {
1033898Skais 	const char *softtoken_dir = NULL;
1034898Skais 	const char *token_label = NULL;
1035898Skais 	const char *password_file = NULL;
10361933Skrishna 	const char *cert_key_file = NULL;
10371933Skrishna 	const char *cacert_chain_file = NULL;
1038898Skais 	const char *certname = NULL;
1039898Skais 	char *suites = NULL;
1040898Skais 	uint32_t timeout = DEFAULT_SID_TIMEOUT;
1041898Skais 	uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES;
10422800Skrishna 	uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
1043898Skais 	int proxy_port = -1;
104410520SBhargava.Yenduri@Sun.COM 	struct sockaddr_in6 server_addr;
1045898Skais 	char *format = NULL;
1046898Skais 	char *port, *addr;
1047898Skais 	char c;
1048898Skais 	int pcnt;
1049898Skais 	kssl_params_t *kssl_params;
1050898Skais 	int bufsize;
10515536Swyllys 	KMF_HANDLE_T kmfh = NULL;
10525536Swyllys 	KMF_RETURN rv = KMF_OK;
10535536Swyllys 	char *err = NULL;
1054898Skais 
1055898Skais 	argc -= 1;
1056898Skais 	argv += 1;
1057898Skais 
10581933Skrishna 	while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) {
1059898Skais 		switch (c) {
1060898Skais 		case 'd':
1061898Skais 			softtoken_dir = optarg;
1062898Skais 			break;
1063898Skais 		case 'c':
1064898Skais 			suites = optarg;
1065898Skais 			break;
1066898Skais 		case 'C':
1067898Skais 			certname = optarg;
1068898Skais 			break;
1069898Skais 		case 'f':
1070898Skais 			format = optarg;
1071898Skais 			break;
10721933Skrishna 		case 'h':
10731933Skrishna 			cacert_chain_file = optarg;
10741933Skrishna 			break;
1075898Skais 		case 'i':
10761933Skrishna 			cert_key_file = optarg;
1077898Skais 			break;
1078898Skais 		case 'T':
1079898Skais 			token_label = optarg;
1080898Skais 			break;
1081898Skais 		case 'p':
1082898Skais 			password_file = optarg;
1083898Skais 			break;
1084898Skais 		case 't':
1085898Skais 			timeout = atoi(optarg);
1086898Skais 			break;
1087898Skais 		case 'x':
1088898Skais 			proxy_port = atoi(optarg);
1089898Skais 			break;
1090898Skais 		case 'v':
1091898Skais 			verbose = B_TRUE;
1092898Skais 			break;
1093898Skais 		case 'z':
1094898Skais 			scache_size = atoi(optarg);
1095898Skais 			break;
1096898Skais 		default:
1097898Skais 			goto err;
1098898Skais 		}
1099898Skais 	}
1100898Skais 
1101898Skais 	pcnt = argc - optind;
1102898Skais 	if (pcnt == 0) {
1103898Skais 		port = "443";	/* default SSL port */
1104898Skais 		addr = NULL;
1105898Skais 	} else if (pcnt == 1) {
1106898Skais 		port = argv[optind];
1107898Skais 		addr = NULL;
1108898Skais 	} else if (pcnt == 2) {
1109898Skais 		addr = argv[optind];
1110898Skais 		port = argv[optind + 1];
1111898Skais 	} else {
1112898Skais 		goto err;
1113898Skais 	}
1114898Skais 
1115898Skais 	if (parse_and_set_addr(addr, port, &server_addr) < 0) {
1116898Skais 		goto err;
1117898Skais 	}
1118898Skais 
1119898Skais 	if (verbose) {
112010520SBhargava.Yenduri@Sun.COM 		char buffer[128];
112110520SBhargava.Yenduri@Sun.COM 
112210520SBhargava.Yenduri@Sun.COM 		(void) inet_ntop(AF_INET6, &server_addr.sin6_addr, buffer,
112310520SBhargava.Yenduri@Sun.COM 		    sizeof (buffer));
112410520SBhargava.Yenduri@Sun.COM 		(void) printf("addr = %s, port = %d\n", buffer,
112510520SBhargava.Yenduri@Sun.COM 		    server_addr.sin6_port);
1126898Skais 	}
1127898Skais 
1128898Skais 	if (format == NULL || proxy_port == -1) {
1129898Skais 		goto err;
1130898Skais 	}
1131898Skais 
11322800Skrishna 	if (check_suites(suites, kssl_suites) != 0) {
11332800Skrishna 		goto err;
11342800Skrishna 	}
11352800Skrishna 
11365536Swyllys 	rv = kmf_initialize(&kmfh, NULL, NULL);
11375536Swyllys 	if (rv != KMF_OK) {
11385536Swyllys 		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
11395536Swyllys 		return (0);
11405536Swyllys 	}
11415536Swyllys 
1142898Skais 	if (strcmp(format, "pkcs11") == 0) {
1143898Skais 		if (token_label == NULL || certname == NULL) {
1144898Skais 			goto err;
1145898Skais 		}
1146898Skais 		if (softtoken_dir != NULL) {
1147898Skais 			(void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1);
1148898Skais 			if (verbose) {
1149898Skais 				(void) printf(
1150898Skais 				    "SOFTTOKEN_DIR=%s\n",
1151898Skais 				    getenv("SOFTTOKEN_DIR"));
1152898Skais 			}
1153898Skais 		}
11545536Swyllys 		kssl_params = load_from_pkcs11(kmfh,
1155898Skais 		    token_label, password_file, certname, &bufsize);
1156898Skais 	} else if (strcmp(format, "pkcs12") == 0) {
11571933Skrishna 		if (cert_key_file == NULL) {
1158898Skais 			goto err;
1159898Skais 		}
11605536Swyllys 		kssl_params = load_from_pkcs12(kmfh,
11611933Skrishna 		    cert_key_file, password_file, &bufsize);
1162898Skais 	} else if (strcmp(format, "pem") == 0) {
11631933Skrishna 		if (cert_key_file == NULL) {
1164898Skais 			goto err;
1165898Skais 		}
11665536Swyllys 		kssl_params = load_from_pem(kmfh,
11671933Skrishna 		    cert_key_file, password_file, &bufsize);
1168898Skais 	} else {
1169898Skais 		(void) fprintf(stderr, "Unsupported cert format: %s\n", format);
1170898Skais 		goto err;
1171898Skais 	}
1172898Skais 
1173898Skais 	if (kssl_params == NULL) {
11745536Swyllys 		(void) kmf_finalize(kmfh);
1175898Skais 		return (FAILURE);
1176898Skais 	}
1177898Skais 
11783408Swyllys 	/*
11793408Swyllys 	 * Add the list of supported ciphers to the buffer.
11803408Swyllys 	 */
11812800Skrishna 	bcopy(kssl_suites, kssl_params->kssl_suites,
11822800Skrishna 	    sizeof (kssl_params->kssl_suites));
1183898Skais 	kssl_params->kssl_params_size = bufsize;
1184898Skais 	kssl_params->kssl_addr = server_addr;
1185898Skais 	kssl_params->kssl_session_cache_timeout = timeout;
1186898Skais 	kssl_params->kssl_proxy_port = proxy_port;
1187898Skais 	kssl_params->kssl_session_cache_size = scache_size;
1188898Skais 
11891933Skrishna 	if (cacert_chain_file != NULL) {
11905536Swyllys 		kssl_params = add_cacerts(kmfh, kssl_params, cacert_chain_file);
11911933Skrishna 		if (kssl_params == NULL) {
11925536Swyllys 			bzero(kssl_params, bufsize);
11935536Swyllys 			free(kssl_params);
11945536Swyllys 			(void) kmf_finalize(kmfh);
11951933Skrishna 			return (FAILURE);
11961933Skrishna 		}
11971933Skrishna 	}
11981933Skrishna 
1199898Skais 	if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) {
12002800Skrishna 		int err = CRYPTO_FAILED;
12012800Skrishna 
12022800Skrishna 		if (kssl_params->kssl_is_nxkey)
12032800Skrishna 			err = kssl_params->kssl_token.ck_rv;
12042800Skrishna 		(void) fprintf(stderr,
12052800Skrishna 		    "Error loading cert and key: 0x%x\n", err);
12065536Swyllys 		bzero(kssl_params, bufsize);
12075536Swyllys 		free(kssl_params);
12085536Swyllys 		(void) kmf_finalize(kmfh);
1209898Skais 		return (FAILURE);
1210898Skais 	}
1211898Skais 
1212898Skais 	if (verbose)
1213898Skais 		(void) printf("Successfully loaded cert and key\n");
1214898Skais 
12152800Skrishna 	bzero(kssl_params, bufsize);
1216898Skais 	free(kssl_params);
12175536Swyllys 	(void) kmf_finalize(kmfh);
1218898Skais 	return (SUCCESS);
1219898Skais 
1220898Skais err:
1221898Skais 	usage_create(B_TRUE);
12225536Swyllys 	(void) kmf_finalize(kmfh);
1223898Skais 	return (SMF_EXIT_ERR_CONFIG);
1224898Skais }
1225