xref: /titanic_51/usr/src/uts/common/inet/kssl/ksslioctl.c (revision 19449258028e6813f0b7a606b554b2fa37a390ec)
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  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * The kernel SSL module ioctls.
28  */
29 
30 #include <sys/types.h>
31 #include <sys/modctl.h>
32 #include <sys/conf.h>
33 #include <sys/ddi.h>
34 #include <sys/sunddi.h>
35 #include <sys/kmem.h>
36 #include <sys/errno.h>
37 #include <sys/file.h>
38 #include <sys/cred.h>
39 #include <sys/proc.h>
40 #include <sys/task.h>
41 #include <sys/model.h>
42 #include <sys/sysmacros.h>
43 #include <sys/policy.h>
44 #include <sys/crypto/common.h>
45 #include <sys/crypto/api.h>
46 #include <inet/common.h>
47 #include <inet/ip.h>
48 
49 #include "ksslimpl.h"
50 #include "kssl.h"
51 #include "ksslproto.h"
52 
53 kssl_entry_t **kssl_entry_tab;
54 int kssl_entry_tab_size;
55 int kssl_entry_tab_nentries;
56 uint_t null_cipher_suite;	/* setable in /etc/system */
57 kmutex_t kssl_tab_mutex;
58 
59 static void
60 certificate_free(Certificate_t *cert)
61 {
62 	kmem_free(cert->msg, cert->len);
63 	kmem_free(cert, sizeof (struct Certificate));
64 }
65 
66 static void
67 privateKey_free(crypto_key_t *privkey)
68 {
69 	int i;
70 	size_t attrs_size;
71 	crypto_object_attribute_t *attrs;
72 
73 	attrs = privkey->ck_attrs;
74 	attrs_size = privkey->ck_count * sizeof (crypto_object_attribute_t);
75 	for (i = 0; i < privkey->ck_count; i++) {
76 		bzero(attrs[i].oa_value, attrs[i].oa_value_len);
77 		kmem_free(attrs[i].oa_value, attrs[i].oa_value_len);
78 	}
79 	kmem_free(attrs, attrs_size);
80 	kmem_free(privkey, sizeof (crypto_key_t));
81 }
82 
83 static void
84 sess_free(kssl_session_info_t *s)
85 {
86 	if (s->is_valid_handle) {
87 		(void) crypto_session_logout(s->prov, s->sid, NULL);
88 		(void) crypto_session_close(s->prov, s->sid, NULL);
89 		crypto_release_provider(s->prov);
90 		s->is_valid_handle = B_FALSE;
91 	}
92 
93 	if (s->evnt_handle != NULL) {
94 		crypto_unnotify_events(s->evnt_handle);
95 		s->evnt_handle = NULL;
96 	}
97 
98 	bzero(s->tokpin, s->pinlen);
99 	kmem_free(s, sizeof (kssl_session_info_t) + s->pinlen);
100 }
101 
102 /*
103  * Frees the space for the entry and the keys and certs
104  * it carries.
105  */
106 void
107 kssl_free_entry(kssl_entry_t *kssl_entry)
108 {
109 	int i;
110 	Certificate_t *cert;
111 	crypto_key_t *privkey;
112 	kssl_session_info_t *s;
113 
114 	if (kssl_entry->ke_no_freeall) {
115 		kmem_free(kssl_entry, sizeof (kssl_entry_t));
116 		return;
117 	}
118 
119 	if ((cert = kssl_entry->ke_server_certificate) != NULL) {
120 		certificate_free(cert);
121 	}
122 
123 	if ((privkey = kssl_entry->ke_private_key) != NULL) {
124 		privateKey_free(privkey);
125 	}
126 
127 	for (i = 0; i < kssl_entry->sid_cache_nentries; i++)
128 		mutex_destroy(&(kssl_entry->sid_cache[i].se_lock));
129 
130 	kmem_free(kssl_entry->sid_cache,
131 	    kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t));
132 
133 	ASSERT(kssl_entry->ke_proxy_head == NULL);
134 	ASSERT(kssl_entry->ke_fallback_head == NULL);
135 
136 	if ((s = kssl_entry->ke_sessinfo) != NULL) {
137 		ASSERT(kssl_entry->ke_is_nxkey);
138 		sess_free(s);
139 	}
140 
141 	kmem_free(kssl_entry, sizeof (kssl_entry_t));
142 }
143 
144 /*
145  * Returns the index of the entry in kssl_entry_tab[] that matches
146  * the address and port.  Returns -1 if no match is found.
147  */
148 static int
149 kssl_find_entry(in6_addr_t laddr, in_port_t port, int type,
150     boolean_t wild_card_match)
151 {
152 	int i;
153 	kssl_entry_t *ep;
154 
155 	ASSERT(MUTEX_HELD(&kssl_tab_mutex));
156 
157 	for (i = 0; i < kssl_entry_tab_size; i++) {
158 		ep = kssl_entry_tab[i];
159 		if (ep == NULL)
160 			continue;
161 
162 		if (!((type == IS_SSL_PORT && ep->ke_ssl_port == port) ||
163 		    (type == IS_PROXY_PORT && ep->ke_proxy_port == port)))
164 			continue;
165 
166 		if (IN6_ARE_ADDR_EQUAL(&laddr, &ep->ke_laddr) ||
167 		    (wild_card_match && (IN6_IS_ADDR_UNSPECIFIED(&laddr) ||
168 		    IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr))))
169 			break;
170 	}
171 
172 	if (i == kssl_entry_tab_size)
173 		return (-1);
174 
175 	return (i);
176 }
177 
178 static void
179 copy_int_to_bytearray(int x, uchar_t *buf)
180 {
181 	buf[0] = (x >> 16) & 0xff;
182 	buf[1] = (x >> 8) & 0xff;
183 	buf[2] = (x) & 0xff;
184 }
185 
186 static int
187 extract_certificate(kssl_params_t *kssl_params, Certificate_t **certpp)
188 {
189 	int i, len;
190 	uint64_t in_size;
191 	uchar_t *end_pos;
192 	uint32_t ncert;
193 	uint32_t *cert_sizes;
194 	Certificate_t *cert;
195 	char *begin = (char *)kssl_params;
196 	uchar_t *cert_buf;
197 	int cert_buf_len;
198 	uchar_t *cert_from, *cert_to;
199 
200 	ASSERT(kssl_params);
201 
202 	in_size = kssl_params->kssl_params_size;
203 	end_pos = (uchar_t *)kssl_params + in_size;
204 
205 	/*
206 	 * Get the certs array. First the array of sizes, then the actual
207 	 * certs.
208 	 */
209 	ncert = kssl_params->kssl_certs.sc_count;
210 
211 	if (ncert == 0) {
212 		/* no certs in here! why did ya call? */
213 		return (EINVAL);
214 	}
215 	if (in_size < (sizeof (kssl_params_t) + ncert * sizeof (uint32_t))) {
216 		return (EINVAL);
217 	}
218 
219 	/* Trusting that the system call preserved the 4-byte alignment */
220 	cert_sizes = (uint32_t *)(begin +
221 	    kssl_params->kssl_certs.sc_sizes_offset);
222 
223 	/* should this be an ASSERT()? */
224 	if (!IS_P2ALIGNED(cert_sizes, sizeof (uint32_t))) {
225 		return (EINVAL);
226 	}
227 
228 	len = 0;
229 	for (i = 0; i < ncert; i++) {
230 		if (cert_sizes[i] < 1) {
231 			return (EINVAL);
232 		}
233 		len += cert_sizes[i] + 3;
234 	}
235 
236 	len += 3;	/* length of certificate message without msg header */
237 
238 	cert_buf_len = len + 4 + 4;	/* add space for msg headers */
239 
240 	cert_buf = kmem_alloc(cert_buf_len, KM_SLEEP);
241 
242 	cert_buf[0] = (uchar_t)certificate;
243 	copy_int_to_bytearray(len, & cert_buf[1]);
244 	copy_int_to_bytearray(len - 3, & cert_buf[4]);
245 
246 	cert_from = (uchar_t *)(begin +
247 	    kssl_params->kssl_certs.sc_certs_offset);
248 	cert_to = &cert_buf[7];
249 
250 	for (i = 0; i < ncert; i++) {
251 		copy_int_to_bytearray(cert_sizes[i], cert_to);
252 		cert_to += 3;
253 
254 		if (cert_from + cert_sizes[i] > end_pos) {
255 			kmem_free(cert_buf, cert_buf_len);
256 			return (EINVAL);
257 		}
258 
259 		bcopy(cert_from, cert_to, cert_sizes[i]);
260 		cert_from += cert_sizes[i];
261 		cert_to += cert_sizes[i];
262 	}
263 
264 	len += 4;
265 	cert_buf[len] = (uchar_t)server_hello_done;
266 	copy_int_to_bytearray(0, & cert_buf[len + 1]);
267 
268 	cert = kmem_alloc(sizeof (Certificate_t), KM_SLEEP);
269 	cert->msg = cert_buf;
270 	cert->len = cert_buf_len;
271 
272 	*certpp = cert;
273 
274 	return (0);
275 }
276 
277 static int
278 extract_private_key(kssl_params_t *kssl_params, crypto_key_t **privkey)
279 {
280 	char *begin = (char *)kssl_params;
281 	char *end_pos;
282 	int i, j, rv;
283 	size_t attrs_size;
284 	crypto_object_attribute_t *newattrs;
285 	char *mp_attrs;
286 	kssl_object_attribute_t att;
287 	char *attval;
288 	uint32_t attlen;
289 	crypto_key_t *kssl_privkey;
290 
291 	end_pos = (char *)kssl_params + kssl_params->kssl_params_size;
292 
293 	kssl_privkey = kmem_alloc(sizeof (crypto_key_t), KM_SLEEP);
294 
295 	kssl_privkey->ck_format = kssl_params->kssl_privkey.ks_format;
296 	kssl_privkey->ck_count = kssl_params->kssl_privkey.ks_count;
297 
298 	switch (kssl_privkey->ck_format) {
299 		case CRYPTO_KEY_ATTR_LIST:
300 			break;
301 		case CRYPTO_KEY_RAW:
302 		case CRYPTO_KEY_REFERENCE:
303 		default:
304 			rv = EINVAL;
305 			goto err1;
306 	}
307 
308 	/* allocate the attributes */
309 	attrs_size = kssl_privkey->ck_count *
310 	    sizeof (crypto_object_attribute_t);
311 
312 	mp_attrs = begin + kssl_params->kssl_privkey.ks_attrs_offset;
313 	if (mp_attrs + attrs_size > end_pos) {
314 		rv = EINVAL;
315 		goto err1;
316 	}
317 
318 	newattrs = kmem_alloc(attrs_size, KM_SLEEP);
319 
320 	/* Now the individual attributes */
321 	for (i = 0; i < kssl_privkey->ck_count; i++) {
322 		bcopy(mp_attrs, &att, sizeof (kssl_object_attribute_t));
323 
324 		mp_attrs += sizeof (kssl_object_attribute_t);
325 
326 		attval = begin + att.ka_value_offset;
327 		attlen = att.ka_value_len;
328 
329 		if (attval + attlen > end_pos) {
330 			rv = EINVAL;
331 			goto err2;
332 		}
333 
334 		newattrs[i].oa_type = att.ka_type;
335 		newattrs[i].oa_value_len = attlen;
336 		newattrs[i].oa_value = kmem_alloc(attlen, KM_SLEEP);
337 
338 		bcopy(attval, newattrs[i].oa_value, attlen);
339 	}
340 
341 	kssl_privkey->ck_attrs = newattrs;
342 
343 	*privkey = kssl_privkey;
344 
345 	return (0);
346 
347 err2:
348 	for (j = 0; j < i; j++) {
349 		bzero(newattrs[j].oa_value, newattrs[j].oa_value_len);
350 		kmem_free(newattrs[j].oa_value, newattrs[j].oa_value_len);
351 	}
352 	kmem_free(newattrs, attrs_size);
353 err1:
354 	kmem_free(kssl_privkey, sizeof (crypto_key_t));
355 	return (rv);
356 }
357 
358 static int
359 create_sessinfo(kssl_params_t *kssl_params, kssl_entry_t *kssl_entry)
360 {
361 	int rv;
362 	char *p;
363 	kssl_session_info_t *s;
364 	kssl_tokinfo_t *t;
365 
366 	t =  &kssl_params->kssl_token;
367 	/* Do a sanity check */
368 	if (t->pinlen > MAX_PIN_LENGTH) {
369 		return (EINVAL);
370 	}
371 
372 	s = kmem_zalloc(sizeof (kssl_session_info_t) + t->pinlen, KM_SLEEP);
373 	s->pinlen = t->pinlen;
374 	bcopy(t->toklabel, s->toklabel, CRYPTO_EXT_SIZE_LABEL);
375 	p = (char *)kssl_params + t->tokpin_offset;
376 	bcopy(p, s->tokpin, s->pinlen);
377 	ASSERT(kssl_entry->ke_sessinfo == NULL);
378 	kssl_entry->ke_sessinfo = s;
379 
380 	/* Get the handle to the non extractable key */
381 	rv = kssl_get_obj_handle(kssl_entry);
382 	kssl_params->kssl_token.ck_rv = rv;
383 	if (rv != CRYPTO_SUCCESS) {
384 		sess_free(s);
385 		kssl_entry->ke_sessinfo = NULL;
386 		return (EINVAL);
387 	}
388 
389 	kssl_entry->ke_sessinfo->is_valid_handle = B_TRUE;
390 	kssl_entry->ke_sessinfo->do_reauth = B_FALSE;
391 	kssl_entry->ke_sessinfo->evnt_handle =
392 	    crypto_notify_events(kssl_prov_evnt,
393 	    CRYPTO_EVENT_PROVIDER_REGISTERED |
394 	    CRYPTO_EVENT_PROVIDER_UNREGISTERED);
395 
396 	return (0);
397 }
398 
399 static kssl_entry_t *
400 create_kssl_entry(kssl_params_t *kssl_params, Certificate_t *cert,
401     crypto_key_t *privkey)
402 {
403 	int i;
404 	uint16_t s;
405 	kssl_entry_t *kssl_entry, *ep;
406 	uint_t cnt, mech_count;
407 	crypto_mech_name_t *mechs;
408 	boolean_t got_rsa, got_md5, got_sha1, got_rc4, got_des, got_3des;
409 	boolean_t got_aes;
410 
411 	kssl_entry = kmem_zalloc(sizeof (kssl_entry_t), KM_SLEEP);
412 
413 	kssl_entry->ke_laddr = kssl_params->kssl_addr.sin6_addr;
414 	kssl_entry->ke_ssl_port = kssl_params->kssl_addr.sin6_port;
415 	kssl_entry->ke_proxy_port = kssl_params->kssl_proxy_port;
416 	if (kssl_params->kssl_session_cache_timeout == 0)
417 		kssl_entry->sid_cache_timeout = DEFAULT_SID_TIMEOUT;
418 	else
419 		kssl_entry->sid_cache_timeout =
420 		    kssl_params->kssl_session_cache_timeout;
421 	if (kssl_params->kssl_session_cache_size == 0)
422 		kssl_entry->sid_cache_nentries = DEFAULT_SID_CACHE_NENTRIES;
423 	else
424 		kssl_entry->sid_cache_nentries =
425 		    kssl_params->kssl_session_cache_size;
426 	kssl_entry->ke_private_key = privkey;
427 	kssl_entry->ke_server_certificate = cert;
428 
429 	kssl_entry->ke_is_nxkey = kssl_params->kssl_is_nxkey;
430 	if (kssl_entry->ke_is_nxkey) {
431 		if (create_sessinfo(kssl_params, kssl_entry) != 0) {
432 			kmem_free(kssl_entry, sizeof (kssl_entry_t));
433 			return (NULL);
434 		}
435 	}
436 
437 	mechs = crypto_get_mech_list(&mech_count, KM_SLEEP);
438 	if (mechs != NULL) {
439 		got_rsa = got_md5 = got_sha1 = got_rc4 =
440 		    got_des = got_3des = got_aes = B_FALSE;
441 		for (i = 0; i < mech_count; i++) {
442 			if (strncmp(SUN_CKM_RSA_X_509, mechs[i],
443 			    CRYPTO_MAX_MECH_NAME) == 0)
444 				got_rsa = B_TRUE;
445 			else if (strncmp(SUN_CKM_MD5_HMAC, mechs[i],
446 			    CRYPTO_MAX_MECH_NAME) == 0)
447 				got_md5 = B_TRUE;
448 			else if (strncmp(SUN_CKM_SHA1_HMAC, mechs[i],
449 			    CRYPTO_MAX_MECH_NAME) == 0)
450 				got_sha1 = B_TRUE;
451 			else if (strncmp(SUN_CKM_RC4, mechs[i],
452 			    CRYPTO_MAX_MECH_NAME) == 0)
453 				got_rc4 = B_TRUE;
454 			else if (strncmp(SUN_CKM_DES_CBC, mechs[i],
455 			    CRYPTO_MAX_MECH_NAME) == 0)
456 				got_des = B_TRUE;
457 			else if (strncmp(SUN_CKM_DES3_CBC, mechs[i],
458 			    CRYPTO_MAX_MECH_NAME) == 0)
459 				got_3des = B_TRUE;
460 			else if (strncmp(SUN_CKM_AES_CBC, mechs[i],
461 			    CRYPTO_MAX_MECH_NAME) == 0)
462 				got_aes = B_TRUE;
463 		}
464 
465 		cnt = 0;
466 		ep = kssl_entry;
467 		for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
468 			switch (s = kssl_params->kssl_suites[i]) {
469 			case SSL_RSA_WITH_RC4_128_MD5:
470 				if (got_rsa && got_rc4 && got_md5)
471 					ep->kssl_cipherSuites[cnt++] = s;
472 				break;
473 			case SSL_RSA_WITH_RC4_128_SHA:
474 				if (got_rsa && got_rc4 && got_sha1)
475 					ep->kssl_cipherSuites[cnt++] = s;
476 				break;
477 			case SSL_RSA_WITH_DES_CBC_SHA:
478 				if (got_rsa && got_des && got_sha1)
479 					ep->kssl_cipherSuites[cnt++] = s;
480 				break;
481 			case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
482 				if (got_rsa && got_3des && got_sha1)
483 					ep->kssl_cipherSuites[cnt++] = s;
484 				break;
485 			case TLS_RSA_WITH_AES_128_CBC_SHA:
486 				if (got_rsa && got_aes && got_sha1)
487 					ep->kssl_cipherSuites[cnt++] = s;
488 				break;
489 			case TLS_RSA_WITH_AES_256_CBC_SHA:
490 				if (got_rsa && got_aes && got_sha1)
491 					ep->kssl_cipherSuites[cnt++] = s;
492 				break;
493 			case CIPHER_NOTSET:
494 			default:
495 				break;
496 			}
497 		}
498 
499 		crypto_free_mech_list(mechs, mech_count);
500 	}
501 
502 	/*
503 	 * Add the no encryption suite to the end if requested by the
504 	 * kssl:null_cipher_suite /etc/system tunable since we do not want
505 	 * to be running with it by default.
506 	 */
507 	if (null_cipher_suite && got_rsa && got_sha1)
508 		kssl_entry->kssl_cipherSuites[cnt++] = SSL_RSA_WITH_NULL_SHA;
509 	kssl_entry->kssl_cipherSuites_nentries = cnt;
510 	for (i = 0; i < cnt; i++)
511 		kssl_entry->kssl_saved_Suites[i] =
512 		    kssl_entry->kssl_cipherSuites[i];
513 
514 	kssl_entry->sid_cache = kmem_alloc(
515 	    kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t), KM_SLEEP);
516 
517 	for (i = 0; i < kssl_entry->sid_cache_nentries; i++) {
518 		mutex_init(&(kssl_entry->sid_cache[i].se_lock), NULL,
519 		    MUTEX_DEFAULT, NULL);
520 		kssl_entry->sid_cache[i].se_used = 0;
521 		kssl_entry->sid_cache[i].se_sid.cached = B_FALSE;
522 	}
523 
524 	KSSL_ENTRY_REFHOLD(kssl_entry);
525 
526 	return (kssl_entry);
527 }
528 
529 int
530 kssl_add_entry(kssl_params_t *kssl_params)
531 {
532 	int rv, index, i;
533 	Certificate_t *cert;
534 	crypto_key_t *privkey;
535 	kssl_entry_t *kssl_entry;
536 	in6_addr_t laddr;
537 
538 	if ((rv = extract_certificate(kssl_params, &cert)) != 0) {
539 		return (rv);
540 	}
541 
542 	if ((rv = extract_private_key(kssl_params, &privkey)) != 0) {
543 		certificate_free(cert);
544 		return (rv);
545 	}
546 
547 	kssl_entry = create_kssl_entry(kssl_params, cert, privkey);
548 	if (kssl_entry == NULL) {
549 		certificate_free(cert);
550 		privateKey_free(privkey);
551 		return (EINVAL);
552 	}
553 
554 	laddr = kssl_params->kssl_addr.sin6_addr;
555 
556 retry:
557 	mutex_enter(&kssl_tab_mutex);
558 	/* Allocate the array first time here */
559 	if (kssl_entry_tab == NULL) {
560 		size_t allocsize;
561 		kssl_entry_t **tmp_tab;
562 		int tmp_size;
563 
564 		tmp_size = KSSL_TAB_INITSIZE;
565 		allocsize = tmp_size * sizeof (kssl_entry_t *);
566 		mutex_exit(&kssl_tab_mutex);
567 		tmp_tab = kmem_zalloc(allocsize, KM_SLEEP);
568 		mutex_enter(&kssl_tab_mutex);
569 		if (kssl_entry_tab != NULL) {
570 			mutex_exit(&kssl_tab_mutex);
571 			kmem_free(tmp_tab, allocsize);
572 			goto retry;
573 		}
574 		kssl_entry_tab_size = tmp_size;
575 		kssl_entry_tab = tmp_tab;
576 		index = 0;
577 	} else {
578 		/* Check if a matching entry exists already */
579 		index = kssl_find_entry(laddr,
580 		    kssl_params->kssl_addr.sin6_port, IS_SSL_PORT, B_TRUE);
581 
582 		if (index == -1) {
583 			/* Check if an entry with the same proxy port exists */
584 			if (kssl_find_entry(laddr, kssl_params->kssl_proxy_port,
585 			    IS_PROXY_PORT, B_TRUE) != -1) {
586 				mutex_exit(&kssl_tab_mutex);
587 				kssl_free_entry(kssl_entry);
588 				return (EADDRINUSE);
589 			}
590 
591 			/* No matching entry, find an empty spot */
592 			for (i = 0; i < kssl_entry_tab_size; i++) {
593 				if (kssl_entry_tab[i] == NULL)
594 					break;
595 			}
596 			/* Table full. Gotta grow it */
597 			if (i == kssl_entry_tab_size) {
598 				kssl_entry_t **new_tab, **old_tab;
599 				size_t allocsize;
600 				size_t oldtabsize = kssl_entry_tab_size *
601 				    sizeof (kssl_entry_t *);
602 				int tmp_size, old_size;
603 
604 				tmp_size = old_size = kssl_entry_tab_size;
605 				tmp_size += KSSL_TAB_INITSIZE;
606 				allocsize = tmp_size * sizeof (kssl_entry_t *);
607 				mutex_exit(&kssl_tab_mutex);
608 				new_tab = kmem_zalloc(allocsize, KM_SLEEP);
609 				mutex_enter(&kssl_tab_mutex);
610 				if (kssl_entry_tab_size > old_size) {
611 					mutex_exit(&kssl_tab_mutex);
612 					kmem_free(new_tab, allocsize);
613 					goto retry;
614 				}
615 
616 				kssl_entry_tab_size = tmp_size;
617 				bcopy(kssl_entry_tab, new_tab, oldtabsize);
618 
619 				old_tab = kssl_entry_tab;
620 				kssl_entry_tab = new_tab;
621 
622 				kmem_free(old_tab, oldtabsize);
623 			}
624 			index = i;
625 		} else {
626 			kssl_entry_t *ep;
627 
628 			/*
629 			 * We do not want an entry with a specific address and
630 			 * an entry with IN_ADDR_ANY to coexist. We could
631 			 * replace the existing entry. But, most likely this
632 			 * is misconfiguration. Better bail out with an error.
633 			 */
634 			ep = kssl_entry_tab[index];
635 
636 			if ((IN6_IS_ADDR_UNSPECIFIED(&laddr) &&
637 			    !IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr)) ||
638 			    (!IN6_IS_ADDR_UNSPECIFIED(&laddr) &&
639 			    IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr))) {
640 				mutex_exit(&kssl_tab_mutex);
641 				kssl_free_entry(kssl_entry);
642 				return (EEXIST);
643 			}
644 
645 			/* Replace the existing entry */
646 			KSSL_ENTRY_REFRELE(kssl_entry_tab[index]);
647 			kssl_entry_tab[index] = NULL;
648 			kssl_entry_tab_nentries--;
649 		}
650 	}
651 
652 	kssl_entry_tab[index] = kssl_entry;
653 	kssl_entry_tab_nentries++;
654 	mutex_exit(&kssl_tab_mutex);
655 
656 	return (0);
657 }
658 
659 int
660 kssl_delete_entry(struct sockaddr_in6 *kssl_addr)
661 {
662 	in6_addr_t laddr;
663 	int index;
664 
665 	laddr = kssl_addr->sin6_addr;
666 
667 	mutex_enter(&kssl_tab_mutex);
668 	index = kssl_find_entry(laddr, kssl_addr->sin6_port,
669 	    IS_SSL_PORT, B_FALSE);
670 
671 	if (index == -1) {
672 		mutex_exit(&kssl_tab_mutex);
673 		return (ENOENT);
674 	}
675 
676 	KSSL_ENTRY_REFRELE(kssl_entry_tab[index]);
677 	kssl_entry_tab[index] = NULL;
678 	kssl_entry_tab_nentries--;
679 
680 	mutex_exit(&kssl_tab_mutex);
681 
682 	return (0);
683 }
684 
685 /*
686  * We care about only one private key object.
687  * So, set the max count to only 1.
688  */
689 #define	MAX_OBJECT_COUNT	1
690 
691 /*
692  * Open a session to the provider specified by the label and
693  * authenticate to it. Find the private key object with the
694  * specified  attributes and save the handle. The userland component
695  * must set all the attributes in the template so as to uniquely
696  * identify the object.
697  *
698  * Note that the handle will be invalid if we logout or close
699  * the session to the provider.
700  */
701 int
702 kssl_get_obj_handle(kssl_entry_t *kp)
703 {
704 	int rv;
705 	unsigned int count;
706 	void *cookie = NULL;
707 	crypto_provider_t prov;
708 	kssl_session_info_t *s;
709 	crypto_session_id_t sid;
710 	crypto_object_attribute_t *attrs;
711 	crypto_object_id_t ohndl[MAX_OBJECT_COUNT];
712 	char label[CRYPTO_EXT_SIZE_LABEL + 1];
713 
714 	ASSERT(kp->ke_is_nxkey);
715 	s = kp->ke_sessinfo;
716 
717 	bcopy(s->toklabel, label, CRYPTO_EXT_SIZE_LABEL);
718 	label[CRYPTO_EXT_SIZE_LABEL] = '\0';
719 	prov = crypto_get_provider(label, NULL, NULL);
720 	if (prov == NULL)
721 		return (CRYPTO_UNKNOWN_PROVIDER);
722 
723 	rv = crypto_session_open(prov, &sid, NULL);
724 	if (rv != CRYPTO_SUCCESS) {
725 		goto err1;
726 	}
727 
728 	rv = crypto_session_login(prov, sid, CRYPTO_USER,
729 	    s->tokpin, s->pinlen, NULL);
730 	if (rv != CRYPTO_SUCCESS) {
731 		goto err2;
732 	}
733 
734 	count = kp->ke_private_key->ck_count;
735 	attrs = kp->ke_private_key->ck_attrs;
736 
737 	rv = crypto_object_find_init(prov, sid, attrs, count, &cookie, NULL);
738 	if (rv != CRYPTO_SUCCESS) {
739 		goto err3;
740 	}
741 
742 	rv = crypto_object_find(prov, cookie, ohndl, &count,
743 	    MAX_OBJECT_COUNT, NULL);
744 	if (rv != CRYPTO_SUCCESS || count == 0) {
745 		if (count == 0)
746 			rv = CRYPTO_FAILED;
747 		goto err3;
748 	}
749 
750 	(void) crypto_object_find_final(prov, cookie, NULL);
751 
752 	s->sid = sid;
753 	s->prov = prov;
754 	s->key.ck_format = CRYPTO_KEY_REFERENCE;
755 	/* Keep the handle around for later use */
756 	s->key.ck_obj_id = ohndl[0];
757 
758 	return (CRYPTO_SUCCESS);
759 
760 err3:
761 	(void) crypto_session_logout(prov, sid, NULL);
762 err2:
763 	(void) crypto_session_close(prov, sid, NULL);
764 err1:
765 	crypto_release_provider(prov);
766 	return (rv);
767 }
768