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