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