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