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