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