1898Skais /* 2898Skais * CDDL HEADER START 3898Skais * 4898Skais * The contents of this file are subject to the terms of the 52800Skrishna * Common Development and Distribution License (the "License"). 62800Skrishna * You may not use this file except in compliance with the License. 7898Skais * 8898Skais * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9898Skais * or http://www.opensolaris.org/os/licensing. 10898Skais * See the License for the specific language governing permissions 11898Skais * and limitations under the License. 12898Skais * 13898Skais * When distributing Covered Code, include this CDDL HEADER in each 14898Skais * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15898Skais * If applicable, add the following below this CDDL HEADER, with the 16898Skais * fields enclosed by brackets "[]" replaced with your own identifying 17898Skais * information: Portions Copyright [yyyy] [name of copyright owner] 18898Skais * 19898Skais * CDDL HEADER END 20898Skais */ 21898Skais /* 22*10520SBhargava.Yenduri@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23898Skais * Use is subject to license terms. 24898Skais */ 25898Skais 26898Skais /* 27898Skais * The kernel SSL module ioctls. 28898Skais */ 29898Skais 30898Skais #include <sys/types.h> 31898Skais #include <sys/modctl.h> 32898Skais #include <sys/conf.h> 33898Skais #include <sys/ddi.h> 34898Skais #include <sys/sunddi.h> 35898Skais #include <sys/kmem.h> 36898Skais #include <sys/errno.h> 37898Skais #include <sys/file.h> 38898Skais #include <sys/cred.h> 39898Skais #include <sys/proc.h> 40898Skais #include <sys/task.h> 41898Skais #include <sys/model.h> 42898Skais #include <sys/sysmacros.h> 43898Skais #include <sys/policy.h> 44898Skais #include <sys/crypto/common.h> 45898Skais #include <sys/crypto/api.h> 46898Skais #include <inet/common.h> 47898Skais #include <inet/ip.h> 48898Skais 49898Skais #include "ksslimpl.h" 50898Skais #include "kssl.h" 51898Skais #include "ksslproto.h" 52898Skais 53898Skais kssl_entry_t **kssl_entry_tab; 54898Skais int kssl_entry_tab_size; 55898Skais int kssl_entry_tab_nentries; 56898Skais kmutex_t kssl_tab_mutex; 57898Skais 58898Skais static void 59898Skais certificate_free(Certificate_t *cert) 60898Skais { 61898Skais kmem_free(cert->msg, cert->len); 62898Skais kmem_free(cert, sizeof (struct Certificate)); 63898Skais } 64898Skais 65898Skais static void 66898Skais privateKey_free(crypto_key_t *privkey) 67898Skais { 682800Skrishna int i; 692800Skrishna size_t attrs_size; 702800Skrishna crypto_object_attribute_t *attrs; 71898Skais 722800Skrishna attrs = privkey->ck_attrs; 732800Skrishna attrs_size = privkey->ck_count * sizeof (crypto_object_attribute_t); 74898Skais for (i = 0; i < privkey->ck_count; i++) { 75898Skais bzero(attrs[i].oa_value, attrs[i].oa_value_len); 76898Skais kmem_free(attrs[i].oa_value, attrs[i].oa_value_len); 77898Skais } 78898Skais kmem_free(attrs, attrs_size); 79898Skais kmem_free(privkey, sizeof (crypto_key_t)); 80898Skais } 81898Skais 822800Skrishna static void 832800Skrishna sess_free(kssl_session_info_t *s) 842800Skrishna { 852800Skrishna if (s->is_valid_handle) { 862800Skrishna (void) crypto_session_logout(s->prov, s->sid, NULL); 872800Skrishna (void) crypto_session_close(s->prov, s->sid, NULL); 882800Skrishna crypto_release_provider(s->prov); 892800Skrishna s->is_valid_handle = B_FALSE; 902800Skrishna } 912800Skrishna 922800Skrishna if (s->evnt_handle != NULL) { 932800Skrishna crypto_unnotify_events(s->evnt_handle); 942800Skrishna s->evnt_handle = NULL; 952800Skrishna } 962800Skrishna 972800Skrishna bzero(s->tokpin, s->pinlen); 982800Skrishna kmem_free(s, sizeof (kssl_session_info_t) + s->pinlen); 992800Skrishna } 1002800Skrishna 101898Skais /* 102898Skais * Frees the space for the entry and the keys and certs 103898Skais * it carries. 104898Skais */ 105898Skais void 106898Skais kssl_free_entry(kssl_entry_t *kssl_entry) 107898Skais { 108898Skais int i; 109898Skais Certificate_t *cert; 110898Skais crypto_key_t *privkey; 1112800Skrishna kssl_session_info_t *s; 112898Skais 113898Skais if (kssl_entry->ke_no_freeall) { 114898Skais kmem_free(kssl_entry, sizeof (kssl_entry_t)); 115898Skais return; 116898Skais } 117898Skais 118898Skais if ((cert = kssl_entry->ke_server_certificate) != NULL) { 119898Skais certificate_free(cert); 120898Skais } 121898Skais 122898Skais if ((privkey = kssl_entry->ke_private_key) != NULL) { 123898Skais privateKey_free(privkey); 1242800Skrishna } 125898Skais 126898Skais for (i = 0; i < kssl_entry->sid_cache_nentries; i++) 127898Skais mutex_destroy(&(kssl_entry->sid_cache[i].se_lock)); 128898Skais 129898Skais kmem_free(kssl_entry->sid_cache, 130898Skais kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t)); 131898Skais 132898Skais ASSERT(kssl_entry->ke_proxy_head == NULL); 133898Skais ASSERT(kssl_entry->ke_fallback_head == NULL); 134898Skais 1352800Skrishna if ((s = kssl_entry->ke_sessinfo) != NULL) { 1362800Skrishna ASSERT(kssl_entry->ke_is_nxkey); 1372800Skrishna sess_free(s); 1382800Skrishna } 1392800Skrishna 140898Skais kmem_free(kssl_entry, sizeof (kssl_entry_t)); 141898Skais } 142898Skais 143898Skais /* 144898Skais * Returns the index of the entry in kssl_entry_tab[] that matches 145898Skais * the address and port. Returns -1 if no match is found. 146898Skais */ 147898Skais static int 148*10520SBhargava.Yenduri@Sun.COM kssl_find_entry(in6_addr_t laddr, in_port_t port, int type, 149898Skais boolean_t wild_card_match) 150898Skais { 151898Skais int i; 152898Skais kssl_entry_t *ep; 153898Skais 154898Skais ASSERT(MUTEX_HELD(&kssl_tab_mutex)); 155898Skais 156898Skais for (i = 0; i < kssl_entry_tab_size; i++) { 157898Skais ep = kssl_entry_tab[i]; 158898Skais if (ep == NULL) 159898Skais continue; 160898Skais 161898Skais if (!((type == IS_SSL_PORT && ep->ke_ssl_port == port) || 162898Skais (type == IS_PROXY_PORT && ep->ke_proxy_port == port))) 163898Skais continue; 164898Skais 165*10520SBhargava.Yenduri@Sun.COM if (IN6_ARE_ADDR_EQUAL(&laddr, &ep->ke_laddr) || 166*10520SBhargava.Yenduri@Sun.COM (wild_card_match && (IN6_IS_ADDR_UNSPECIFIED(&laddr) || 167*10520SBhargava.Yenduri@Sun.COM IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr)))) 168898Skais break; 169898Skais } 170898Skais 171898Skais if (i == kssl_entry_tab_size) 172898Skais return (-1); 173898Skais 174898Skais return (i); 175898Skais } 176898Skais 177898Skais static void 178898Skais copy_int_to_bytearray(int x, uchar_t *buf) 179898Skais { 180898Skais buf[0] = (x >> 16) & 0xff; 181898Skais buf[1] = (x >> 8) & 0xff; 182898Skais buf[2] = (x) & 0xff; 183898Skais } 184898Skais 185898Skais static int 186898Skais extract_certificate(kssl_params_t *kssl_params, Certificate_t **certpp) 187898Skais { 188898Skais int i, len; 189898Skais uint64_t in_size; 190898Skais uchar_t *end_pos; 191898Skais uint32_t ncert; 192898Skais uint32_t *cert_sizes; 193898Skais Certificate_t *cert; 194898Skais char *begin = (char *)kssl_params; 195898Skais uchar_t *cert_buf; 196898Skais int cert_buf_len; 197898Skais uchar_t *cert_from, *cert_to; 198898Skais 199898Skais ASSERT(kssl_params); 200898Skais 201898Skais in_size = kssl_params->kssl_params_size; 202898Skais end_pos = (uchar_t *)kssl_params + in_size; 203898Skais 204898Skais /* 205898Skais * Get the certs array. First the array of sizes, then the actual 206898Skais * certs. 207898Skais */ 208898Skais ncert = kssl_params->kssl_certs.sc_count; 209898Skais 210898Skais if (ncert == 0) { 211898Skais /* no certs in here! why did ya call? */ 212898Skais return (EINVAL); 213898Skais } 214898Skais if (in_size < (sizeof (kssl_params_t) + ncert * sizeof (uint32_t))) { 215898Skais return (EINVAL); 216898Skais } 217898Skais 2182800Skrishna /* Trusting that the system call preserved the 4-byte alignment */ 219898Skais cert_sizes = (uint32_t *)(begin + 220898Skais kssl_params->kssl_certs.sc_sizes_offset); 221898Skais 222898Skais /* should this be an ASSERT()? */ 223898Skais if (!IS_P2ALIGNED(cert_sizes, sizeof (uint32_t))) { 224898Skais return (EINVAL); 225898Skais } 226898Skais 227898Skais len = 0; 228898Skais for (i = 0; i < ncert; i++) { 229898Skais if (cert_sizes[i] < 1) { 230898Skais return (EINVAL); 231898Skais } 232898Skais len += cert_sizes[i] + 3; 233898Skais } 234898Skais 235898Skais len += 3; /* length of certificate message without msg header */ 236898Skais 237898Skais cert_buf_len = len + 4 + 4; /* add space for msg headers */ 238898Skais 239898Skais cert_buf = kmem_alloc(cert_buf_len, KM_SLEEP); 240898Skais 241898Skais cert_buf[0] = (uchar_t)certificate; 242898Skais copy_int_to_bytearray(len, & cert_buf[1]); 243898Skais copy_int_to_bytearray(len - 3, & cert_buf[4]); 244898Skais 245898Skais cert_from = (uchar_t *)(begin + 246898Skais kssl_params->kssl_certs.sc_certs_offset); 247898Skais cert_to = &cert_buf[7]; 248898Skais 249898Skais for (i = 0; i < ncert; i++) { 250898Skais copy_int_to_bytearray(cert_sizes[i], cert_to); 251898Skais cert_to += 3; 252898Skais 253898Skais if (cert_from + cert_sizes[i] > end_pos) { 254898Skais kmem_free(cert_buf, cert_buf_len); 255898Skais return (EINVAL); 256898Skais } 257898Skais 258898Skais bcopy(cert_from, cert_to, cert_sizes[i]); 259898Skais cert_from += cert_sizes[i]; 260898Skais cert_to += cert_sizes[i]; 261898Skais } 262898Skais 263898Skais len += 4; 264898Skais cert_buf[len] = (uchar_t)server_hello_done; 265898Skais copy_int_to_bytearray(0, & cert_buf[len + 1]); 266898Skais 267898Skais cert = kmem_alloc(sizeof (Certificate_t), KM_SLEEP); 268898Skais cert->msg = cert_buf; 269898Skais cert->len = cert_buf_len; 270898Skais 271898Skais *certpp = cert; 272898Skais 273898Skais return (0); 274898Skais } 275898Skais 276898Skais static int 277898Skais extract_private_key(kssl_params_t *kssl_params, crypto_key_t **privkey) 278898Skais { 279898Skais char *begin = (char *)kssl_params; 280898Skais char *end_pos; 281898Skais int i, j, rv; 282898Skais size_t attrs_size; 283*10520SBhargava.Yenduri@Sun.COM crypto_object_attribute_t *newattrs; 284898Skais char *mp_attrs; 285898Skais kssl_object_attribute_t att; 286898Skais char *attval; 287898Skais uint32_t attlen; 288898Skais crypto_key_t *kssl_privkey; 289898Skais 290898Skais end_pos = (char *)kssl_params + kssl_params->kssl_params_size; 291898Skais 292898Skais kssl_privkey = kmem_alloc(sizeof (crypto_key_t), KM_SLEEP); 293898Skais 294898Skais kssl_privkey->ck_format = kssl_params->kssl_privkey.ks_format; 295898Skais kssl_privkey->ck_count = kssl_params->kssl_privkey.ks_count; 296898Skais 297898Skais switch (kssl_privkey->ck_format) { 298898Skais case CRYPTO_KEY_ATTR_LIST: 299898Skais break; 300898Skais case CRYPTO_KEY_RAW: 301898Skais case CRYPTO_KEY_REFERENCE: 302898Skais default: 303898Skais rv = EINVAL; 304898Skais goto err1; 305898Skais } 306898Skais 307898Skais /* allocate the attributes */ 308898Skais attrs_size = kssl_privkey->ck_count * 309898Skais sizeof (crypto_object_attribute_t); 310898Skais 311898Skais mp_attrs = begin + kssl_params->kssl_privkey.ks_attrs_offset; 312898Skais if (mp_attrs + attrs_size > end_pos) { 313898Skais rv = EINVAL; 314898Skais goto err1; 315898Skais } 316898Skais 3172800Skrishna newattrs = kmem_alloc(attrs_size, KM_SLEEP); 3182800Skrishna 319898Skais /* Now the individual attributes */ 320898Skais for (i = 0; i < kssl_privkey->ck_count; i++) { 321898Skais bcopy(mp_attrs, &att, sizeof (kssl_object_attribute_t)); 322898Skais 323898Skais mp_attrs += sizeof (kssl_object_attribute_t); 324898Skais 325898Skais attval = begin + att.ka_value_offset; 326898Skais attlen = att.ka_value_len; 327898Skais 328898Skais if (attval + attlen > end_pos) { 329898Skais rv = EINVAL; 330898Skais goto err2; 331898Skais } 332898Skais 333898Skais newattrs[i].oa_type = att.ka_type; 334898Skais newattrs[i].oa_value_len = attlen; 3352800Skrishna newattrs[i].oa_value = kmem_alloc(attlen, KM_SLEEP); 336898Skais 337898Skais bcopy(attval, newattrs[i].oa_value, attlen); 338898Skais } 339898Skais 340898Skais kssl_privkey->ck_attrs = newattrs; 341898Skais 342898Skais *privkey = kssl_privkey; 343898Skais 344898Skais return (0); 345898Skais 346898Skais err2: 347898Skais for (j = 0; j < i; j++) { 3482800Skrishna bzero(newattrs[j].oa_value, newattrs[j].oa_value_len); 349898Skais kmem_free(newattrs[j].oa_value, newattrs[j].oa_value_len); 350898Skais } 351898Skais kmem_free(newattrs, attrs_size); 352898Skais err1: 353898Skais kmem_free(kssl_privkey, sizeof (crypto_key_t)); 354898Skais return (rv); 355898Skais } 356898Skais 3572800Skrishna static int 3582800Skrishna create_sessinfo(kssl_params_t *kssl_params, kssl_entry_t *kssl_entry) 3592800Skrishna { 3602800Skrishna int rv; 3612800Skrishna char *p; 3622800Skrishna kssl_session_info_t *s; 3632800Skrishna kssl_tokinfo_t *t; 3642800Skrishna 3652800Skrishna t = &kssl_params->kssl_token; 3662800Skrishna /* Do a sanity check */ 3672800Skrishna if (t->pinlen > MAX_PIN_LENGTH) { 3682800Skrishna return (EINVAL); 3692800Skrishna } 3702800Skrishna 3712800Skrishna s = kmem_zalloc(sizeof (kssl_session_info_t) + t->pinlen, KM_SLEEP); 3722800Skrishna s->pinlen = t->pinlen; 3732800Skrishna bcopy(t->toklabel, s->toklabel, CRYPTO_EXT_SIZE_LABEL); 3742800Skrishna p = (char *)kssl_params + t->tokpin_offset; 3752800Skrishna bcopy(p, s->tokpin, s->pinlen); 3762800Skrishna ASSERT(kssl_entry->ke_sessinfo == NULL); 3772800Skrishna kssl_entry->ke_sessinfo = s; 3782800Skrishna 3792800Skrishna /* Get the handle to the non extractable key */ 3802800Skrishna rv = kssl_get_obj_handle(kssl_entry); 3812800Skrishna kssl_params->kssl_token.ck_rv = rv; 3822800Skrishna if (rv != CRYPTO_SUCCESS) { 3832800Skrishna sess_free(s); 3842800Skrishna kssl_entry->ke_sessinfo = NULL; 3852800Skrishna return (EINVAL); 3862800Skrishna } 3872800Skrishna 3882800Skrishna kssl_entry->ke_sessinfo->is_valid_handle = B_TRUE; 3892800Skrishna kssl_entry->ke_sessinfo->do_reauth = B_FALSE; 3902800Skrishna kssl_entry->ke_sessinfo->evnt_handle = 3912800Skrishna crypto_notify_events(kssl_prov_evnt, 3926788Skrishna CRYPTO_EVENT_PROVIDER_REGISTERED | 3936788Skrishna CRYPTO_EVENT_PROVIDER_UNREGISTERED); 3942800Skrishna 3952800Skrishna return (0); 3962800Skrishna } 3972800Skrishna 398898Skais static kssl_entry_t * 399898Skais create_kssl_entry(kssl_params_t *kssl_params, Certificate_t *cert, 400898Skais crypto_key_t *privkey) 401898Skais { 402898Skais int i; 403898Skais uint16_t s; 4046788Skrishna kssl_entry_t *kssl_entry, *ep; 405898Skais uint_t cnt, mech_count; 406898Skais crypto_mech_name_t *mechs; 407898Skais boolean_t got_rsa, got_md5, got_sha1, got_rc4, got_des, got_3des; 4086788Skrishna boolean_t got_aes; 409898Skais 410898Skais kssl_entry = kmem_zalloc(sizeof (kssl_entry_t), KM_SLEEP); 411898Skais 412*10520SBhargava.Yenduri@Sun.COM kssl_entry->ke_laddr = kssl_params->kssl_addr.sin6_addr; 413*10520SBhargava.Yenduri@Sun.COM kssl_entry->ke_ssl_port = kssl_params->kssl_addr.sin6_port; 414898Skais kssl_entry->ke_proxy_port = kssl_params->kssl_proxy_port; 415898Skais if (kssl_params->kssl_session_cache_timeout == 0) 416898Skais kssl_entry->sid_cache_timeout = DEFAULT_SID_TIMEOUT; 417898Skais else 418898Skais kssl_entry->sid_cache_timeout = 419898Skais kssl_params->kssl_session_cache_timeout; 420898Skais if (kssl_params->kssl_session_cache_size == 0) 421898Skais kssl_entry->sid_cache_nentries = DEFAULT_SID_CACHE_NENTRIES; 422898Skais else 423898Skais kssl_entry->sid_cache_nentries = 424898Skais kssl_params->kssl_session_cache_size; 425898Skais kssl_entry->ke_private_key = privkey; 426898Skais kssl_entry->ke_server_certificate = cert; 427898Skais 4282800Skrishna kssl_entry->ke_is_nxkey = kssl_params->kssl_is_nxkey; 4292800Skrishna if (kssl_entry->ke_is_nxkey) { 4302800Skrishna if (create_sessinfo(kssl_params, kssl_entry) != 0) { 4312800Skrishna kmem_free(kssl_entry, sizeof (kssl_entry_t)); 4322800Skrishna return (NULL); 4332800Skrishna } 4342800Skrishna } 4352800Skrishna 436898Skais mechs = crypto_get_mech_list(&mech_count, KM_SLEEP); 437898Skais if (mechs != NULL) { 438898Skais got_rsa = got_md5 = got_sha1 = got_rc4 = 4396788Skrishna got_des = got_3des = got_aes = B_FALSE; 440898Skais for (i = 0; i < mech_count; i++) { 441898Skais if (strncmp(SUN_CKM_RSA_X_509, mechs[i], 442898Skais CRYPTO_MAX_MECH_NAME) == 0) 443898Skais got_rsa = B_TRUE; 444898Skais else if (strncmp(SUN_CKM_MD5_HMAC, mechs[i], 445898Skais CRYPTO_MAX_MECH_NAME) == 0) 446898Skais got_md5 = B_TRUE; 447898Skais else if (strncmp(SUN_CKM_SHA1_HMAC, mechs[i], 448898Skais CRYPTO_MAX_MECH_NAME) == 0) 449898Skais got_sha1 = B_TRUE; 450898Skais else if (strncmp(SUN_CKM_RC4, mechs[i], 451898Skais CRYPTO_MAX_MECH_NAME) == 0) 452898Skais got_rc4 = B_TRUE; 453898Skais else if (strncmp(SUN_CKM_DES_CBC, mechs[i], 454898Skais CRYPTO_MAX_MECH_NAME) == 0) 455898Skais got_des = B_TRUE; 456898Skais else if (strncmp(SUN_CKM_DES3_CBC, mechs[i], 457898Skais CRYPTO_MAX_MECH_NAME) == 0) 458898Skais got_3des = B_TRUE; 4596788Skrishna else if (strncmp(SUN_CKM_AES_CBC, mechs[i], 4606788Skrishna CRYPTO_MAX_MECH_NAME) == 0) 4616788Skrishna got_aes = B_TRUE; 462898Skais } 463898Skais 464898Skais cnt = 0; 4656788Skrishna ep = kssl_entry; 466898Skais for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) { 467898Skais switch (s = kssl_params->kssl_suites[i]) { 468898Skais case SSL_RSA_WITH_RC4_128_MD5: 469898Skais if (got_rsa && got_rc4 && got_md5) 4706788Skrishna ep->kssl_cipherSuites[cnt++] = s; 471898Skais break; 472898Skais case SSL_RSA_WITH_RC4_128_SHA: 473898Skais if (got_rsa && got_rc4 && got_sha1) 4746788Skrishna ep->kssl_cipherSuites[cnt++] = s; 475898Skais break; 476898Skais case SSL_RSA_WITH_DES_CBC_SHA: 477898Skais if (got_rsa && got_des && got_sha1) 4786788Skrishna ep->kssl_cipherSuites[cnt++] = s; 479898Skais break; 480898Skais case SSL_RSA_WITH_3DES_EDE_CBC_SHA: 481898Skais if (got_rsa && got_3des && got_sha1) 4826788Skrishna ep->kssl_cipherSuites[cnt++] = s; 4836788Skrishna break; 4846788Skrishna case TLS_RSA_WITH_AES_128_CBC_SHA: 4856788Skrishna if (got_rsa && got_aes && got_sha1) 4866788Skrishna ep->kssl_cipherSuites[cnt++] = s; 4876788Skrishna break; 4886788Skrishna case TLS_RSA_WITH_AES_256_CBC_SHA: 4896788Skrishna if (got_rsa && got_aes && got_sha1) 4906788Skrishna ep->kssl_cipherSuites[cnt++] = s; 491898Skais break; 492898Skais case CIPHER_NOTSET: 493898Skais default: 494898Skais break; 495898Skais } 496898Skais } 497898Skais 498898Skais crypto_free_mech_list(mechs, mech_count); 499898Skais } 500898Skais 501898Skais /* Add the no encryption suite to the end */ 502898Skais kssl_entry->kssl_cipherSuites[cnt++] = SSL_RSA_WITH_NULL_SHA; 503898Skais kssl_entry->kssl_cipherSuites_nentries = cnt; 504898Skais for (i = 0; i < cnt; i++) 505898Skais kssl_entry->kssl_saved_Suites[i] = 506898Skais kssl_entry->kssl_cipherSuites[i]; 507898Skais 508898Skais kssl_entry->sid_cache = kmem_alloc( 509898Skais kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t), KM_SLEEP); 510898Skais 511898Skais for (i = 0; i < kssl_entry->sid_cache_nentries; i++) { 512898Skais mutex_init(&(kssl_entry->sid_cache[i].se_lock), NULL, 513898Skais MUTEX_DEFAULT, NULL); 514898Skais kssl_entry->sid_cache[i].se_used = 0; 515898Skais kssl_entry->sid_cache[i].se_sid.cached = B_FALSE; 516898Skais } 517898Skais 518898Skais KSSL_ENTRY_REFHOLD(kssl_entry); 519898Skais 520898Skais return (kssl_entry); 521898Skais } 522898Skais 523898Skais int 524898Skais kssl_add_entry(kssl_params_t *kssl_params) 525898Skais { 526898Skais int rv, index, i; 527898Skais Certificate_t *cert; 528898Skais crypto_key_t *privkey; 529898Skais kssl_entry_t *kssl_entry; 530*10520SBhargava.Yenduri@Sun.COM in6_addr_t laddr; 531898Skais 532898Skais if ((rv = extract_certificate(kssl_params, &cert)) != 0) { 533898Skais return (rv); 534898Skais } 535898Skais 536898Skais if ((rv = extract_private_key(kssl_params, &privkey)) != 0) { 537898Skais certificate_free(cert); 538898Skais return (rv); 539898Skais } 540898Skais 541898Skais kssl_entry = create_kssl_entry(kssl_params, cert, privkey); 5422800Skrishna if (kssl_entry == NULL) { 5432800Skrishna certificate_free(cert); 5442800Skrishna privateKey_free(privkey); 5452800Skrishna return (EINVAL); 5462800Skrishna } 547898Skais 548*10520SBhargava.Yenduri@Sun.COM laddr = kssl_params->kssl_addr.sin6_addr; 549898Skais 550898Skais retry: 551898Skais mutex_enter(&kssl_tab_mutex); 552898Skais /* Allocate the array first time here */ 553898Skais if (kssl_entry_tab == NULL) { 554898Skais size_t allocsize; 555898Skais kssl_entry_t **tmp_tab; 556898Skais int tmp_size; 557898Skais 558898Skais tmp_size = KSSL_TAB_INITSIZE; 559898Skais allocsize = tmp_size * sizeof (kssl_entry_t *); 560898Skais mutex_exit(&kssl_tab_mutex); 561898Skais tmp_tab = kmem_zalloc(allocsize, KM_SLEEP); 562898Skais mutex_enter(&kssl_tab_mutex); 563898Skais if (kssl_entry_tab != NULL) { 564898Skais mutex_exit(&kssl_tab_mutex); 565898Skais kmem_free(tmp_tab, allocsize); 566898Skais goto retry; 567898Skais } 568898Skais kssl_entry_tab_size = tmp_size; 569898Skais kssl_entry_tab = tmp_tab; 570898Skais index = 0; 571898Skais } else { 572898Skais /* Check if a matching entry exists already */ 573898Skais index = kssl_find_entry(laddr, 574*10520SBhargava.Yenduri@Sun.COM kssl_params->kssl_addr.sin6_port, IS_SSL_PORT, B_TRUE); 575898Skais 576898Skais if (index == -1) { 577898Skais /* Check if an entry with the same proxy port exists */ 578898Skais if (kssl_find_entry(laddr, kssl_params->kssl_proxy_port, 579898Skais IS_PROXY_PORT, B_TRUE) != -1) { 580898Skais mutex_exit(&kssl_tab_mutex); 581898Skais kssl_free_entry(kssl_entry); 582898Skais return (EADDRINUSE); 583898Skais } 584898Skais 585898Skais /* No matching entry, find an empty spot */ 586898Skais for (i = 0; i < kssl_entry_tab_size; i++) { 587898Skais if (kssl_entry_tab[i] == NULL) 588898Skais break; 589898Skais } 590898Skais /* Table full. Gotta grow it */ 591898Skais if (i == kssl_entry_tab_size) { 592898Skais kssl_entry_t **new_tab, **old_tab; 593898Skais size_t allocsize; 594898Skais size_t oldtabsize = kssl_entry_tab_size * 595898Skais sizeof (kssl_entry_t *); 596898Skais int tmp_size, old_size; 597898Skais 598898Skais tmp_size = old_size = kssl_entry_tab_size; 599898Skais tmp_size += KSSL_TAB_INITSIZE; 600898Skais allocsize = tmp_size * sizeof (kssl_entry_t *); 601898Skais mutex_exit(&kssl_tab_mutex); 602898Skais new_tab = kmem_zalloc(allocsize, KM_SLEEP); 603898Skais mutex_enter(&kssl_tab_mutex); 604898Skais if (kssl_entry_tab_size > old_size) { 605898Skais mutex_exit(&kssl_tab_mutex); 606898Skais kmem_free(new_tab, allocsize); 607898Skais goto retry; 608898Skais } 609898Skais 610898Skais kssl_entry_tab_size = tmp_size; 611898Skais bcopy(kssl_entry_tab, new_tab, oldtabsize); 612898Skais 613898Skais old_tab = kssl_entry_tab; 614898Skais kssl_entry_tab = new_tab; 615898Skais 616898Skais kmem_free(old_tab, oldtabsize); 617898Skais } 618898Skais index = i; 619898Skais } else { 620*10520SBhargava.Yenduri@Sun.COM kssl_entry_t *ep; 621*10520SBhargava.Yenduri@Sun.COM 622898Skais /* 623898Skais * We do not want an entry with a specific address and 624898Skais * an entry with IN_ADDR_ANY to coexist. We could 625898Skais * replace the existing entry. But, most likely this 626898Skais * is misconfiguration. Better bail out with an error. 627898Skais */ 628*10520SBhargava.Yenduri@Sun.COM ep = kssl_entry_tab[index]; 629*10520SBhargava.Yenduri@Sun.COM 630*10520SBhargava.Yenduri@Sun.COM if ((IN6_IS_ADDR_UNSPECIFIED(&laddr) && 631*10520SBhargava.Yenduri@Sun.COM !IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr)) || 632*10520SBhargava.Yenduri@Sun.COM (!IN6_IS_ADDR_UNSPECIFIED(&laddr) && 633*10520SBhargava.Yenduri@Sun.COM IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr))) { 634898Skais mutex_exit(&kssl_tab_mutex); 635898Skais kssl_free_entry(kssl_entry); 636898Skais return (EEXIST); 637898Skais } 638898Skais 639898Skais /* Replace the existing entry */ 640898Skais KSSL_ENTRY_REFRELE(kssl_entry_tab[index]); 641898Skais kssl_entry_tab[index] = NULL; 642898Skais kssl_entry_tab_nentries--; 643898Skais } 644898Skais } 645898Skais 646898Skais kssl_entry_tab[index] = kssl_entry; 647898Skais kssl_entry_tab_nentries++; 648898Skais mutex_exit(&kssl_tab_mutex); 649898Skais 650898Skais return (0); 651898Skais } 652898Skais 653898Skais int 654*10520SBhargava.Yenduri@Sun.COM kssl_delete_entry(struct sockaddr_in6 *kssl_addr) 655898Skais { 656*10520SBhargava.Yenduri@Sun.COM in6_addr_t laddr; 657898Skais int index; 658898Skais 659*10520SBhargava.Yenduri@Sun.COM laddr = kssl_addr->sin6_addr; 660898Skais 661898Skais mutex_enter(&kssl_tab_mutex); 662*10520SBhargava.Yenduri@Sun.COM index = kssl_find_entry(laddr, kssl_addr->sin6_port, 663898Skais IS_SSL_PORT, B_FALSE); 664898Skais 665898Skais if (index == -1) { 666898Skais mutex_exit(&kssl_tab_mutex); 667898Skais return (ENOENT); 668898Skais } 669898Skais 670898Skais KSSL_ENTRY_REFRELE(kssl_entry_tab[index]); 671898Skais kssl_entry_tab[index] = NULL; 672898Skais kssl_entry_tab_nentries--; 673898Skais 674898Skais mutex_exit(&kssl_tab_mutex); 675898Skais 676898Skais return (0); 677898Skais } 6782800Skrishna 6792800Skrishna /* 6802800Skrishna * We care about only one private key object. 6812800Skrishna * So, set the max count to only 1. 6822800Skrishna */ 6832800Skrishna #define MAX_OBJECT_COUNT 1 6842800Skrishna 6852800Skrishna /* 6862800Skrishna * Open a session to the provider specified by the label and 6872800Skrishna * authenticate to it. Find the private key object with the 6882800Skrishna * specified attributes and save the handle. The userland component 6892800Skrishna * must set all the attributes in the template so as to uniquely 6902800Skrishna * identify the object. 6912800Skrishna * 6922800Skrishna * Note that the handle will be invalid if we logout or close 6932800Skrishna * the session to the provider. 6942800Skrishna */ 6952800Skrishna int 6962800Skrishna kssl_get_obj_handle(kssl_entry_t *kp) 6972800Skrishna { 6982800Skrishna int rv; 6992800Skrishna unsigned int count; 7002800Skrishna void *cookie = NULL; 7012800Skrishna crypto_provider_t prov; 7022800Skrishna kssl_session_info_t *s; 7032800Skrishna crypto_session_id_t sid; 7042800Skrishna crypto_object_attribute_t *attrs; 7052800Skrishna crypto_object_id_t ohndl[MAX_OBJECT_COUNT]; 7062800Skrishna char label[CRYPTO_EXT_SIZE_LABEL + 1]; 7072800Skrishna 7082800Skrishna ASSERT(kp->ke_is_nxkey); 7092800Skrishna s = kp->ke_sessinfo; 7102800Skrishna 7112800Skrishna bcopy(s->toklabel, label, CRYPTO_EXT_SIZE_LABEL); 7122800Skrishna label[CRYPTO_EXT_SIZE_LABEL] = '\0'; 7132800Skrishna prov = crypto_get_provider(label, NULL, NULL); 7142800Skrishna if (prov == NULL) 7152800Skrishna return (CRYPTO_UNKNOWN_PROVIDER); 7162800Skrishna 7172800Skrishna rv = crypto_session_open(prov, &sid, NULL); 7182800Skrishna if (rv != CRYPTO_SUCCESS) { 7192800Skrishna goto err1; 7202800Skrishna } 7212800Skrishna 7222800Skrishna rv = crypto_session_login(prov, sid, CRYPTO_USER, 7232800Skrishna s->tokpin, s->pinlen, NULL); 7242800Skrishna if (rv != CRYPTO_SUCCESS) { 7252800Skrishna goto err2; 7262800Skrishna } 7272800Skrishna 7282800Skrishna count = kp->ke_private_key->ck_count; 7292800Skrishna attrs = kp->ke_private_key->ck_attrs; 7302800Skrishna 7312800Skrishna rv = crypto_object_find_init(prov, sid, attrs, count, &cookie, NULL); 7322800Skrishna if (rv != CRYPTO_SUCCESS) { 7332800Skrishna goto err3; 7342800Skrishna } 7352800Skrishna 7362800Skrishna rv = crypto_object_find(prov, cookie, ohndl, &count, 7372800Skrishna MAX_OBJECT_COUNT, NULL); 7382800Skrishna if (rv != CRYPTO_SUCCESS || count == 0) { 7392800Skrishna if (count == 0) 7402800Skrishna rv = CRYPTO_FAILED; 7412800Skrishna goto err3; 7422800Skrishna } 7432800Skrishna 7442800Skrishna (void) crypto_object_find_final(prov, cookie, NULL); 7452800Skrishna 7462800Skrishna s->sid = sid; 7472800Skrishna s->prov = prov; 7482800Skrishna s->key.ck_format = CRYPTO_KEY_REFERENCE; 7492800Skrishna /* Keep the handle around for later use */ 7502800Skrishna s->key.ck_obj_id = ohndl[0]; 7512800Skrishna 7522800Skrishna return (CRYPTO_SUCCESS); 7532800Skrishna 7542800Skrishna err3: 7552800Skrishna (void) crypto_session_logout(prov, sid, NULL); 7562800Skrishna err2: 7572800Skrishna (void) crypto_session_close(prov, sid, NULL); 7582800Skrishna err1: 7592800Skrishna crypto_release_provider(prov); 7602800Skrishna return (rv); 7612800Skrishna } 762