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