Home | History | Annotate | Download | only in kssl
      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