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 2006 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; 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 415 kssl_entry = kmem_zalloc(sizeof (kssl_entry_t), KM_SLEEP); 416 417 kssl_entry->ke_laddr = kssl_params->kssl_addr.sin_addr.s_addr; 418 kssl_entry->ke_ssl_port = kssl_params->kssl_addr.sin_port; 419 kssl_entry->ke_proxy_port = kssl_params->kssl_proxy_port; 420 if (kssl_params->kssl_session_cache_timeout == 0) 421 kssl_entry->sid_cache_timeout = DEFAULT_SID_TIMEOUT; 422 else 423 kssl_entry->sid_cache_timeout = 424 kssl_params->kssl_session_cache_timeout; 425 if (kssl_params->kssl_session_cache_size == 0) 426 kssl_entry->sid_cache_nentries = DEFAULT_SID_CACHE_NENTRIES; 427 else 428 kssl_entry->sid_cache_nentries = 429 kssl_params->kssl_session_cache_size; 430 kssl_entry->ke_private_key = privkey; 431 kssl_entry->ke_server_certificate = cert; 432 433 kssl_entry->ke_is_nxkey = kssl_params->kssl_is_nxkey; 434 if (kssl_entry->ke_is_nxkey) { 435 if (create_sessinfo(kssl_params, kssl_entry) != 0) { 436 kmem_free(kssl_entry, sizeof (kssl_entry_t)); 437 return (NULL); 438 } 439 } 440 441 mechs = crypto_get_mech_list(&mech_count, KM_SLEEP); 442 if (mechs != NULL) { 443 got_rsa = got_md5 = got_sha1 = got_rc4 = 444 got_des = got_3des = B_FALSE; 445 for (i = 0; i < mech_count; i++) { 446 if (strncmp(SUN_CKM_RSA_X_509, mechs[i], 447 CRYPTO_MAX_MECH_NAME) == 0) 448 got_rsa = B_TRUE; 449 else if (strncmp(SUN_CKM_MD5_HMAC, mechs[i], 450 CRYPTO_MAX_MECH_NAME) == 0) 451 got_md5 = B_TRUE; 452 else if (strncmp(SUN_CKM_SHA1_HMAC, mechs[i], 453 CRYPTO_MAX_MECH_NAME) == 0) 454 got_sha1 = B_TRUE; 455 else if (strncmp(SUN_CKM_RC4, mechs[i], 456 CRYPTO_MAX_MECH_NAME) == 0) 457 got_rc4 = B_TRUE; 458 else if (strncmp(SUN_CKM_DES_CBC, mechs[i], 459 CRYPTO_MAX_MECH_NAME) == 0) 460 got_des = B_TRUE; 461 else if (strncmp(SUN_CKM_DES3_CBC, mechs[i], 462 CRYPTO_MAX_MECH_NAME) == 0) 463 got_3des = B_TRUE; 464 } 465 466 cnt = 0; 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 kssl_entry->kssl_cipherSuites[cnt++] = s; 472 break; 473 case SSL_RSA_WITH_RC4_128_SHA: 474 if (got_rsa && got_rc4 && got_sha1) 475 kssl_entry->kssl_cipherSuites[cnt++] = s; 476 break; 477 case SSL_RSA_WITH_DES_CBC_SHA: 478 if (got_rsa && got_des && got_sha1) 479 kssl_entry->kssl_cipherSuites[cnt++] = s; 480 break; 481 case SSL_RSA_WITH_3DES_EDE_CBC_SHA: 482 if (got_rsa && got_3des && got_sha1) 483 kssl_entry->kssl_cipherSuites[cnt++] = s; 484 break; 485 case CIPHER_NOTSET: 486 default: 487 break; 488 } 489 } 490 491 crypto_free_mech_list(mechs, mech_count); 492 } 493 494 /* Add the no encryption suite to the end */ 495 kssl_entry->kssl_cipherSuites[cnt++] = SSL_RSA_WITH_NULL_SHA; 496 kssl_entry->kssl_cipherSuites_nentries = cnt; 497 for (i = 0; i < cnt; i++) 498 kssl_entry->kssl_saved_Suites[i] = 499 kssl_entry->kssl_cipherSuites[i]; 500 501 kssl_entry->sid_cache = kmem_alloc( 502 kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t), KM_SLEEP); 503 504 for (i = 0; i < kssl_entry->sid_cache_nentries; i++) { 505 mutex_init(&(kssl_entry->sid_cache[i].se_lock), NULL, 506 MUTEX_DEFAULT, NULL); 507 kssl_entry->sid_cache[i].se_used = 0; 508 kssl_entry->sid_cache[i].se_sid.cached = B_FALSE; 509 } 510 511 KSSL_ENTRY_REFHOLD(kssl_entry); 512 513 return (kssl_entry); 514 } 515 516 int 517 kssl_add_entry(kssl_params_t *kssl_params) 518 { 519 int rv, index, i; 520 Certificate_t *cert; 521 crypto_key_t *privkey; 522 kssl_entry_t *kssl_entry; 523 ipaddr_t laddr; 524 525 if ((rv = extract_certificate(kssl_params, &cert)) != 0) { 526 return (rv); 527 } 528 529 if ((rv = extract_private_key(kssl_params, &privkey)) != 0) { 530 certificate_free(cert); 531 return (rv); 532 } 533 534 kssl_entry = create_kssl_entry(kssl_params, cert, privkey); 535 if (kssl_entry == NULL) { 536 certificate_free(cert); 537 privateKey_free(privkey); 538 return (EINVAL); 539 } 540 541 /* Revisit here for IPv6 support */ 542 laddr = kssl_params->kssl_addr.sin_addr.s_addr; 543 544 retry: 545 mutex_enter(&kssl_tab_mutex); 546 /* Allocate the array first time here */ 547 if (kssl_entry_tab == NULL) { 548 size_t allocsize; 549 kssl_entry_t **tmp_tab; 550 int tmp_size; 551 552 tmp_size = KSSL_TAB_INITSIZE; 553 allocsize = tmp_size * sizeof (kssl_entry_t *); 554 mutex_exit(&kssl_tab_mutex); 555 tmp_tab = kmem_zalloc(allocsize, KM_SLEEP); 556 mutex_enter(&kssl_tab_mutex); 557 if (kssl_entry_tab != NULL) { 558 mutex_exit(&kssl_tab_mutex); 559 kmem_free(tmp_tab, allocsize); 560 goto retry; 561 } 562 kssl_entry_tab_size = tmp_size; 563 kssl_entry_tab = tmp_tab; 564 index = 0; 565 } else { 566 /* Check if a matching entry exists already */ 567 index = kssl_find_entry(laddr, 568 kssl_params->kssl_addr.sin_port, IS_SSL_PORT, B_TRUE); 569 570 if (index == -1) { 571 /* Check if an entry with the same proxy port exists */ 572 if (kssl_find_entry(laddr, kssl_params->kssl_proxy_port, 573 IS_PROXY_PORT, B_TRUE) != -1) { 574 mutex_exit(&kssl_tab_mutex); 575 kssl_free_entry(kssl_entry); 576 return (EADDRINUSE); 577 } 578 579 /* No matching entry, find an empty spot */ 580 for (i = 0; i < kssl_entry_tab_size; i++) { 581 if (kssl_entry_tab[i] == NULL) 582 break; 583 } 584 /* Table full. Gotta grow it */ 585 if (i == kssl_entry_tab_size) { 586 kssl_entry_t **new_tab, **old_tab; 587 size_t allocsize; 588 size_t oldtabsize = kssl_entry_tab_size * 589 sizeof (kssl_entry_t *); 590 int tmp_size, old_size; 591 592 tmp_size = old_size = kssl_entry_tab_size; 593 tmp_size += KSSL_TAB_INITSIZE; 594 allocsize = tmp_size * sizeof (kssl_entry_t *); 595 mutex_exit(&kssl_tab_mutex); 596 new_tab = kmem_zalloc(allocsize, KM_SLEEP); 597 mutex_enter(&kssl_tab_mutex); 598 if (kssl_entry_tab_size > old_size) { 599 mutex_exit(&kssl_tab_mutex); 600 kmem_free(new_tab, allocsize); 601 goto retry; 602 } 603 604 kssl_entry_tab_size = tmp_size; 605 bcopy(kssl_entry_tab, new_tab, oldtabsize); 606 607 old_tab = kssl_entry_tab; 608 kssl_entry_tab = new_tab; 609 610 kmem_free(old_tab, oldtabsize); 611 } 612 index = i; 613 } else { 614 /* 615 * We do not want an entry with a specific address and 616 * an entry with IN_ADDR_ANY to coexist. We could 617 * replace the existing entry. But, most likely this 618 * is misconfiguration. Better bail out with an error. 619 */ 620 if ((laddr == INADDR_ANY && 621 (kssl_entry_tab[index]->ke_laddr != INADDR_ANY)) || 622 (laddr != INADDR_ANY && 623 (kssl_entry_tab[index]->ke_laddr == INADDR_ANY))) { 624 mutex_exit(&kssl_tab_mutex); 625 kssl_free_entry(kssl_entry); 626 return (EEXIST); 627 } 628 629 /* Replace the existing entry */ 630 KSSL_ENTRY_REFRELE(kssl_entry_tab[index]); 631 kssl_entry_tab[index] = NULL; 632 kssl_entry_tab_nentries--; 633 } 634 } 635 636 kssl_entry_tab[index] = kssl_entry; 637 kssl_entry_tab_nentries++; 638 mutex_exit(&kssl_tab_mutex); 639 640 return (0); 641 } 642 643 int 644 kssl_delete_entry(struct sockaddr_in *kssl_addr) 645 { 646 ipaddr_t laddr; 647 int index; 648 649 /* Revisit here for IPv6 support */ 650 laddr = kssl_addr->sin_addr.s_addr; 651 652 mutex_enter(&kssl_tab_mutex); 653 index = kssl_find_entry(laddr, kssl_addr->sin_port, 654 IS_SSL_PORT, B_FALSE); 655 656 if (index == -1) { 657 mutex_exit(&kssl_tab_mutex); 658 return (ENOENT); 659 } 660 661 KSSL_ENTRY_REFRELE(kssl_entry_tab[index]); 662 kssl_entry_tab[index] = NULL; 663 kssl_entry_tab_nentries--; 664 665 mutex_exit(&kssl_tab_mutex); 666 667 return (0); 668 } 669 670 /* 671 * We care about only one private key object. 672 * So, set the max count to only 1. 673 */ 674 #define MAX_OBJECT_COUNT 1 675 676 /* 677 * Open a session to the provider specified by the label and 678 * authenticate to it. Find the private key object with the 679 * specified attributes and save the handle. The userland component 680 * must set all the attributes in the template so as to uniquely 681 * identify the object. 682 * 683 * Note that the handle will be invalid if we logout or close 684 * the session to the provider. 685 */ 686 int 687 kssl_get_obj_handle(kssl_entry_t *kp) 688 { 689 int rv; 690 unsigned int count; 691 void *cookie = NULL; 692 crypto_provider_t prov; 693 kssl_session_info_t *s; 694 crypto_session_id_t sid; 695 crypto_object_attribute_t *attrs; 696 crypto_object_id_t ohndl[MAX_OBJECT_COUNT]; 697 char label[CRYPTO_EXT_SIZE_LABEL + 1]; 698 699 ASSERT(kp->ke_is_nxkey); 700 s = kp->ke_sessinfo; 701 702 bcopy(s->toklabel, label, CRYPTO_EXT_SIZE_LABEL); 703 label[CRYPTO_EXT_SIZE_LABEL] = '\0'; 704 prov = crypto_get_provider(label, NULL, NULL); 705 if (prov == NULL) 706 return (CRYPTO_UNKNOWN_PROVIDER); 707 708 rv = crypto_session_open(prov, &sid, NULL); 709 if (rv != CRYPTO_SUCCESS) { 710 goto err1; 711 } 712 713 rv = crypto_session_login(prov, sid, CRYPTO_USER, 714 s->tokpin, s->pinlen, NULL); 715 if (rv != CRYPTO_SUCCESS) { 716 goto err2; 717 } 718 719 count = kp->ke_private_key->ck_count; 720 attrs = kp->ke_private_key->ck_attrs; 721 722 rv = crypto_object_find_init(prov, sid, attrs, count, &cookie, NULL); 723 if (rv != CRYPTO_SUCCESS) { 724 goto err3; 725 } 726 727 rv = crypto_object_find(prov, cookie, ohndl, &count, 728 MAX_OBJECT_COUNT, NULL); 729 if (rv != CRYPTO_SUCCESS || count == 0) { 730 if (count == 0) 731 rv = CRYPTO_FAILED; 732 goto err3; 733 } 734 735 (void) crypto_object_find_final(prov, cookie, NULL); 736 737 s->sid = sid; 738 s->prov = prov; 739 s->key.ck_format = CRYPTO_KEY_REFERENCE; 740 /* Keep the handle around for later use */ 741 s->key.ck_obj_id = ohndl[0]; 742 743 return (CRYPTO_SUCCESS); 744 745 err3: 746 (void) crypto_session_logout(prov, sid, NULL); 747 err2: 748 (void) crypto_session_close(prov, sid, NULL); 749 err1: 750 crypto_release_provider(prov); 751 return (rv); 752 } 753