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 2006 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 <arpa/inet.h>
30 #include <errno.h>
31 #include <sys/sysmacros.h>
32 #include <netdb.h> /* hostent */
33 #include <netinet/in.h>
34 #include <openssl/rsa.h>
35 #include <security/cryptoki.h>
36 #include <security/pkcs11.h>
37 #include <cryptoutil.h>
38 #include <stdio.h>
39 #include <strings.h>
40 #include <sys/socket.h>
41 #include <libscf.h>
42 #include <inet/kssl/kssl.h>
43 #include "kssladm.h"
44 
45 void
46 usage_create(boolean_t do_print)
47 {
48 	if (do_print)
49 		(void) fprintf(stderr, "Usage:\n");
50 	(void) fprintf(stderr, "kssladm create"
51 		" -f pkcs11 [-d softtoken_directory] -T <token_label>"
52 		" -C <certificate_label> -x <proxy_port>"
53 		" [-h <ca_certchain_file>]"
54 		" [options] [<server_address>] [<server_port>]\n");
55 
56 	(void) fprintf(stderr, "kssladm create"
57 		" -f pkcs12 -i <cert_and_key_pk12file> -x <proxy_port>"
58 		" [options] [<server_address>] [<server_port>]\n");
59 
60 	(void) fprintf(stderr, "kssladm create"
61 		" -f pem -i <cert_and_key_pemfile> -x <proxy_port>"
62 		" [options] [<server_address>] [<server_port>]\n");
63 
64 	(void) fprintf(stderr, "options are:\n"
65 		"\t[-c <ciphersuites>]\n"
66 		"\t[-p <password_file>]\n"
67 		"\t[-t <ssl_session_cache_timeout>]\n"
68 		"\t[-z <ssl_session_cache_size>]\n"
69 		"\t[-v]\n");
70 }
71 
72 static uchar_t *
73 get_cert_val(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE cert_obj, int *len)
74 {
75 	CK_RV rv;
76 	uchar_t *buf;
77 	CK_ATTRIBUTE cert_attrs[] = {{CKA_VALUE, NULL_PTR, 0}};
78 
79 	/* the certs ... */
80 	rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1);
81 	if (rv != CKR_OK) {
82 		(void) fprintf(stderr, "Cannot get cert size."
83 		    " error = %s\n", pkcs11_strerror(rv));
84 		return (NULL);
85 	}
86 
87 	buf = malloc(cert_attrs[0].ulValueLen);
88 	if (buf == NULL)
89 		return (NULL);
90 	cert_attrs[0].pValue = buf;
91 
92 	rv = C_GetAttributeValue(sess, cert_obj, cert_attrs, 1);
93 	if (rv != CKR_OK) {
94 		(void) fprintf(stderr, "Cannot get cert value."
95 		    " error = %s\n", pkcs11_strerror(rv));
96 		free(buf);
97 		return (NULL);
98 	}
99 
100 	*len = cert_attrs[0].ulValueLen;
101 	return (buf);
102 }
103 
104 #define	OPT_ATTR_CNT	6
105 #define	MAX_ATTR_CNT	16
106 
107 int known_attr_cnt = 0;
108 
109 #define	CKA_TOKEN_INDEX	1
110 /*
111  * The order of the attributes must stay in the same order
112  * as in the attribute template, privkey_tmpl, in load_from_pkcs11().
113  */
114 CK_ATTRIBUTE key_gattrs[MAX_ATTR_CNT] = {
115 	{CKA_MODULUS, NULL_PTR, 0},
116 	{CKA_TOKEN, NULL_PTR, 0},
117 	{CKA_CLASS, NULL_PTR, 0},
118 	{CKA_KEY_TYPE, NULL_PTR, 0},
119 };
120 CK_ATTRIBUTE known_cert_attrs[1];
121 
122 /*
123  * Everything is allocated in one single contiguous buffer.
124  * The layout is the following:
125  * . the kssl_params_t structure
126  * . optional buffer containing pin (if key is non extractable)
127  * . the array of key attribute structs, (value of ck_attrs)
128  * . the key attributes values (values of ck_attrs[i].ck_value);
129  * . the array of sizes of the certificates, (referred to as sc_sizes[])
130  * . the certificates values (referred to as sc_certs[])
131  *
132  * The address of the certs and key attributes values are offsets
133  * from the beginning of the big buffer. sc_sizes_offset points
134  * to sc_sizes[0] and sc_certs_offset points to sc_certs[0].
135  */
136 static kssl_params_t *
137 pkcs11_to_kssl(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE privkey_obj,
138     boolean_t is_nxkey, int *paramsize, char *label, char *pin, int pinlen)
139 {
140 	int i;
141 	CK_RV rv;
142 	int total_attr_cnt;
143 	uint32_t cert_size, bufsize;
144 	char *buf;
145 	kssl_key_t *key;
146 	kssl_params_t *kssl_params;
147 	CK_ATTRIBUTE privkey_opt_attrs[OPT_ATTR_CNT] = {
148 		{CKA_PUBLIC_EXPONENT, NULL_PTR, 0},
149 		{CKA_PRIME_1, NULL_PTR, 0},
150 		{CKA_PRIME_2, NULL_PTR, 0},
151 		{CKA_EXPONENT_1, NULL_PTR, 0},
152 		{CKA_EXPONENT_2, NULL_PTR, 0},
153 		{CKA_COEFFICIENT, NULL_PTR, 0}
154 	};
155 	kssl_object_attribute_t kssl_attrs[MAX_ATTR_CNT];
156 
157 	/* Get the certificate size */
158 	bufsize = sizeof (kssl_params_t);
159 	cert_size = (uint32_t)known_cert_attrs[0].ulValueLen;
160 	bufsize += cert_size + MAX_CHAIN_LENGTH * sizeof (uint32_t);
161 
162 	/* These are attributes for which we have the value and length */
163 	for (i = 0; i < known_attr_cnt; i++) {
164 		bufsize += sizeof (crypto_object_attribute_t) +
165 		    key_gattrs[i].ulValueLen;
166 	}
167 	total_attr_cnt = known_attr_cnt;
168 
169 	if (!is_nxkey) {
170 		/* Add CKA_PRIVATE_EXPONENT for extractable key */
171 		key_gattrs[total_attr_cnt].type = CKA_PRIVATE_EXPONENT;
172 		key_gattrs[total_attr_cnt].pValue  = NULL_PTR;
173 		key_gattrs[total_attr_cnt].ulValueLen = 0;
174 
175 		rv = C_GetAttributeValue(sess, privkey_obj,
176 		    &key_gattrs[total_attr_cnt], 1);
177 		if (rv != CKR_OK) {
178 			(void) fprintf(stderr,
179 			    "Cannot get private key object attribute."
180 			    " error = %s\n", pkcs11_strerror(rv));
181 			return (NULL);
182 		}
183 
184 		bufsize += sizeof (crypto_object_attribute_t) +
185 		    key_gattrs[total_attr_cnt].ulValueLen;
186 		total_attr_cnt++;
187 	}
188 
189 	/*
190 	 * Get the optional key attributes. The return values could be
191 	 * CKR_ATTRIBUTE_TYPE_INVALID with ulValueLen set to -1 OR
192 	 * CKR_OK with ulValueLen set to 0. The latter is done by
193 	 * soft token and seems dubious.
194 	 */
195 	if (!is_nxkey) {
196 		rv = C_GetAttributeValue(sess, privkey_obj, privkey_opt_attrs,
197 		    OPT_ATTR_CNT);
198 		if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
199 			(void) fprintf(stderr,
200 			    "Cannot get private key object attributes."
201 			    " error = %s\n", pkcs11_strerror(rv));
202 			return (NULL);
203 		}
204 
205 		for (i = 0; i < OPT_ATTR_CNT; i++) {
206 			if (privkey_opt_attrs[i].ulValueLen == (CK_ULONG)-1 ||
207 			    privkey_opt_attrs[i].ulValueLen == 0)
208 				continue;
209 			/* Structure copy */
210 			key_gattrs[total_attr_cnt] = privkey_opt_attrs[i];
211 			bufsize += sizeof (crypto_object_attribute_t) +
212 			    privkey_opt_attrs[i].ulValueLen;
213 			total_attr_cnt++;
214 		}
215 	} else
216 		bufsize += pinlen;
217 
218 	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
219 	bufsize += sizeof (uint32_t);
220 
221 	/* Now the big memory allocation */
222 	if ((buf = calloc(bufsize, 1)) == NULL) {
223 		(void) fprintf(stderr,
224 			"Cannot allocate memory for the kssl_params "
225 			"and values\n");
226 		return (NULL);
227 	}
228 
229 	/* LINTED */
230 	kssl_params = (kssl_params_t *)buf;
231 
232 	buf = (char *)(kssl_params + 1);
233 
234 	if (is_nxkey) {
235 		kssl_params->kssl_is_nxkey = 1;
236 		bcopy(label, kssl_params->kssl_token.toklabel,
237 		    CRYPTO_EXT_SIZE_LABEL);
238 		kssl_params->kssl_token.pinlen = pinlen;
239 		kssl_params->kssl_token.tokpin_offset =
240 		    buf - (char *)kssl_params;
241 		kssl_params->kssl_token.ck_rv = 0;
242 		bcopy(pin, buf, pinlen);
243 		buf += pinlen;
244 	}
245 
246 	/* the keys attributes structs array */
247 	key = &kssl_params->kssl_privkey;
248 	key->ks_format = CRYPTO_KEY_ATTR_LIST;
249 	key->ks_count = total_attr_cnt;
250 	key->ks_attrs_offset = buf - (char *)kssl_params;
251 	buf += total_attr_cnt * sizeof (kssl_object_attribute_t);
252 
253 	/* These are attributes for which we already have the value */
254 	for (i = 0; i < known_attr_cnt; i++) {
255 		bcopy(key_gattrs[i].pValue, buf, key_gattrs[i].ulValueLen);
256 		kssl_attrs[i].ka_type = key_gattrs[i].type;
257 		kssl_attrs[i].ka_value_offset = buf - (char *)kssl_params;
258 		kssl_attrs[i].ka_value_len = key_gattrs[i].ulValueLen;
259 		buf += key_gattrs[i].ulValueLen;
260 	}
261 
262 	if (total_attr_cnt > known_attr_cnt) {
263 		/* These are attributes for which we need to get the value */
264 		for (i = known_attr_cnt; i < total_attr_cnt; i++) {
265 			key_gattrs[i].pValue = buf;
266 			kssl_attrs[i].ka_type = key_gattrs[i].type;
267 			kssl_attrs[i].ka_value_offset =
268 			    buf - (char *)kssl_params;
269 			kssl_attrs[i].ka_value_len = key_gattrs[i].ulValueLen;
270 			buf += key_gattrs[i].ulValueLen;
271 		}
272 
273 		rv = C_GetAttributeValue(sess, privkey_obj,
274 		    &key_gattrs[known_attr_cnt],
275 		    total_attr_cnt - known_attr_cnt);
276 		if (rv != CKR_OK) {
277 			(void) fprintf(stderr,
278 			    "Cannot get private key object attributes."
279 			    " error = %s\n", pkcs11_strerror(rv));
280 			return (NULL);
281 		}
282 	}
283 
284 	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
285 	    total_attr_cnt * sizeof (kssl_object_attribute_t));
286 
287 	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
288 	kssl_params->kssl_certs.sc_count = 1;
289 	bcopy(&cert_size, buf, sizeof (uint32_t));
290 	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
291 	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
292 
293 	/* now the certs values */
294 	bcopy(known_cert_attrs[0].pValue, buf, known_cert_attrs[0].ulValueLen);
295 	free(known_cert_attrs[0].pValue);
296 	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
297 
298 	*paramsize = bufsize;
299 	bzero(pin, pinlen);
300 	(void) C_Logout(sess);
301 	(void) C_CloseSession(sess);
302 	return (kssl_params);
303 }
304 
305 #define	max_num_cert 32
306 
307 static kssl_params_t *
308 load_from_pkcs11(const char *token_label, const char *password_file,
309     const char *certname, int *bufsize)
310 {
311 	static CK_BBOOL true = TRUE;
312 	static CK_BBOOL false = FALSE;
313 
314 	CK_RV rv;
315 	CK_SLOT_ID slot;
316 	CK_SLOT_ID_PTR	pk11_slots;
317 	CK_ULONG slotcnt = 10;
318 	CK_TOKEN_INFO	token_info;
319 	CK_SESSION_HANDLE sess;
320 	static CK_OBJECT_CLASS cert_class = CKO_CERTIFICATE;
321 	static CK_CERTIFICATE_TYPE cert_type = CKC_X_509;
322 	CK_ATTRIBUTE cert_tmpl[4] = {
323 		{CKA_TOKEN, &true, sizeof (true)},
324 		{CKA_LABEL, NULL_PTR, 0},
325 		{CKA_CLASS, &cert_class, sizeof (cert_class)},
326 		{CKA_CERTIFICATE_TYPE, &cert_type, sizeof (cert_type)}
327 	};
328 	CK_ULONG cert_tmpl_count = 4, cert_obj_count = 1;
329 	CK_OBJECT_HANDLE cert_obj, privkey_obj;
330 	CK_OBJECT_HANDLE cert_objs[max_num_cert];
331 	static CK_OBJECT_CLASS privkey_class = CKO_PRIVATE_KEY;
332 	static CK_KEY_TYPE privkey_type = CKK_RSA;
333 	CK_ATTRIBUTE privkey_tmpl[] = {
334 		/*
335 		 * The order of attributes must stay in the same order
336 		 * as in the global attribute array, key_gattrs.
337 		 */
338 		{CKA_MODULUS, NULL_PTR, 0},
339 		{CKA_TOKEN, &true, sizeof (true)},
340 		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
341 		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)}
342 	};
343 	CK_ULONG privkey_tmpl_count = 4, privkey_obj_count = 1;
344 	CK_BBOOL is_extractable;
345 	CK_ATTRIBUTE privkey_attrs[1] = {
346 		{CKA_EXTRACTABLE, NULL_PTR, 0},
347 	};
348 	boolean_t bingo = B_FALSE;
349 	int i, blen, mlen;
350 	uchar_t *mval, *ber_buf;
351 	char token_label_padded[sizeof (token_info.label) + 1];
352 	char passphrase[MAX_PIN_LENGTH];
353 	CK_ULONG ulPinLen;
354 
355 	(void) snprintf(token_label_padded, sizeof (token_label_padded),
356 		"%-32s", token_label);
357 
358 	rv = C_Initialize(NULL_PTR);
359 
360 	if ((rv != CKR_OK) && (rv != CKR_CRYPTOKI_ALREADY_INITIALIZED)) {
361 		(void) fprintf(stderr,
362 		    "Cannot initialize PKCS#11. error = %s\n",
363 		    pkcs11_strerror(rv));
364 		return (NULL);
365 	}
366 
367 	/* Get slot count */
368 	rv = C_GetSlotList(1, NULL_PTR, &slotcnt);
369 	if (rv != CKR_OK || slotcnt == 0) {
370 		(void) fprintf(stderr,
371 		    "Cannot get PKCS#11 slot list. error = %s\n",
372 		    pkcs11_strerror(rv));
373 		return (NULL);
374 	}
375 
376 	pk11_slots = calloc(slotcnt, sizeof (CK_SLOT_ID));
377 	if (pk11_slots == NULL) {
378 		(void) fprintf(stderr,
379 		    "Cannot get memory for %ld slots\n", slotcnt);
380 		return (NULL);
381 	}
382 
383 	rv = C_GetSlotList(1, pk11_slots, &slotcnt);
384 	if (rv != CKR_OK) {
385 		(void) fprintf(stderr,
386 		    "Cannot get PKCS#11 slot list. error = %s\n",
387 		    pkcs11_strerror(rv));
388 		return (NULL);
389 	}
390 
391 	if (verbose)
392 		(void) printf("Found %ld slots\n", slotcnt);
393 
394 	/* Search the token that matches the label */
395 	while (slotcnt > 0) {
396 		rv = C_GetTokenInfo(pk11_slots[--slotcnt], &token_info);
397 		if (rv != CKR_OK)
398 			continue;
399 
400 		if (verbose)
401 			(void) printf("slot [%ld] = %s\n",
402 			    slotcnt, token_info.label);
403 		if (memcmp(token_label_padded, token_info.label,
404 		    sizeof (token_info.label)) == 0) {
405 			bingo = B_TRUE;
406 			slot = pk11_slots[slotcnt];
407 			break;
408 		}
409 		if (verbose) {
410 			token_info.label[31] = '\0';
411 			(void) printf("found slot [%s]\n", token_info.label);
412 		}
413 	}
414 
415 	if (!bingo) {
416 		(void) fprintf(stderr, "no matching PKCS#11 token found\n");
417 		return (NULL);
418 	}
419 
420 	rv = C_OpenSession(slot, CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR,
421 		&sess);
422 	if (rv != CKR_OK) {
423 		(void) fprintf(stderr, "Cannot open session. error = %s\n",
424 		    pkcs11_strerror(rv));
425 		return (NULL);
426 	}
427 
428 	/*
429 	 * Some tokens may not be setting CKF_LOGIN_REQUIRED. So, we do
430 	 * not check for this flag and always login to be safe.
431 	 */
432 	ulPinLen = get_passphrase(password_file, passphrase,
433 	    sizeof (passphrase));
434 	if (ulPinLen == 0) {
435 		(void) fprintf(stderr, "Unable to read passphrase");
436 		return (NULL);
437 	}
438 
439 	rv = C_Login(sess, CKU_USER, (CK_UTF8CHAR_PTR)passphrase,
440 	    ulPinLen);
441 	if (rv != CKR_OK) {
442 		(void) fprintf(stderr, "Cannot login to the token."
443 		    " error = %s\n", pkcs11_strerror(rv));
444 		return (NULL);
445 	}
446 
447 	cert_tmpl[1].pValue = (CK_VOID_PTR) certname;
448 	cert_tmpl[1].ulValueLen = strlen(certname);
449 
450 	rv = C_FindObjectsInit(sess, cert_tmpl, cert_tmpl_count);
451 	if (rv != CKR_OK) {
452 		(void) fprintf(stderr,
453 		    "Cannot initialize cert search."
454 		    " error = %s\n", pkcs11_strerror(rv));
455 		return (NULL);
456 	}
457 
458 	rv = C_FindObjects(sess, cert_objs,
459 		(certname == NULL ? 1 : max_num_cert), &cert_obj_count);
460 	if (rv != CKR_OK) {
461 		(void) fprintf(stderr,
462 		    "Cannot retrieve cert object. error = %s\n",
463 		    pkcs11_strerror(rv));
464 		return (NULL);
465 	}
466 
467 	/* Who cares if this fails! */
468 	(void) C_FindObjectsFinal(sess);
469 	if (verbose)
470 		(void) printf("found %ld certificates\n", cert_obj_count);
471 
472 	if (cert_obj_count == 0) {
473 		(void) fprintf(stderr, "\"%s\" not found.\n", certname);
474 		(void) fprintf(stderr, "no certs. bye.\n");
475 		return (NULL);
476 	}
477 
478 	cert_obj = cert_objs[0];
479 
480 	/* Get the modulus value from the certificate */
481 	ber_buf = get_cert_val(sess, cert_obj, &blen);
482 	if (ber_buf == NULL) {
483 		(void) fprintf(stderr,
484 		    "Cannot get certificate data for \"%s\".\n", certname);
485 		return (NULL);
486 	}
487 
488 	/* Store it for later use. We free the buffer at that time. */
489 	known_cert_attrs[0].type = CKA_VALUE;
490 	known_cert_attrs[0].pValue = ber_buf;
491 	known_cert_attrs[0].ulValueLen = blen;
492 
493 	mval = get_modulus(ber_buf, blen, &mlen);
494 	if (mval == NULL) {
495 		(void) fprintf(stderr,
496 		    "Cannot get Modulus in certificate \"%s\".\n", certname);
497 		return (NULL);
498 	}
499 
500 	/* Now get the private key */
501 	privkey_tmpl[0].pValue = mval;
502 	privkey_tmpl[0].ulValueLen = mlen;
503 
504 	rv = C_FindObjectsInit(sess, privkey_tmpl, privkey_tmpl_count);
505 	if (rv != CKR_OK) {
506 		(void) fprintf(stderr, "Cannot intialize private key search."
507 		    " error = %s\n", pkcs11_strerror(rv));
508 		return (NULL);
509 	}
510 
511 	rv = C_FindObjects(sess, &privkey_obj, 1,  &privkey_obj_count);
512 	if (rv != CKR_OK) {
513 		(void) fprintf(stderr, "Cannot retrieve private key object "
514 		    " error = %s\n", pkcs11_strerror(rv));
515 		return (NULL);
516 	}
517 	/* Who cares if this fails! */
518 	(void) C_FindObjectsFinal(sess);
519 
520 	if (privkey_obj_count == 0) {
521 		(void) fprintf(stderr, "no private keys. bye.\n");
522 		return (NULL);
523 	}
524 
525 	(void) printf("found %ld private keys\n", privkey_obj_count);
526 	if (verbose) {
527 		(void) printf("private key attributes:    \n");
528 		(void) printf("\tmodulus: size %d \n", mlen);
529 	}
530 
531 	/*
532 	 * Store it for later use. The index of the attributes
533 	 * is the same in both the structures.
534 	 */
535 	known_attr_cnt = privkey_tmpl_count;
536 	for (i = 0; i < privkey_tmpl_count; i++)
537 		key_gattrs[i] = privkey_tmpl[i];
538 
539 	/*
540 	 * Get CKA_EXTRACTABLE value. We set the default value
541 	 * TRUE if the token returns CKR_ATTRIBUTE_TYPE_INVALID.
542 	 * The token would supply this attribute if the key
543 	 * is not extractable.
544 	 */
545 	privkey_attrs[0].pValue = &is_extractable;
546 	privkey_attrs[0].ulValueLen = sizeof (is_extractable);
547 	rv = C_GetAttributeValue(sess, privkey_obj, privkey_attrs, 1);
548 	if (rv != CKR_OK && rv != CKR_ATTRIBUTE_TYPE_INVALID) {
549 		(void) fprintf(stderr,
550 		    "Cannot get CKA_EXTRACTABLE attribute."
551 		    " error = %s\n", pkcs11_strerror(rv));
552 		return (NULL);
553 	}
554 
555 	if (rv == CKR_ATTRIBUTE_TYPE_INVALID)
556 		is_extractable = TRUE;
557 	key_gattrs[known_attr_cnt++] = privkey_attrs[0];
558 
559 	if (is_extractable) {
560 	/* Now wrap the key, then unwrap it */
561 	CK_BYTE	aes_key_val[16] = {
562 		1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
563 	static CK_BYTE aes_param[16] = {
564 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
565 	CK_MECHANISM aes_cbc_pad_mech = {CKM_AES_CBC_PAD, aes_param, 16};
566 	CK_OBJECT_HANDLE aes_key_obj, sess_privkey_obj;
567 	CK_BYTE *wrapped_privkey;
568 	CK_ULONG wrapped_privkey_len;
569 
570 	CK_ATTRIBUTE unwrap_tmpl[] = {
571 		/* code below depends on the following attribute order */
572 		{CKA_TOKEN, &false, sizeof (false)},
573 		{CKA_CLASS, &privkey_class, sizeof (privkey_class)},
574 		{CKA_KEY_TYPE, &privkey_type, sizeof (privkey_type)},
575 		{CKA_SENSITIVE, &false, sizeof (false)},
576 		{CKA_PRIVATE, &false, sizeof (false)}
577 	};
578 
579 	rv = SUNW_C_KeyToObject(sess, CKM_AES_CBC_PAD, aes_key_val, 16,
580 	    &aes_key_obj);
581 
582 	if (rv != CKR_OK) {
583 		(void) fprintf(stderr,
584 		    "Cannot create wrapping key. error = %s\n",
585 		    pkcs11_strerror(rv));
586 		return (NULL);
587 	}
588 
589 	/* get the size of the wrapped key */
590 	rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj,
591 	    NULL, &wrapped_privkey_len);
592 	if (rv != CKR_OK) {
593 		(void) fprintf(stderr, "Cannot get key size. error = %s\n",
594 		    pkcs11_strerror(rv));
595 		return (NULL);
596 	}
597 
598 	wrapped_privkey = malloc(wrapped_privkey_len * sizeof (CK_BYTE));
599 	if (wrapped_privkey == NULL) {
600 		return (NULL);
601 	}
602 
603 	/* do the actual key wrapping */
604 	rv = C_WrapKey(sess, &aes_cbc_pad_mech, aes_key_obj, privkey_obj,
605 	    wrapped_privkey, &wrapped_privkey_len);
606 	if (rv != CKR_OK) {
607 		(void) fprintf(stderr, "Cannot wrap private key. error = %s\n",
608 		    pkcs11_strerror(rv));
609 		return (NULL);
610 	}
611 	(void) printf("private key successfully wrapped, "
612 		"wrapped blob length: %ld\n",
613 		wrapped_privkey_len);
614 
615 	rv = C_UnwrapKey(sess, &aes_cbc_pad_mech, aes_key_obj,
616 	    wrapped_privkey, wrapped_privkey_len,
617 	    unwrap_tmpl, 5, &sess_privkey_obj);
618 	if (rv != CKR_OK) {
619 		(void) fprintf(stderr, "Cannot unwrap private key."
620 		    " error = %s\n", pkcs11_strerror(rv));
621 		return (NULL);
622 	}
623 	(void) printf("session private key successfully unwrapped\n");
624 
625 	privkey_obj = sess_privkey_obj;
626 	/* Store the one modified attribute and the two new attributes. */
627 	key_gattrs[CKA_TOKEN_INDEX] = unwrap_tmpl[0];
628 	key_gattrs[known_attr_cnt++] = unwrap_tmpl[3];
629 	key_gattrs[known_attr_cnt++] = unwrap_tmpl[4];
630 	}
631 
632 	return (pkcs11_to_kssl(sess, privkey_obj, !is_extractable, bufsize,
633 	    token_label_padded, passphrase, ulPinLen));
634 }
635 
636 #define	MAX_OPENSSL_ATTR_CNT	8
637 
638 /*
639  * See the comments for pkcs11_to_kssl() for the layout of the
640  * returned buffer.
641  */
642 static kssl_params_t *
643 openssl_to_kssl(RSA *rsa, int ncerts, uchar_t *cert_bufs[], int *cert_sizes,
644     int *paramsize)
645 {
646 	int i, tcsize;
647 	kssl_params_t *kssl_params;
648 	kssl_key_t *key;
649 	char *buf;
650 	uint32_t bufsize;
651 	kssl_object_attribute_t kssl_attrs[MAX_OPENSSL_ATTR_CNT];
652 	kssl_object_attribute_t kssl_tmpl_attrs[MAX_OPENSSL_ATTR_CNT] = {
653 		{SUN_CKA_MODULUS, NULL, 0},
654 		{SUN_CKA_PUBLIC_EXPONENT, NULL, 0},
655 		{SUN_CKA_PRIVATE_EXPONENT, NULL, 0},
656 		{SUN_CKA_PRIME_1, NULL, 0},
657 		{SUN_CKA_PRIME_2, NULL, 0},
658 		{SUN_CKA_EXPONENT_1, NULL, 0},
659 		{SUN_CKA_EXPONENT_2, NULL, 0},
660 		{SUN_CKA_COEFFICIENT, NULL, 0}
661 	};
662 	BIGNUM *priv_key_bignums[MAX_OPENSSL_ATTR_CNT];
663 	int attr_cnt;
664 
665 	tcsize = 0;
666 	for (i = 0; i < ncerts; i++)
667 		tcsize += cert_sizes[i];
668 
669 	bufsize = sizeof (kssl_params_t);
670 	bufsize += (tcsize + MAX_CHAIN_LENGTH * sizeof (uint32_t));
671 
672 	/* and the key attributes */
673 	priv_key_bignums[0] = rsa->n;		/* MODULUS */
674 	priv_key_bignums[1] = rsa->e; 		/* PUBLIC_EXPONENT */
675 	priv_key_bignums[2] = rsa->d; 		/* PRIVATE_EXPONENT */
676 	priv_key_bignums[3] = rsa->p;		/* PRIME_1 */
677 	priv_key_bignums[4] = rsa->q;		/* PRIME_2 */
678 	priv_key_bignums[5] = rsa->dmp1;	/* EXPONENT_1 */
679 	priv_key_bignums[6] = rsa->dmq1;	/* EXPONENT_2 */
680 	priv_key_bignums[7] = rsa->iqmp;	/* COEFFICIENT */
681 
682 	if (rsa->n == NULL || rsa->d == NULL) {
683 		(void) fprintf(stderr,
684 		    "missing required attributes in private key.\n");
685 		return (NULL);
686 	}
687 
688 	attr_cnt = 0;
689 	for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) {
690 		if (priv_key_bignums[i] == NULL)
691 			continue;
692 		kssl_attrs[attr_cnt].ka_type = kssl_tmpl_attrs[i].ka_type;
693 		kssl_attrs[attr_cnt].ka_value_len =
694 		    BN_num_bytes(priv_key_bignums[i]);
695 		bufsize += sizeof (crypto_object_attribute_t) +
696 		    kssl_attrs[attr_cnt].ka_value_len;
697 		attr_cnt++;
698 	}
699 
700 	/* Add 4-byte cushion as sc_sizes[0] needs 32-bit alignment */
701 	bufsize += sizeof (uint32_t);
702 
703 	/* Now the big memory allocation */
704 	if ((buf = calloc(bufsize, 1)) == NULL) {
705 		(void) fprintf(stderr,
706 		    "Cannot allocate memory for the kssl_params "
707 		    "and values\n");
708 		return (NULL);
709 	}
710 
711 	/* LINTED */
712 	kssl_params = (kssl_params_t *)buf;
713 
714 	buf = (char *)(kssl_params + 1);
715 
716 	/* the keys attributes structs array */
717 	key = &kssl_params->kssl_privkey;
718 	key->ks_format = CRYPTO_KEY_ATTR_LIST;
719 	key->ks_count = attr_cnt;
720 	key->ks_attrs_offset = buf - (char *)kssl_params;
721 	buf += attr_cnt * sizeof (kssl_object_attribute_t);
722 
723 	attr_cnt = 0;
724 	/* then the key attributes values */
725 	for (i = 0; i < MAX_OPENSSL_ATTR_CNT; i++) {
726 		if (priv_key_bignums[i] == NULL)
727 			continue;
728 		(void) BN_bn2bin(priv_key_bignums[i], (unsigned char *)buf);
729 		kssl_attrs[attr_cnt].ka_value_offset =
730 		    buf - (char *)kssl_params;
731 		buf += kssl_attrs[attr_cnt].ka_value_len;
732 		attr_cnt++;
733 	}
734 
735 	bcopy(kssl_attrs, ((char *)kssl_params) + key->ks_attrs_offset,
736 	    attr_cnt * sizeof (kssl_object_attribute_t));
737 
738 	buf = (char *)P2ROUNDUP((uintptr_t)buf, sizeof (uint32_t));
739 	kssl_params->kssl_certs.sc_count = ncerts;
740 	bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t));
741 	kssl_params->kssl_certs.sc_sizes_offset = buf - (char *)kssl_params;
742 	buf += MAX_CHAIN_LENGTH * sizeof (uint32_t);
743 
744 	kssl_params->kssl_certs.sc_certs_offset = buf - (char *)kssl_params;
745 	/* now the certs values */
746 	for (i = 0; i < ncerts; i++) {
747 		bcopy(cert_bufs[i], buf, cert_sizes[i]);
748 		buf += cert_sizes[i];
749 	}
750 
751 	*paramsize = bufsize;
752 	return (kssl_params);
753 }
754 
755 static kssl_params_t *
756 add_cacerts(kssl_params_t *old_params, const char *cacert_chain_file,
757     const char *password_file)
758 {
759 	int i, ncerts, newlen;
760 	int *cert_sizes;
761 	uint32_t certlen = 0;
762 	char *buf;
763 	uchar_t **cert_bufs;
764 	kssl_params_t *kssl_params;
765 
766 	ncerts = 0;
767 	cert_bufs = PEM_get_rsa_key_certs(cacert_chain_file,
768 	    (char *)password_file, NULL, &cert_sizes, &ncerts);
769 	if (cert_bufs == NULL || ncerts == 0) {
770 		bzero(old_params, old_params->kssl_params_size);
771 		free(old_params);
772 		return (NULL);
773 	}
774 
775 	if (verbose) {
776 		(void) printf("%d certificates read successfully\n", ncerts);
777 	}
778 
779 	newlen = old_params->kssl_params_size;
780 	for (i = 0; i < ncerts; i++)
781 		newlen += cert_sizes[i];
782 
783 	/*
784 	 * Get a bigger structure and update the
785 	 * fields to account for the additional certs.
786 	 */
787 	kssl_params = realloc(old_params, newlen);
788 
789 	kssl_params->kssl_params_size = newlen;
790 	kssl_params->kssl_certs.sc_count += ncerts;
791 
792 	/* Put the cert_sizes starting from sc_sizes[1] */
793 	buf = (char *)kssl_params;
794 	buf += kssl_params->kssl_certs.sc_sizes_offset;
795 	bcopy(buf, &certlen, sizeof (uint32_t));
796 	buf += sizeof (uint32_t);
797 	bcopy(cert_sizes, buf, ncerts * sizeof (uint32_t));
798 
799 	/* Put the cert_bufs starting from sc_certs[1] */
800 	buf = (char *)kssl_params;
801 	buf += kssl_params->kssl_certs.sc_certs_offset;
802 	buf += certlen;
803 
804 	/* now the certs values */
805 	for (i = 0; i < ncerts; i++) {
806 		bcopy(cert_bufs[i], buf, cert_sizes[i]);
807 		buf += cert_sizes[i];
808 	}
809 
810 	for (i = 0; i < ncerts; i++)
811 		free(cert_bufs[i]);
812 	free(cert_bufs);
813 	free(cert_sizes);
814 
815 	return (kssl_params);
816 }
817 
818 static kssl_params_t *
819 load_from_pem(const char *filename, const char *password_file, int *paramsize)
820 {
821 	uchar_t **cert_bufs;
822 	int *cert_sizes, ncerts, i;
823 	RSA *rsa;
824 	kssl_params_t *kssl_params;
825 
826 	ncerts = 0;
827 	cert_bufs = PEM_get_rsa_key_certs(filename, (char *)password_file,
828 	    &rsa, &cert_sizes, &ncerts);
829 	if (rsa == NULL || cert_bufs == NULL || ncerts == 0) {
830 		return (NULL);
831 	}
832 
833 	if (verbose)
834 		(void) printf("%d certificates read successfully\n", ncerts);
835 
836 	kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs,
837 	    cert_sizes, paramsize);
838 
839 	for (i = 0; i < ncerts; i++)
840 		free(cert_bufs[i]);
841 	free(cert_bufs);
842 	free(cert_sizes);
843 	RSA_free(rsa);
844 	return (kssl_params);
845 }
846 
847 static kssl_params_t *
848 load_from_pkcs12(const char *filename, const char *password_file,
849     int *paramsize)
850 {
851 	RSA *rsa;
852 	kssl_params_t *kssl_params;
853 	uchar_t **cert_bufs;
854 	int *cert_sizes, ncerts, i;
855 
856 	ncerts = 0;
857 	cert_bufs = PKCS12_get_rsa_key_certs(filename, password_file, &rsa,
858 	    &cert_sizes, &ncerts);
859 	if (cert_bufs == NULL || ncerts == 0) {
860 		(void) fprintf(stderr,
861 		    "Unable to read cert and/or key from %s\n", filename);
862 		return (NULL);
863 	}
864 
865 	if (verbose)
866 		(void) printf("%d certificates read successfully\n", ncerts);
867 
868 	kssl_params = openssl_to_kssl(rsa, ncerts, cert_bufs,
869 	    cert_sizes, paramsize);
870 
871 	for (i = 0; i < ncerts; i++)
872 		free(cert_bufs[i]);
873 	free(cert_bufs);
874 	free(cert_sizes);
875 
876 	RSA_free(rsa);
877 	return (kssl_params);
878 }
879 
880 
881 int
882 parse_and_set_addr(char *server_address, char *server_port,
883     struct sockaddr_in *addr)
884 {
885 	if (server_port == NULL) {
886 		return (-1);
887 	}
888 
889 	if (server_address == NULL) {
890 		addr->sin_addr.s_addr = INADDR_ANY;
891 	} else {
892 		addr->sin_addr.s_addr = inet_addr(server_address);
893 		if ((int)addr->sin_addr.s_addr == -1) {
894 			struct hostent *hp;
895 
896 			if ((hp = gethostbyname(server_address)) == NULL) {
897 				(void) fprintf(stderr,
898 				    "Error: Unknown host: %s\n",
899 				    server_address);
900 				return (-1);
901 			}
902 
903 			(void) memcpy(&addr->sin_addr.s_addr,
904 			    hp->h_addr_list[0],
905 			    sizeof (addr->sin_addr.s_addr));
906 		}
907 	}
908 
909 	errno = 0;
910 	addr->sin_port = strtol(server_port, NULL, 10);
911 	if (addr->sin_port == 0 || errno != 0) {
912 		(void) fprintf(stderr, "Error: Invalid Port value: %s\n",
913 		    server_port);
914 		return (-1);
915 	}
916 
917 	return (0);
918 }
919 
920 /*
921  * The order of the ciphers is important. It is used as the
922  * default order (when -c is not specified).
923  */
924 struct csuite {
925 	const char *suite;
926 	uint16_t val;
927 	boolean_t seen;
928 } cipher_suites[CIPHER_SUITE_COUNT - 1] = {
929 	{"rsa_rc4_128_sha", SSL_RSA_WITH_RC4_128_SHA, B_FALSE},
930 	{"rsa_rc4_128_md5", SSL_RSA_WITH_RC4_128_MD5, B_FALSE},
931 	{"rsa_3des_ede_cbc_sha", SSL_RSA_WITH_3DES_EDE_CBC_SHA, B_FALSE},
932 	{"rsa_des_cbc_sha", SSL_RSA_WITH_DES_CBC_SHA, B_FALSE},
933 };
934 
935 static int
936 check_suites(char *suites, uint16_t *sarray)
937 {
938 	int i;
939 	int err = 0;
940 	char *suite;
941 	int sindx = 0;
942 
943 	if (suites != NULL) {
944 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
945 			sarray[i] = CIPHER_NOTSET;
946 	} else {
947 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++)
948 			sarray[i] = cipher_suites[i].val;
949 		return (err);
950 	}
951 
952 	suite = strtok(suites, ",");
953 	do {
954 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
955 			if (strcasecmp(suite, cipher_suites[i].suite) == 0) {
956 				if (!cipher_suites[i].seen) {
957 					sarray[sindx++] = cipher_suites[i].val;
958 					cipher_suites[i].seen = B_TRUE;
959 				}
960 				break;
961 			}
962 		}
963 
964 		if (i == (CIPHER_SUITE_COUNT - 1)) {
965 			(void) fprintf(stderr,
966 			    "Unknown Cipher suite name: %s\n", suite);
967 			err++;
968 		}
969 	} while ((suite = strtok(NULL, ",")) != NULL);
970 
971 	return (err);
972 }
973 
974 int
975 do_create(int argc, char *argv[])
976 {
977 	const char *softtoken_dir = NULL;
978 	const char *token_label = NULL;
979 	const char *password_file = NULL;
980 	const char *cert_key_file = NULL;
981 	const char *cacert_chain_file = NULL;
982 	const char *certname = NULL;
983 	char *suites = NULL;
984 	uint32_t timeout = DEFAULT_SID_TIMEOUT;
985 	uint32_t scache_size = DEFAULT_SID_CACHE_NENTRIES;
986 	uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
987 	int proxy_port = -1;
988 	struct sockaddr_in server_addr;
989 	char *format = NULL;
990 	char *port, *addr;
991 	char c;
992 	int pcnt;
993 	kssl_params_t *kssl_params;
994 	int bufsize;
995 
996 	argc -= 1;
997 	argv += 1;
998 
999 	while ((c = getopt(argc, argv, "vT:d:f:h:i:p:c:C:t:x:z:")) != -1) {
1000 		switch (c) {
1001 		case 'd':
1002 			softtoken_dir = optarg;
1003 			break;
1004 		case 'c':
1005 			suites = optarg;
1006 			break;
1007 		case 'C':
1008 			certname = optarg;
1009 			break;
1010 		case 'f':
1011 			format = optarg;
1012 			break;
1013 		case 'h':
1014 			cacert_chain_file = optarg;
1015 			break;
1016 		case 'i':
1017 			cert_key_file = optarg;
1018 			break;
1019 		case 'T':
1020 			token_label = optarg;
1021 			break;
1022 		case 'p':
1023 			password_file = optarg;
1024 			break;
1025 		case 't':
1026 			timeout = atoi(optarg);
1027 			break;
1028 		case 'x':
1029 			proxy_port = atoi(optarg);
1030 			break;
1031 		case 'v':
1032 			verbose = B_TRUE;
1033 			break;
1034 		case 'z':
1035 			scache_size = atoi(optarg);
1036 			break;
1037 		default:
1038 			goto err;
1039 		}
1040 	}
1041 
1042 	pcnt = argc - optind;
1043 	if (pcnt == 0) {
1044 		port = "443";	/* default SSL port */
1045 		addr = NULL;
1046 	} else if (pcnt == 1) {
1047 		port = argv[optind];
1048 		addr = NULL;
1049 	} else if (pcnt == 2) {
1050 		addr = argv[optind];
1051 		port = argv[optind + 1];
1052 	} else {
1053 		goto err;
1054 	}
1055 
1056 	if (parse_and_set_addr(addr, port, &server_addr) < 0) {
1057 		goto err;
1058 	}
1059 
1060 	if (verbose) {
1061 		(void) printf("addr=%s, port = %d\n",
1062 		    inet_ntoa(server_addr.sin_addr), server_addr.sin_port);
1063 	}
1064 
1065 	if (format == NULL || proxy_port == -1) {
1066 		goto err;
1067 	}
1068 
1069 	if (check_suites(suites, kssl_suites) != 0) {
1070 		goto err;
1071 	}
1072 
1073 	if (strcmp(format, "pkcs11") == 0) {
1074 		if (token_label == NULL || certname == NULL) {
1075 			goto err;
1076 		}
1077 		if (softtoken_dir != NULL) {
1078 			(void) setenv("SOFTTOKEN_DIR", softtoken_dir, 1);
1079 			if (verbose) {
1080 				(void) printf(
1081 				    "SOFTTOKEN_DIR=%s\n",
1082 				    getenv("SOFTTOKEN_DIR"));
1083 			}
1084 		}
1085 		kssl_params = load_from_pkcs11(
1086 		    token_label, password_file, certname, &bufsize);
1087 	} else if (strcmp(format, "pkcs12") == 0) {
1088 		if (cert_key_file == NULL) {
1089 			goto err;
1090 		}
1091 		kssl_params = load_from_pkcs12(
1092 		    cert_key_file, password_file, &bufsize);
1093 	} else if (strcmp(format, "pem") == 0) {
1094 		if (cert_key_file == NULL) {
1095 			goto err;
1096 		}
1097 		kssl_params = load_from_pem(
1098 		    cert_key_file, password_file, &bufsize);
1099 	} else {
1100 		(void) fprintf(stderr, "Unsupported cert format: %s\n", format);
1101 		goto err;
1102 	}
1103 
1104 	if (kssl_params == NULL) {
1105 		return (FAILURE);
1106 	}
1107 
1108 	bcopy(kssl_suites, kssl_params->kssl_suites,
1109 	    sizeof (kssl_params->kssl_suites));
1110 	kssl_params->kssl_params_size = bufsize;
1111 	kssl_params->kssl_addr = server_addr;
1112 	kssl_params->kssl_session_cache_timeout = timeout;
1113 	kssl_params->kssl_proxy_port = proxy_port;
1114 	kssl_params->kssl_session_cache_size = scache_size;
1115 
1116 	if (cacert_chain_file != NULL) {
1117 		kssl_params = add_cacerts(kssl_params, cacert_chain_file,
1118 		    password_file);
1119 		if (kssl_params == NULL) {
1120 			return (FAILURE);
1121 		}
1122 	}
1123 
1124 	if (kssl_send_command((char *)kssl_params, KSSL_ADD_ENTRY) < 0) {
1125 		int err = CRYPTO_FAILED;
1126 
1127 		if (kssl_params->kssl_is_nxkey)
1128 			err = kssl_params->kssl_token.ck_rv;
1129 		(void) fprintf(stderr,
1130 		    "Error loading cert and key: 0x%x\n", err);
1131 		return (FAILURE);
1132 	}
1133 
1134 	if (verbose)
1135 		(void) printf("Successfully loaded cert and key\n");
1136 
1137 	bzero(kssl_params, bufsize);
1138 	free(kssl_params);
1139 	return (SUCCESS);
1140 
1141 err:
1142 	usage_create(B_TRUE);
1143 	return (SMF_EXIT_ERR_CONFIG);
1144 }
1145