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 
49 void
50 usage_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  */
90 static kssl_params_t *
91 kmf_to_kssl(int nxkey, KMF_RAW_KEY_DATA *rsa, int ncerts,
92 	KMF_DATA *certs, int *paramsize, char *token_label, KMF_DATA *idstr,
93 	KMF_CREDENTIAL *creds)
94 {
95 	int i, tcsize;
96 	kssl_params_t *kssl_params;
97 	kssl_key_t *key;
98 	char *buf;
99 	uint32_t bufsize;
100 	static CK_BBOOL true = TRUE;
101 	static CK_BBOOL false = FALSE;
102 	static CK_OBJECT_CLASS class = CKO_PRIVATE_KEY;
103 	static CK_KEY_TYPE keytype = CKK_RSA;
104 	kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
105 	CK_ATTRIBUTE exkey_attrs[MAX_ATTR_CNT] = {
106 		{CKA_TOKEN, &true, sizeof (true)},
107 		{CKA_EXTRACTABLE, &false, sizeof (false)},
108 		{CKA_CLASS,	&class, sizeof (class) },
109 		{CKA_KEY_TYPE,	&keytype, sizeof (keytype) },
110 		{CKA_ID,	NULL, 0}
111 	};
112 	kssl_object_attribute_t kssl_tmpl_attrs[MAX_ATTR_CNT] = {
113 		{SUN_CKA_MODULUS, NULL, 0},
114 		{SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
115 		{SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
116 		{SUN_CKA_PRIME_1, NULL, 0},
117 		{SUN_CKA_PRIME_2, NULL, 0},
118 		{SUN_CKA_EXPONENT_1, NULL, 0},
119 		{SUN_CKA_EXPONENT_2, NULL, 0},
120 		{SUN_CKA_COEFFICIENT, NULL, 0}
121 	};
122 	KMF_BIGINT priv_key_bignums[MAX_ATTR_CNT];
123 	int attr_cnt;
124 
125 	if (nxkey && idstr != NULL) {
126 		exkey_attrs[4].pValue = idstr->Data;
127 		exkey_attrs[4].ulValueLen = idstr->Length;
128 	}
129 	tcsize = 0;
130 	for (i = 0; i < ncerts; i++)
131 		tcsize += certs[i].Length;
132 
133 	bufsize = sizeof (kssl_params_t);
134 	bufsize += (tcsize + (MAX_CHAIN_LENGTH * sizeof (uint32_t)));
135 
136 	if (!nxkey) {
137 		bzero(priv_key_bignums, sizeof (KMF_BIGINT) *
138 			MAX_ATTR_CNT);
139 		/* and the key attributes */
140 		priv_key_bignums[0] = rsa->rawdata.rsa.mod;
141 		priv_key_bignums[1] = rsa->rawdata.rsa.pubexp;
142 		priv_key_bignums[2] = rsa->rawdata.rsa.priexp;
143 		priv_key_bignums[3] = rsa->rawdata.rsa.prime1;
144 		priv_key_bignums[4] = rsa->rawdata.rsa.prime2;
145 		priv_key_bignums[5] = rsa->rawdata.rsa.exp1;
146 		priv_key_bignums[6] = rsa->rawdata.rsa.exp2;
147 		priv_key_bignums[7] = rsa->rawdata.rsa.coef;
148 
149 		if (rsa->rawdata.rsa.mod.val == NULL ||
150 			rsa->rawdata.rsa.priexp.val == NULL) {
151 			(void) fprintf(stderr,
152 			    "missing required attributes in private key.\n");
153 			return (NULL);
154 		}
155 
156 		attr_cnt = 0;
157 		for (i = 0; i < MAX_ATTR_CNT; i++) {
158 			if (priv_key_bignums[i].val == NULL)
159 				continue;
160 			kssl_attrs[attr_cnt].ka_type =
161 				kssl_tmpl_attrs[i].ka_type;
162 			kssl_attrs[attr_cnt].ka_value_len =
163 				priv_key_bignums[i].len;
164 			bufsize += sizeof (crypto_object_attribute_t) +
165 			    kssl_attrs[attr_cnt].ka_value_len;
166 			attr_cnt++;
167 		}
168 	} else {
169 		/*
170 		 * Compute space for the attributes and values that the
171 		 * kssl kernel module will need in order to search for
172 		 * the private key.
173 		 */
174 		for (attr_cnt = 0; attr_cnt < 5; attr_cnt++) {
175 			bufsize += sizeof (crypto_object_attribute_t) +
176 				exkey_attrs[attr_cnt].ulValueLen;
177 		}
178 		if (creds)
179 			bufsize += creds->credlen;
180 	}
181 
182 	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
183 	bufsize += sizeof (uint32_t);
184 
185 	/* Now the big memory allocation */
186 	if ((buf = calloc(bufsize, 1)) == NULL) {
187 		(void) fprintf(stderr,
188 		    "Cannot allocate memory for the kssl_params "
189 		    "and values\n");
190 		return (NULL);
191 	}
192 
193 	/* LINTED */
194 	kssl_params = (kssl_params_t *)buf;
195 
196 	buf = (char *)(kssl_params + 1);
197 
198 	if (!nxkey) {
199 		/* the keys attributes structs array */
200 		key = &kssl_params->kssl_privkey;
201 		key->ks_format = CRYPTO_KEY_ATTR_LIST;
202 		key->ks_count = attr_cnt;
203 		key->ks_attrs_offset = buf - (char *)kssl_params;
204 		buf += attr_cnt * sizeof (kssl_object_attribute_t);
205 
206 		attr_cnt = 0;
207 		/* then the key attributes values */
208 		for (i = 0; i < MAX_ATTR_CNT; i++) {
209 			if (priv_key_bignums[i].val == NULL)
210 				continue;
211 			(void) memcpy(buf, priv_key_bignums[i].val,
212 				priv_key_bignums[i].len);
213 			kssl_attrs[attr_cnt].ka_value_offset =
214 			    buf - (char *)kssl_params;
215 			buf += kssl_attrs[attr_cnt].ka_value_len;
216 			attr_cnt++;
217 		}
218 	} else {
219 		char tlabel[CRYPTO_EXT_SIZE_LABEL];
220 		bzero(tlabel, sizeof (tlabel));
221 		(void) strlcpy(tlabel, token_label, sizeof (tlabel));
222 
223 		/*
224 		 * For a non-extractable key, we must provide the PIN
225 		 * so the kssl module can access the token to find
226 		 * the key handle.
227 		 */
228 		kssl_params->kssl_is_nxkey = 1;
229 		bcopy(tlabel, kssl_params->kssl_token.toklabel,
230 			CRYPTO_EXT_SIZE_LABEL);
231 		kssl_params->kssl_token.pinlen = creds->credlen;
232 		kssl_params->kssl_token.tokpin_offset =
233 			buf - (char *)kssl_params;
234 		kssl_params->kssl_token.ck_rv = 0;
235 		bcopy(creds->cred, buf, creds->credlen);
236 		buf += creds->credlen;
237 
238 		/*
239 		 * Next in the buffer, we must provide the attributes
240 		 * that the kssl module will use to search in the
241 		 * token to find the protected key handle.
242 		 */
243 		key = &kssl_params->kssl_privkey;
244 		key->ks_format = CRYPTO_KEY_ATTR_LIST;
245 		key->ks_count = attr_cnt;
246 		key->ks_attrs_offset = buf - (char *)kssl_params;
247 
248 		buf += attr_cnt * sizeof (kssl_object_attribute_t);
249 		for (i = 0; i < attr_cnt; i++) {
250 			bcopy(exkey_attrs[i].pValue, buf,
251 				exkey_attrs[i].ulValueLen);
252 
253 			kssl_attrs[i].ka_type = exkey_attrs[i].type;
254 			kssl_attrs[i].ka_value_offset =
255 				buf - (char *)kssl_params;
256 			kssl_attrs[i].ka_value_len = exkey_attrs[i].ulValueLen;
257 
258 			buf += exkey_attrs[i].ulValueLen;
259 		}
260 	}
261 	/* Copy the key attributes array here */
262 	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
263 		attr_cnt * sizeof (kssl_object_attribute_t));
264 
265 	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
266 
267 	/*
268 	 * Finally, add the certificate chain to the buffer.
269 	 */
270 	kssl_params->kssl_certs.sc_count = ncerts;
271 
272 	/* First, an array of certificate sizes */
273 	for (i = 0; i < ncerts; i++) {
274 		uint32_t certsz = (uint32_t)certs[i].Length;
275 		char *p = buf + (i * sizeof (uint32_t));
276 		bcopy(&certsz, p, sizeof (uint32_t));
277 	}
278 
279 	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
280 	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
281 
282 	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
283 
284 	/* Now add the certificate data (ASN.1 DER encoded) */
285 	for (i = 0; i < ncerts; i++) {
286 		bcopy(certs[i].Data, buf, certs[i].Length);
287 		buf += certs[i].Length;
288 	}
289 
290 	*paramsize = bufsize;
291 	return (kssl_params);
292 }
293 
294 /*
295  * Extract a sensitive key via wrap/unwrap operations.
296  *
297  * This function requires that we call PKCS#11 API directly since
298  * KMF does not yet support wrapping/unwrapping of keys.   By extracting
299  * a sensitive key in wrapped form, we then unwrap it into a session key
300  * object.  KMF is then used to find the session key and return it in
301  * KMF_RAW_KEY format which is then passed along to KSSL by the caller.
302  */
303 static KMF_RETURN
304 get_sensitive_key_data(KMF_HANDLE_T kmfh, KMF_FINDKEY_PARAMS *fkparams,
305 	KMF_KEY_HANDLE *key, KMF_KEY_HANDLE *rawkey)
306 {
307 	KMF_RETURN rv = KMF_OK;
308 	static CK_BYTE aes_param[16];
309 	static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
310 	static CK_KEY_TYPE privkey_type = CKK_RSA;
311 	static CK_BBOOL true = TRUE;
312 	static CK_BBOOL false = FALSE;
313 	char *err = NULL;
314 	char wrapkey_label[BUFSIZ];
315 	int fd;
316 	uint32_t nkeys = 0;
317 	CK_RV ckrv;
318 	CK_SESSION_HANDLE pk11session;
319 	CK_BYTE aes_key_val[16];
320 
321 	CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param,
322 		sizeof (aes_param)};
323 	CK_OBJECT_HANDLE aes_key_obj = CK_INVALID_HANDLE;
324 	CK_OBJECT_HANDLE sess_privkey_obj = CK_INVALID_HANDLE;
325 	CK_BYTE *wrapped_privkey = NULL;
326 	CK_ULONG wrapped_privkey_len = 0;
327 
328 	CK_ATTRIBUTE unwrap_tmpl[] = {
329 		/* code below depends on the following attribute order */
330 		{CKA_TOKEN, &false, sizeof (false)},
331 		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
332 		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
333 		{CKA_SENSITIVE, &false, sizeof (false)},
334 		{CKA_PRIVATE, &false, sizeof (false)},
335 		{CKA_LABEL, NULL, 0}
336 	};
337 
338 	/*
339 	 * Create a wrap key with random data.
340 	 */
341 	fd = open("/dev/urandom", O_RDONLY);
342 	if (fd == -1) {
343 		perror("Error reading /dev/urandom");
344 		return (KMF_ERR_INTERNAL);
345 	}
346 	if (read(fd, aes_key_val, sizeof (aes_key_val)) !=
347 		sizeof (aes_key_val)) {
348 		perror("Error reading from /dev/urandom");
349 		(void) close(fd);
350 		return (KMF_ERR_INTERNAL);
351 	}
352 	(void) close(fd);
353 
354 	pk11session = KMF_GetPK11Handle(kmfh);
355 
356 	/*
357 	 * Login to create the wrap key stuff.
358 	 */
359 	ckrv = C_Login(pk11session, CKU_USER,
360 		(CK_UTF8CHAR_PTR)fkparams->cred.cred,
361 		fkparams->cred.credlen);
362 	if (ckrv != CKR_OK && ckrv != CKR_USER_ALREADY_LOGGED_IN) {
363 		(void) fprintf(stderr,
364 			"Cannot login to the token. error = %s\n",
365 			pkcs11_strerror(ckrv));
366 		return (KMF_ERR_INTERNAL);
367 	}
368 
369 	/*
370 	 * Turn the random key into a PKCS#11 session object.
371 	 */
372 	ckrv = SUNW_C_KeyToObject(pk11session, CKM_AES_CBC_PAD, aes_key_val,
373 		sizeof (aes_key_val), &aes_key_obj);
374 	if (ckrv != CKR_OK) {
375 		(void) fprintf(stderr,
376 			"Cannot create wrapping key. error = %s\n",
377 			pkcs11_strerror(ckrv));
378 		return (KMF_ERR_INTERNAL);
379 	}
380 
381 	/*
382 	 * Find the original private key that we are going to wrap.
383 	 */
384 	rv = KMF_FindKey(kmfh, fkparams, key, &nkeys);
385 	if (rv != KMF_OK) {
386 		REPORT_KMF_ERROR(rv, "Error finding private key", err);
387 		goto out;
388 	}
389 
390 	/*
391 	 * Get the size of the wrapped private key.
392 	 */
393 	bzero(aes_param, sizeof (aes_param));
394 	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
395 		aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
396 		NULL, &wrapped_privkey_len);
397 	if (ckrv != CKR_OK) {
398 		/*
399 		 * Most common error here is that the token doesn't
400 		 * support the wrapping mechanism or the key is
401 		 * marked non-extractable.  Return an error and let
402 		 * the caller deal with it gracefully.
403 		 */
404 		(void) fprintf(stderr,
405 			"Cannot get wrap key size. error = %s\n",
406 			pkcs11_strerror(ckrv));
407 		rv = KMF_ERR_INTERNAL;
408 		goto out;
409 	}
410 	wrapped_privkey = malloc(wrapped_privkey_len);
411 	if (wrapped_privkey == NULL) {
412 		rv = KMF_ERR_MEMORY;
413 		goto out;
414 	}
415 	/*
416 	 * Now get the actual wrapped key data.
417 	 */
418 	ckrv = C_WrapKey(pk11session, &aes_cbc_pad_mech,
419 		aes_key_obj, (CK_OBJECT_HANDLE)key->keyp,
420 		wrapped_privkey, &wrapped_privkey_len);
421 	if (ckrv != CKR_OK) {
422 		(void) fprintf(stderr,
423 			"Cannot wrap private key. error = %s\n",
424 			pkcs11_strerror(ckrv));
425 		rv = KMF_ERR_INTERNAL;
426 		goto out;
427 	}
428 	/*
429 	 * Create a label for the wrapped session key so we can find
430 	 * it easier later.
431 	 */
432 	snprintf(wrapkey_label, sizeof (wrapkey_label), "ksslprikey_%d",
433 		getpid());
434 
435 	unwrap_tmpl[5].pValue = wrapkey_label;
436 	unwrap_tmpl[5].ulValueLen = strlen(wrapkey_label);
437 
438 	/*
439 	 * Unwrap the key into the template and create a temporary
440 	 * session private key.
441 	 */
442 	ckrv = C_UnwrapKey(pk11session, &aes_cbc_pad_mech, aes_key_obj,
443 		wrapped_privkey, wrapped_privkey_len,
444 		unwrap_tmpl, 6, &sess_privkey_obj);
445 	if (ckrv != CKR_OK) {
446 		(void) fprintf(stderr,
447 			"Cannot unwrap private key. error = %s\n",
448 			pkcs11_strerror(ckrv));
449 		rv = KMF_ERR_INTERNAL;
450 		goto out;
451 	}
452 
453 	/*
454 	 * Use KMF to find the session key and return it as RAW data
455 	 * so we can pass it along to KSSL.
456 	 */
457 	fkparams->kstype = KMF_KEYSTORE_PK11TOKEN;
458 	fkparams->keyclass = KMF_ASYM_PRI;
459 	fkparams->format = KMF_FORMAT_RAWKEY;
460 	fkparams->findLabel = wrapkey_label;
461 	fkparams->pkcs11parms.sensitive = FALSE;
462 	fkparams->pkcs11parms.private = FALSE;
463 	fkparams->pkcs11parms.token = FALSE; /* <-- very important! */
464 
465 	rv = KMF_FindKey(kmfh, fkparams, rawkey, &nkeys);
466 	if (rv != KMF_OK) {
467 		REPORT_KMF_ERROR(rv, "Error finding raw private key", err);
468 		goto out;
469 	}
470 out:
471 	if (wrapped_privkey)
472 		free(wrapped_privkey);
473 
474 	if (aes_key_obj != CK_INVALID_HANDLE)
475 		C_DestroyObject(pk11session, aes_key_obj);
476 
477 	if (sess_privkey_obj != CK_INVALID_HANDLE)
478 		C_DestroyObject(pk11session, sess_privkey_obj);
479 
480 	return (rv);
481 }
482 
483 static kssl_params_t *
484 load_from_pkcs11(const char *token_label, const char *password_file,
485     const char *certname, int *bufsize)
486 {
487 	KMF_RETURN rv;
488 	KMF_HANDLE_T kmfh;
489 	KMF_X509_DER_CERT cert;
490 	KMF_KEY_HANDLE key, rawkey;
491 	KMF_CREDENTIAL creds;
492 	KMF_FINDCERT_PARAMS fcparams;
493 	KMF_FINDKEY_PARAMS fkparams;
494 	KMF_CONFIG_PARAMS cfgparams;
495 	KMF_DATA iddata = { NULL, 0 };
496 	kssl_params_t *kssl_params = NULL;
497 	uint32_t ncerts, nkeys;
498 	char *err, *idstr = NULL;
499 	char password_buf[1024];
500 	int nxkey = 0;
501 
502 	rv = KMF_Initialize(&kmfh, NULL, NULL);
503 	if (rv != KMF_OK) {
504 		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
505 		return (0);
506 	}
507 	if (get_passphrase(password_file, password_buf,
508 		sizeof (password_buf)) <= 0) {
509 		perror("Unable to read passphrase");
510 		goto done;
511 	}
512 	creds.cred = password_buf;
513 	creds.credlen = strlen(password_buf);
514 
515 	bzero(&cfgparams, sizeof (cfgparams));
516 	bzero(&fcparams, sizeof (fcparams));
517 	bzero(&fkparams, sizeof (fkparams));
518 
519 	cfgparams.kstype = KMF_KEYSTORE_PK11TOKEN;
520 	cfgparams.pkcs11config.label = (char *)token_label;
521 	cfgparams.pkcs11config.readonly = B_FALSE;
522 
523 	rv = KMF_ConfigureKeystore(kmfh, &cfgparams);
524 	if (rv != KMF_OK) {
525 		REPORT_KMF_ERROR(rv, "Error configuring KMF keystore", err);
526 		goto done;
527 	}
528 
529 	/*
530 	 * Find the certificate matching the given label.
531 	 */
532 	fcparams.kstype = KMF_KEYSTORE_PK11TOKEN;
533 	fcparams.certLabel = (char *)certname;
534 	rv = KMF_FindCert(kmfh, &fcparams, &cert, &ncerts);
535 	if (rv != KMF_OK || ncerts == 0)
536 		goto done;
537 
538 	/*
539 	 * Find the associated private key for this cert by
540 	 * keying off of the label and the ASCII ID string.
541 	 */
542 	rv = KMF_GetCertIDString(&cert.certificate, &idstr);
543 	if (rv != KMF_OK)
544 		goto done;
545 
546 	fkparams.kstype = KMF_KEYSTORE_PK11TOKEN;
547 	fkparams.keyclass = KMF_ASYM_PRI;
548 	fkparams.cred = creds;
549 	fkparams.format = KMF_FORMAT_RAWKEY;
550 	fkparams.findLabel = (char *)certname;
551 	fkparams.idstr = idstr;
552 	fkparams.pkcs11parms.private = TRUE;
553 	fkparams.pkcs11parms.token = TRUE;
554 
555 	rv = KMF_FindKey(kmfh, &fkparams, &key, &nkeys);
556 	if (rv == KMF_ERR_SENSITIVE_KEY) {
557 		KMF_FreeKMFKey(kmfh, &key);
558 		/*
559 		 * Get a normal key handle and then do a wrap/unwrap
560 		 * in order to get the necessary raw data fields needed
561 		 * to send to KSSL.
562 		 */
563 		fkparams.format = KMF_FORMAT_NATIVE;
564 		rv = get_sensitive_key_data(kmfh, &fkparams, &key, &rawkey);
565 		if (rv == KMF_OK) {
566 			/* Swap "key" for "rawkey" */
567 			KMF_FreeKMFKey(kmfh, &key);
568 
569 			key = rawkey;
570 		} else {
571 			KMF_FreeKMFKey(kmfh, &key);
572 
573 			/* Let kssl try to find the key. */
574 			nxkey = 1;
575 			rv = KMF_GetCertIDData(&cert.certificate, &iddata);
576 		}
577 	} else if (rv == KMF_ERR_UNEXTRACTABLE_KEY) {
578 			KMF_FreeKMFKey(kmfh, &key);
579 
580 			/* Let kssl try to find the key. */
581 			nxkey = 1;
582 			rv = KMF_GetCertIDData(&cert.certificate, &iddata);
583 	} else if (rv != KMF_OK || nkeys == 0)
584 		goto done;
585 
586 	if (rv == KMF_OK)
587 		kssl_params = kmf_to_kssl(nxkey, (KMF_RAW_KEY_DATA *)key.keyp,
588 			1, &cert.certificate, bufsize,
589 			(char *)token_label, &iddata, &creds);
590 done:
591 	if (ncerts != 0)
592 		KMF_FreeKMFCert(kmfh, &cert);
593 	if (nkeys != 0)
594 		KMF_FreeKMFKey(kmfh, &key);
595 	if (idstr)
596 		free(idstr);
597 
598 	if (kmfh != NULL)
599 		(void) KMF_Finalize(kmfh);
600 
601 	return (kssl_params);
602 }
603 
604 /*
605  * add_cacerts
606  *
607  * Load a chain of certificates from a PEM file.
608  */
609 static kssl_params_t *
610 add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file)
611 {
612 	int i, newlen;
613 	uint32_t certlen = 0, ncerts;
614 	char *buf;
615 	KMF_RETURN rv;
616 	KMF_X509_DER_CERT *certs = NULL;
617 	KMF_FINDCERT_PARAMS fcparms;
618 	kssl_params_t *kssl_params;
619 	KMF_HANDLE_T kmfh;
620 	char *err = NULL;
621 
622 	bzero(&fcparms, sizeof (fcparms));
623 	fcparms.kstype = KMF_KEYSTORE_OPENSSL;
624 	fcparms.sslparms.certfile = (char *)cacert_chain_file;
625 
626 	rv = KMF_Initialize(&kmfh, NULL, NULL);
627 	if (rv != KMF_OK) {
628 		REPORT_KMF_ERROR(rv, "Error initializing KMF", err);
629 		return (0);
630 	}
631 	rv = KMF_FindCert(kmfh, &fcparms, NULL, &ncerts);
632 	if (rv != KMF_OK) {
633 		REPORT_KMF_ERROR(rv, "Error finding CA certificates", err);
634 		(void) KMF_Finalize(kmfh);
635 		return (0);
636 	}
637 	certs = (KMF_X509_DER_CERT *)malloc(ncerts *
638 		sizeof (KMF_X509_DER_CERT));
639 	if (certs == NULL) {
640 		(void) fprintf(stderr, "memory allocation error.\n");
641 		(void) KMF_Finalize(kmfh);
642 		return (NULL);
643 	}
644 	bzero(certs, ncerts * sizeof (KMF_X509_DER_CERT));
645 	rv = KMF_FindCert(kmfh, &fcparms, certs, &ncerts);
646 
647 	(void) KMF_Finalize(kmfh);
648 
649 	if (rv != KMF_OK || ncerts == 0) {
650 		bzero(old_params, old_params->kssl_params_size);
651 		free(old_params);
652 		return (NULL);
653 	}
654 
655 	if (verbose) {
656 		(void) printf("%d certificates read successfully\n", ncerts);
657 	}
658 
659 	newlen = old_params->kssl_params_size;
660 	for (i = 0; i < ncerts; i++)
661 		newlen += certs[i].certificate.Length;
662 
663 	/*
664 	 * Get a bigger structure and update the
665 	 * fields to account for the additional certs.
666 	 */
667 	kssl_params = realloc(old_params, newlen);
668 
669 	kssl_params->kssl_params_size = newlen;
670 	kssl_params->kssl_certs.sc_count += ncerts;
671 
672 	/* Put the cert size info starting from sc_sizes[1] */
673 	buf = (char *)kssl_params;
674 	buf += kssl_params->kssl_certs.sc_sizes_offset;
675 	bcopy(buf, &certlen, sizeof (uint32_t));
676 	buf += sizeof (uint32_t);
677 	for (i = 0; i < ncerts; i++) {
678 		uint32_t size = (uint32_t)certs[i].certificate.Length;
679 		bcopy(&size, buf, sizeof (uint32_t));
680 		buf += sizeof (uint32_t);
681 	}
682 
683 	/* Put the cert_bufs starting from sc_certs[1] */
684 	buf = (char *)kssl_params;
685 	buf += kssl_params->kssl_certs.sc_certs_offset;
686 	buf += certlen;
687 
688 	/* now the certs values */
689 	for (i = 0; i < ncerts; i++) {
690 		bcopy(certs[i].certificate.Data, buf,
691 			certs[i].certificate.Length);
692 		buf += certs[i].certificate.Length;
693 	}
694 
695 	for (i = 0; i < ncerts; i++)
696 		KMF_FreeKMFCert(kmfh, &certs[i]);
697 	free(certs);
698 
699 	return (kssl_params);
700 }
701 
702 /*
703  * Find a key and certificate(s) from a single PEM file.
704  */
705 static kssl_params_t *
706 load_from_pem(const char *filename, const char *password_file, int *paramsize)
707 {
708 	int ncerts = 0, i;
709 	kssl_params_t *kssl_params;
710 	KMF_RAW_KEY_DATA *rsa = NULL;
711 	KMF_DATA *certs = NULL;
712 
713 	ncerts = PEM_get_rsa_key_certs(filename, (char *)password_file,
714 		&rsa, &certs);
715 	if (rsa == NULL || certs == NULL || ncerts == 0) {
716 		return (NULL);
717 	}
718 
719 	if (verbose)
720 		(void) printf("%d certificates read successfully\n", ncerts);
721 
722 	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
723 		NULL, NULL);
724 
725 	for (i = 0; i < ncerts; i++)
726 		KMF_FreeData(&certs[i]);
727 	free(certs);
728 	KMF_FreeRawKey(rsa);
729 
730 	return (kssl_params);
731 }
732 
733 /*
734  * Load a raw key and certificate(s) from a PKCS#12 file.
735  */
736 static kssl_params_t *
737 load_from_pkcs12(const char *filename, const char *password_file,
738     int *paramsize)
739 {
740 	KMF_RAW_KEY_DATA *rsa = NULL;
741 	kssl_params_t *kssl_params;
742 	KMF_DATA *certs = NULL;
743 	int ncerts = 0, i;
744 
745 	ncerts = PKCS12_get_rsa_key_certs(filename,
746 		password_file, &rsa, &certs);
747 
748 	if (certs == NULL || ncerts == 0) {
749 		(void) fprintf(stderr,
750 		    "Unable to read cert and/or key from %s\n", filename);
751 		return (NULL);
752 	}
753 
754 	if (verbose)
755 		(void) printf("%d certificates read successfully\n", ncerts);
756 
757 	kssl_params = kmf_to_kssl(0, rsa, ncerts, certs, paramsize, NULL,
758 		NULL, NULL);
759 
760 	for (i = 0; i < ncerts; i++)
761 		KMF_FreeData(&certs[i]);
762 	free(certs);
763 
764 	KMF_FreeRawKey(rsa);
765 	return (kssl_params);
766 }
767 
768 int
769 parse_and_set_addr(char *server_address, char *server_port,
770     struct sockaddr_in *addr)
771 {
772 	if (server_port == NULL) {
773 		return (-1);
774 	}
775 
776 	if (server_address == NULL) {
777 		addr->sin_addr.s_addr = INADDR_ANY;
778 	} else {
779 		addr->sin_addr.s_addr = inet_addr(server_address);
780 		if ((int)addr->sin_addr.s_addr == -1) {
781 			struct hostent *hp;
782 
783 			if ((hp = gethostbyname(server_address)) == NULL) {
784 				(void) fprintf(stderr,
785 				    "Error: Unknown host: %s\n",
786 				    server_address);
787 				return (-1);
788 			}
789 
790 			(void) memcpy(&addr->sin_addr.s_addr,
791 			    hp->h_addr_list[0],
792 			    sizeof (addr->sin_addr.s_addr));
793 		}
794 	}
795 
796 	errno = 0;
797 	addr->sin_port = strtol(server_port, NULL, 10);
798 	if (addr->sin_port == 0 || errno != 0) {
799 		(void) fprintf(stderr, "Error: Invalid Port value: %s\n",
800 		    server_port);
801 		return (-1);
802 	}
803 
804 	return (0);
805 }
806 
807 /*
808  * The order of the ciphers is important. It is used as the
809  * default order (when -c is not specified).
810  */
811 struct csuite {
812 	const char *suite;
813 	uint16_t val;
814 	boolean_t seen;
815 } cipher_suites[CIPHER_SUITE_COUNT - 1] = {
816 	{"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE},
817 	{"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE},
818 	{"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE},
819 	{"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE},
820 };
821 
822 static int
823 check_suites(char *suites, uint16_t *sarray)
824 {
825 	int i;
826 	int err = 0;
827 	char *suite;
828 	int sindx = 0;
829 
830 	if (suites != NULL) {
831 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
832 			sarray[i] = CIPHER_NOTSET;
833 	} else {
834 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
835 			sarray[i] = cipher_suites[i].val;
836 		return (err);
837 	}
838 
839 	suite = strtok(suites, ",");
840 	do {
841 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
842 			if (strcasecmp(suite, cipher_suites[i].suite) == 0) {
843 				if (!cipher_suites[i].seen) {
844 					sarray[sindx++] = cipher_suites[i].val;
845 					cipher_suites[i].seen = B_TRUE;
846 				}
847 				break;
848 			}
849 		}
850 
851 		if (i == (CIPHER_SUITE_COUNT - 1)) {
852 			(void) fprintf(stderr,
853 			    "Unknown Cipher suite name: %s\n", suite);
854 			err++;
855 		}
856 	} while ((suite = strtok(NULL, ",")) != NULL);
857 
858 	return (err);
859 }
860 
861 int
862 do_create(int argc, char *argv[])
863 {
864 	const char *softtoken_dir = NULL;
865 	const char *token_label = NULL;
866 	const char *password_file = NULL;
867 	const char *cert_key_file = NULL;
868 	const char *cacert_chain_file = NULL;
869 	const char *certname = NULL;
870 	char *suites = NULL;
871 	uint32_t timeout = DEFAULT_SID_TIMEOUT;
872 	uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES;
873 	uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
874 	int proxy_port = -1;
875 	struct sockaddr_in server_addr;
876 	char *format = NULL;
877 	char *port, *addr;
878 	char c;
879 	int pcnt;
880 	kssl_params_t *kssl_params;
881 	int bufsize;
882 
883 	argc -= 1;
884 	argv += 1;
885 
886 	while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) {
887 		switch (c) {
888 		case 'd':
889 			softtoken_dir = optarg;
890 			break;
891 		case 'c':
892 			suites = optarg;
893 			break;
894 		case 'C':
895 			certname = optarg;
896 			break;
897 		case 'f':
898 			format = optarg;
899 			break;
900 		case 'h':
901 			cacert_chain_file = optarg;
902 			break;
903 		case 'i':
904 			cert_key_file = optarg;
905 			break;
906 		case 'T':
907 			token_label = optarg;
908 			break;
909 		case 'p':
910 			password_file = optarg;
911 			break;
912 		case 't':
913 			timeout = atoi(optarg);
914 			break;
915 		case 'x':
916 			proxy_port = atoi(optarg);
917 			break;
918 		case 'v':
919 			verbose = B_TRUE;
920 			break;
921 		case 'z':
922 			scache_size = atoi(optarg);
923 			break;
924 		default:
925 			goto err;
926 		}
927 	}
928 
929 	pcnt = argc - optind;
930 	if (pcnt == 0) {
931 		port = "443";	/* default SSL port */
932 		addr = NULL;
933 	} else if (pcnt == 1) {
934 		port = argv[optind];
935 		addr = NULL;
936 	} else if (pcnt == 2) {
937 		addr = argv[optind];
938 		port = argv[optind + 1];
939 	} else {
940 		goto err;
941 	}
942 
943 	if (parse_and_set_addr(addr, port, &server_addr) < 0) {
944 		goto err;
945 	}
946 
947 	if (verbose) {
948 		(void) printf("addr=%s, port = %d\n",
949 		    inet_ntoa(server_addr.sin_addr), server_addr.sin_port);
950 	}
951 
952 	if (format == NULL || proxy_port == -1) {
953 		goto err;
954 	}
955 
956 	if (check_suites(suites, kssl_suites) != 0) {
957 		goto err;
958 	}
959 
960 	if (strcmp(format, "pkcs11") == 0) {
961 		if (token_label == NULL || certname == NULL) {
962 			goto err;
963 		}
964 		if (softtoken_dir != NULL) {
965 			(void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1);
966 			if (verbose) {
967 				(void) printf(
968 				    "SOFTTOKEN_DIR=%s\n",
969 				    getenv("SOFTTOKEN_DIR"));
970 			}
971 		}
972 		kssl_params = load_from_pkcs11(
973 		    token_label, password_file, certname, &bufsize);
974 	} else if (strcmp(format, "pkcs12") == 0) {
975 		if (cert_key_file == NULL) {
976 			goto err;
977 		}
978 		kssl_params = load_from_pkcs12(
979 		    cert_key_file, password_file, &bufsize);
980 	} else if (strcmp(format, "pem") == 0) {
981 		if (cert_key_file == NULL) {
982 			goto err;
983 		}
984 		kssl_params = load_from_pem(
985 		    cert_key_file, password_file, &bufsize);
986 	} else {
987 		(void) fprintf(stderr, "Unsupported cert format: %s\n", format);
988 		goto err;
989 	}
990 
991 	if (kssl_params == NULL) {
992 		return (FAILURE);
993 	}
994 
995 	/*
996 	 * Add the list of supported ciphers to the buffer.
997 	 */
998 	bcopy(kssl_suites, kssl_params->kssl_suites,
999 	    sizeof (kssl_params->kssl_suites));
1000 	kssl_params->kssl_params_size = bufsize;
1001 	kssl_params->kssl_addr = server_addr;
1002 	kssl_params->kssl_session_cache_timeout = timeout;
1003 	kssl_params->kssl_proxy_port = proxy_port;
1004 	kssl_params->kssl_session_cache_size = scache_size;
1005 
1006 	if (cacert_chain_file != NULL) {
1007 		kssl_params = add_cacerts(kssl_params, cacert_chain_file);
1008 		if (kssl_params == NULL) {
1009 			return (FAILURE);
1010 		}
1011 	}
1012 
1013 	if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) {
1014 		int err = CRYPTO_FAILED;
1015 
1016 		if (kssl_params->kssl_is_nxkey)
1017 			err = kssl_params->kssl_token.ck_rv;
1018 		(void) fprintf(stderr,
1019 		    "Error loading cert and key: 0x%x\n", err);
1020 		return (FAILURE);
1021 	}
1022 
1023 	if (verbose)
1024 		(void) printf("Successfully loaded cert and key\n");
1025 
1026 	bzero(kssl_params, bufsize);
1027 	free(kssl_params);
1028 	return (SUCCESS);
1029 
1030 err:
1031 	usage_create(B_TRUE);
1032 	return (SMF_EXIT_ERR_CONFIG);
1033 }
1034