summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/Makefile1
-rw-r--r--usr/src/uts/common/Makefile.files9
-rw-r--r--usr/src/uts/common/Makefile.rules6
-rw-r--r--usr/src/uts/common/c2/audit.c74
-rw-r--r--usr/src/uts/common/c2/audit.h2
-rw-r--r--usr/src/uts/common/inet/kssl/Makefile53
-rw-r--r--usr/src/uts/common/inet/kssl/kssl.c690
-rw-r--r--usr/src/uts/common/inet/kssl/kssl.conf29
-rw-r--r--usr/src/uts/common/inet/kssl/kssl.h126
-rw-r--r--usr/src/uts/common/inet/kssl/ksslapi.c1317
-rw-r--r--usr/src/uts/common/inet/kssl/ksslapi.h104
-rw-r--r--usr/src/uts/common/inet/kssl/ksslfilter.c615
-rw-r--r--usr/src/uts/common/inet/kssl/ksslimpl.h223
-rw-r--r--usr/src/uts/common/inet/kssl/ksslioctl.c767
-rw-r--r--usr/src/uts/common/inet/kssl/ksslproto.h339
-rw-r--r--usr/src/uts/common/inet/kssl/ksslrec.c2531
-rw-r--r--usr/src/uts/intel/Makefile.intel4
-rw-r--r--usr/src/uts/intel/kssl/Makefile85
-rw-r--r--usr/src/uts/intel/ksslf/Makefile82
-rw-r--r--usr/src/uts/intel/ml/modstubs.s2
-rw-r--r--usr/src/uts/sparc/Makefile.sparc4
-rw-r--r--usr/src/uts/sparc/kssl/Makefile85
-rw-r--r--usr/src/uts/sparc/ksslf/Makefile82
-rw-r--r--usr/src/uts/sparc/ml/modstubs.s2
24 files changed, 8 insertions, 7224 deletions
diff --git a/usr/src/uts/Makefile b/usr/src/uts/Makefile
index 7e83978de5..b21c920fce 100644
--- a/usr/src/uts/Makefile
+++ b/usr/src/uts/Makefile
@@ -138,7 +138,6 @@ COMMON_HDRDIRS= common/c2 \
common/klm \
common/inet \
common/inet/ipf/netinet \
- common/inet/kssl \
common/inet/nca \
common/inet/sockmods/netpacket \
common/io/bpf/net \
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 6151835e1a..0c8c23ead8 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -24,7 +24,7 @@
# Copyright (c) 2011, 2014 by Delphix. All rights reserved.
# Copyright (c) 2013 by Saso Kiselkov. All rights reserved.
# Copyright 2018 Nexenta Systems, Inc.
-# Copyright 2016 Garrett D'Amore <garrett@damore.org>
+# Copyright 2022 Garrett D'Amore <garrett@damore.org>
# Copyright 2020 Joyent, Inc.
# Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved.
# Copyright 2016 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
@@ -1639,13 +1639,6 @@ RSAPROV_OBJS += rsa.o rsa_impl.o pkcs1.o
SWRANDPROV_OBJS += swrand.o
#
-# kernel SSL
-#
-KSSL_OBJS += kssl.o ksslioctl.o
-
-KSSL_SOCKFIL_MOD_OBJS += ksslfilter.o ksslapi.o ksslrec.o
-
-#
# misc. modules
#
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index 3439c34ba0..8a535a17ec 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -21,7 +21,7 @@
#
# Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2016 Garrett D'Amore <garrett@damore.org>
+# Copyright 2022 Garrett D'Amore <garrett@damore.org>
# Copyright 2013 Saso Kiselkov. All rights reserved.
# Copyright 2019 Joyent, Inc.
# Copyright 2018 Nexenta Systems, Inc.
@@ -498,10 +498,6 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/iptun/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
-$(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/kssl/%.c
- $(COMPILE.c) -o $@ $<
- $(CTFCONVERT_O)
-
$(OBJS_DIR)/%.o: $(UTSBASE)/common/inet/sctp/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
diff --git a/usr/src/uts/common/c2/audit.c b/usr/src/uts/common/c2/audit.c
index 0553cca7b2..15d492bdb5 100644
--- a/usr/src/uts/common/c2/audit.c
+++ b/usr/src/uts/common/c2/audit.c
@@ -61,7 +61,6 @@
#include <sys/devpolicy.h>
#include <sys/crypto/ioctladmin.h>
#include <sys/cred_impl.h>
-#include <inet/kssl/kssl.h>
#include <net/pfpolicy.h>
static void add_return_token(caddr_t *, unsigned int scid, int err, int rval);
@@ -2003,79 +2002,6 @@ audit_cryptoadm(int cmd, char *module_name, crypto_mech_name_t *mech_names,
}
/*
- * Audit the kernel SSL administration command. The address and the
- * port number for the SSL instance, and the proxy port are put in the
- * audit trail.
- */
-void
-audit_kssl(int cmd, void *params, int error)
-{
- cred_t *cr = CRED();
- t_audit_data_t *tad;
- token_t *ad = NULL;
- const auditinfo_addr_t *ainfo = crgetauinfo(cr);
- au_kcontext_t *kctx = GET_KCTX_PZ;
-
- tad = U2A(u);
-
- if (ainfo == NULL)
- return;
-
- tad->tad_event = AUE_CONFIGKSSL;
-
- if (audit_success(kctx, tad, error, NULL) != AU_OK)
- return;
-
- /* Add subject information */
- AUDIT_SETSUBJ((caddr_t *)&ad, cr, ainfo, kctx);
-
- switch (cmd) {
- case KSSL_ADD_ENTRY: {
- char buf[32];
- kssl_params_t *kp = (kssl_params_t *)params;
- struct sockaddr_in6 *saddr = &kp->kssl_addr;
-
- au_write((caddr_t *)&ad, au_to_text("op=KSSL_ADD_ENTRY"));
- au_write((caddr_t *)&ad,
- au_to_in_addr_ex((int32_t *)&saddr->sin6_addr));
- (void) snprintf(buf, sizeof (buf), "SSL port=%d",
- saddr->sin6_port);
- au_write((caddr_t *)&ad, au_to_text(buf));
-
- (void) snprintf(buf, sizeof (buf), "proxy port=%d",
- kp->kssl_proxy_port);
- au_write((caddr_t *)&ad, au_to_text(buf));
- break;
- }
-
- case KSSL_DELETE_ENTRY: {
- char buf[32];
- struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)params;
-
- au_write((caddr_t *)&ad, au_to_text("op=KSSL_DELETE_ENTRY"));
- au_write((caddr_t *)&ad,
- au_to_in_addr_ex((int32_t *)&saddr->sin6_addr));
- (void) snprintf(buf, sizeof (buf), "SSL port=%d",
- saddr->sin6_port);
- au_write((caddr_t *)&ad, au_to_text(buf));
- break;
- }
-
- default:
- return;
- }
-
- /* add a return token */
- add_return_token((caddr_t *)&ad, tad->tad_scid, error, 0);
-
- AS_INC(as_generated, 1, kctx);
- AS_INC(as_kernel, 1, kctx);
-
- au_close(kctx, (caddr_t *)&ad, AU_OK, AUE_CONFIGKSSL, tad->tad_evmod,
- NULL);
-}
-
-/*
* Audit the kernel PF_POLICY administration commands. Record command,
* zone, policy type (global or tunnel, active or inactive)
*/
diff --git a/usr/src/uts/common/c2/audit.h b/usr/src/uts/common/c2/audit.h
index 27a0388b14..66539662c1 100644
--- a/usr/src/uts/common/c2/audit.h
+++ b/usr/src/uts/common/c2/audit.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2022 Garrett D'Amore <garrett@damore.org>
*/
/*
@@ -595,7 +596,6 @@ void audit_psecflags(proc_t *, psecflagwhich_t,
const secflagdelta_t *);
void audit_devpolicy(int, const struct devplcysys *);
void audit_update_context(proc_t *, cred_t *);
-void audit_kssl(int, void *, int);
void audit_pf_policy(int, cred_t *, netstack_t *, char *, boolean_t, int,
pid_t);
void audit_sec_attributes(caddr_t *, struct vnode *);
diff --git a/usr/src/uts/common/inet/kssl/Makefile b/usr/src/uts/common/inet/kssl/Makefile
deleted file mode 100644
index 47df45ba4a..0000000000
--- a/usr/src/uts/common/inet/kssl/Makefile
+++ /dev/null
@@ -1,53 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-#
-# uts/common/inet/kssl/Makefile
-#
-# include global definitions
-include ../../../../Makefile.master
-
-HDRS= kssl.h ksslapi.h ksslimpl.h ksslproto.h
-
-ROOTDIRS= $(ROOT)/usr/include/inet/kssl
-
-ROOTHDRS= $(HDRS:%=$(ROOT)/usr/include/inet/kssl/%)
-
-CHECKHDRS= $(HDRS:%.h=%.check)
-
-$(ROOTDIRS)/%: %
- $(INS.file)
-
-.KEEP_STATE:
-
-.PARALLEL: $(CHECKHDRS)
-
-install_h: $(ROOTDIRS) $(ROOTHDRS)
-
-$(ROOTDIRS):
- $(INS.dir)
-
-check: $(CHECKHDRS)
diff --git a/usr/src/uts/common/inet/kssl/kssl.c b/usr/src/uts/common/inet/kssl/kssl.c
deleted file mode 100644
index 37d10c6f84..0000000000
--- a/usr/src/uts/common/inet/kssl/kssl.c
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-
-/*
- * The system call and DDI interface for the kernel SSL module
- */
-
-#include <sys/types.h>
-#include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/stat.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/kmem.h>
-#include <sys/errno.h>
-#include <sys/file.h>
-#include <sys/open.h>
-#include <sys/cred.h>
-#include <sys/proc.h>
-#include <sys/task.h>
-#include <sys/model.h>
-#include <sys/sysmacros.h>
-#include <sys/policy.h>
-#include <sys/crypto/common.h>
-#include <sys/crypto/api.h>
-#include <c2/audit.h>
-#include <sys/kstat.h>
-
-#include "kssl.h"
-#include "ksslimpl.h"
-
-/*
- * DDI entry points.
- */
-static int kssl_attach(dev_info_t *, ddi_attach_cmd_t);
-static int kssl_detach(dev_info_t *, ddi_detach_cmd_t);
-static int kssl_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
-static int kssl_open(dev_t *, int, int, cred_t *);
-static int kssl_close(dev_t, int, int, cred_t *);
-static int kssl_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
-
-static int kssl_constructor(void *buf, void *arg, int kmflags);
-static void kssl_destructor(void *buf, void *arg);
-
-/*
- * Module linkage.
- */
-static struct cb_ops cbops = {
- kssl_open, /* cb_open */
- kssl_close, /* cb_close */
- nodev, /* cb_strategy */
- nodev, /* cb_print */
- nodev, /* cb_dump */
- nodev, /* cb_read */
- nodev, /* cb_write */
- kssl_ioctl, /* cb_ioctl */
- nodev, /* cb_devmap */
- nodev, /* cb_mmap */
- nodev, /* cb_segmap */
- nochpoll, /* cb_chpoll */
- ddi_prop_op, /* cb_prop_op */
- NULL, /* cb_streamtab */
- D_MP, /* cb_flag */
- CB_REV, /* cb_rev */
- nodev, /* cb_aread */
- nodev, /* cb_awrite */
-};
-
-static struct dev_ops devops = {
- DEVO_REV, /* devo_rev */
- 0, /* devo_refcnt */
- kssl_getinfo, /* devo_getinfo */
- nulldev, /* devo_identify */
- nulldev, /* devo_probe */
- kssl_attach, /* devo_attach */
- kssl_detach, /* devo_detach */
- nodev, /* devo_reset */
- &cbops, /* devo_cb_ops */
- NULL, /* devo_bus_ops */
- NULL, /* devo_power */
- ddi_quiesce_not_needed, /* devo_quiesce */
-};
-
-static struct modldrv modldrv = {
- &mod_driverops, /* drv_modops */
- "Kernel SSL Interface", /* drv_linkinfo */
- &devops,
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1, /* ml_rev */
- &modldrv, /* ml_linkage */
- NULL
-};
-
-static dev_info_t *kssl_dip = NULL;
-
-crypto_mechanism_t rsa_x509_mech = {CRYPTO_MECH_INVALID, NULL, 0};
-crypto_mechanism_t hmac_md5_mech = {CRYPTO_MECH_INVALID, NULL, 0};
-crypto_mechanism_t hmac_sha1_mech = {CRYPTO_MECH_INVALID, NULL, 0};
-crypto_call_flag_t kssl_call_flag = CRYPTO_ALWAYS_QUEUE;
-
-KSSLCipherDef cipher_defs[] = { /* indexed by SSL3BulkCipher */
- /* type bsize keysz crypto_mech_type_t */
-
- {type_stream, 0, 0, CRYPTO_MECH_INVALID},
-
- /* mech_type to be initialized with CKM_RC4's */
- {type_stream, 0, 16, CRYPTO_MECH_INVALID},
-
- /* mech_type to be initialized with CKM_DES_CBC's */
- {type_block, 8, 8, CRYPTO_MECH_INVALID},
-
- /* mech_type to be initialized with CKM_DES3_CBC's */
- {type_block, 8, 24, CRYPTO_MECH_INVALID},
-
- /* mech_type to be initialized with CKM_AES_CBC with 128-bit key */
- {type_block, 16, 16, CRYPTO_MECH_INVALID},
-
- /* mech_type to be initialized with CKM_AES_CBC with 256-bit key */
- {type_block, 16, 32, CRYPTO_MECH_INVALID},
-};
-
-struct kmem_cache *kssl_cache;
-static crypto_notify_handle_t prov_update_handle = NULL;
-
-static void kssl_global_init();
-static void kssl_global_fini();
-static void kssl_init_mechs();
-static void kssl_event_callback(uint32_t, void *);
-
-/*
- * DDI entry points.
- */
-int
-_init(void)
-{
- int error;
-
- kssl_global_init();
-
- if ((error = mod_install(&modlinkage)) != 0) {
- kssl_global_fini();
- return (error);
- }
- return (0);
-}
-
-int
-_fini(void)
-{
- int error;
-
- if ((error = mod_remove(&modlinkage)) != 0)
- return (error);
-
- if (prov_update_handle != NULL)
- crypto_unnotify_events(prov_update_handle);
-
- kssl_global_fini();
-
- return (0);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-/* ARGSUSED */
-static int
-kssl_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
-{
- switch (cmd) {
- case DDI_INFO_DEVT2DEVINFO:
- *result = kssl_dip;
- return (DDI_SUCCESS);
-
- case DDI_INFO_DEVT2INSTANCE:
- *result = (void *)0;
- return (DDI_SUCCESS);
- }
- return (DDI_FAILURE);
-}
-
-static int
-kssl_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
-{
- if (cmd != DDI_ATTACH) {
- return (DDI_FAILURE);
- }
-
- if (ddi_get_instance(dip) != 0) {
- /* we only allow instance 0 to attach */
- return (DDI_FAILURE);
- }
-
- /* create the minor node */
- if (ddi_create_minor_node(dip, "kssl", S_IFCHR, 0, DDI_PSEUDO, 0) !=
- DDI_SUCCESS) {
- cmn_err(CE_WARN, "kssl_attach: failed creating minor node");
- ddi_remove_minor_node(dip, NULL);
- return (DDI_FAILURE);
- }
-
- kssl_dip = dip;
-
- return (DDI_SUCCESS);
-}
-
-static kstat_t *kssl_ksp = NULL;
-
-static int
-kssl_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
-{
- if (cmd != DDI_DETACH)
- return (DDI_FAILURE);
-
- if (kssl_entry_tab_nentries != 0)
- return (DDI_FAILURE);
-
- kssl_dip = NULL;
-
- ddi_remove_minor_node(dip, NULL);
-
- return (DDI_SUCCESS);
-}
-
-/* ARGSUSED */
-static int
-kssl_open(dev_t *devp, int flag, int otyp, cred_t *credp)
-{
- if (otyp != OTYP_CHR)
- return (ENXIO);
-
- if (kssl_dip == NULL)
- return (ENXIO);
-
- /* first time here? initialize everything */
- if (rsa_x509_mech.cm_type == CRYPTO_MECH_INVALID) {
- kssl_init_mechs();
- prov_update_handle = crypto_notify_events(
- kssl_event_callback, CRYPTO_EVENT_MECHS_CHANGED);
- }
-
- /* exclusive opens are not supported */
- if (flag & FEXCL)
- return (ENOTSUP);
-
- return (0);
-}
-
-/* ARGSUSED */
-static int
-kssl_close(dev_t dev, int flag, int otyp, cred_t *credp)
-{
- return (0);
-}
-
-#define KSSL_MAX_KEYANDCERTS 80000 /* max 64K plus a little margin */
-
-/* ARGSUSED */
-static int
-kssl_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c,
- int *rval)
-{
- int error = EINVAL;
- uint32_t auditing = AU_AUDITING();
-
-#define ARG ((caddr_t)arg)
-
- if (secpolicy_net_config(c, B_FALSE) != 0) {
- return (EPERM);
- }
-
- switch (cmd) {
- case KSSL_ADD_ENTRY: {
- uint64_t len;
- uint32_t ck_rv;
- size_t off;
- kssl_params_t *kssl_params;
-
- off = offsetof(kssl_params_t, kssl_params_size);
- if (copyin(ARG + off, &len, sizeof (len)) != 0) {
- return (EFAULT);
- }
-
- if (len < sizeof (kssl_params_t) ||
- len > KSSL_MAX_KEYANDCERTS) {
- return (EINVAL);
- }
-
- kssl_params = kmem_alloc(len, KM_SLEEP);
-
- /* Get the whole structure and parameters in one move */
- if (copyin(ARG, kssl_params, len) != 0) {
- kmem_free(kssl_params, len);
- return (EFAULT);
- }
- error = kssl_add_entry(kssl_params);
- if (auditing)
- audit_kssl(KSSL_ADD_ENTRY, kssl_params, error);
- off = offsetof(kssl_params_t, kssl_token) +
- offsetof(kssl_tokinfo_t, ck_rv);
- ck_rv = kssl_params->kssl_token.ck_rv;
- if (copyout(&ck_rv, ARG + off, sizeof (ck_rv)) != 0) {
- error = EFAULT;
- }
-
- bzero(kssl_params, len);
- kmem_free(kssl_params, len);
- break;
- }
- case KSSL_DELETE_ENTRY: {
- struct sockaddr_in6 server_addr;
-
- if (copyin(ARG, &server_addr, sizeof (server_addr)) != 0) {
- return (EFAULT);
- }
-
- error = kssl_delete_entry(&server_addr);
- if (auditing)
- audit_kssl(KSSL_DELETE_ENTRY, &server_addr, error);
- break;
- }
- }
-
- return (error);
-}
-
-#define NUM_MECHS 7
-static mech_to_cipher_t mech_to_cipher_tab[NUM_MECHS] = {
- {CRYPTO_MECH_INVALID, SUN_CKM_RSA_X_509,
- {SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA,
- SSL_RSA_WITH_DES_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA,
- TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA,
- SSL_RSA_WITH_NULL_SHA}},
- {CRYPTO_MECH_INVALID, SUN_CKM_MD5_HMAC, {SSL_RSA_WITH_RC4_128_MD5}},
- {CRYPTO_MECH_INVALID, SUN_CKM_SHA1_HMAC,
- {SSL_RSA_WITH_RC4_128_SHA, SSL_RSA_WITH_DES_CBC_SHA,
- SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_NULL_SHA,
- TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA}},
- {CRYPTO_MECH_INVALID, SUN_CKM_RC4,
- {SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA}},
- {CRYPTO_MECH_INVALID, SUN_CKM_DES_CBC, {SSL_RSA_WITH_DES_CBC_SHA}},
- {CRYPTO_MECH_INVALID, SUN_CKM_DES3_CBC,
- {SSL_RSA_WITH_3DES_EDE_CBC_SHA}},
- {CRYPTO_MECH_INVALID, SUN_CKM_AES_CBC,
- {TLS_RSA_WITH_AES_128_CBC_SHA, TLS_RSA_WITH_AES_256_CBC_SHA}},
-};
-
-static void
-kssl_init_mechs()
-{
- mech_to_cipher_tab[0].mech = rsa_x509_mech.cm_type =
- crypto_mech2id(SUN_CKM_RSA_X_509);
- mech_to_cipher_tab[1].mech = hmac_md5_mech.cm_type =
- crypto_mech2id(SUN_CKM_MD5_HMAC);
- mech_to_cipher_tab[2].mech = hmac_sha1_mech.cm_type =
- crypto_mech2id(SUN_CKM_SHA1_HMAC);
-
- mech_to_cipher_tab[3].mech = cipher_defs[cipher_rc4].mech_type =
- crypto_mech2id(SUN_CKM_RC4);
- mech_to_cipher_tab[4].mech = cipher_defs[cipher_des].mech_type =
- crypto_mech2id(SUN_CKM_DES_CBC);
- mech_to_cipher_tab[5].mech = cipher_defs[cipher_3des].mech_type =
- crypto_mech2id(SUN_CKM_DES3_CBC);
- mech_to_cipher_tab[6].mech = cipher_defs[cipher_aes128].mech_type =
- cipher_defs[cipher_aes256].mech_type =
- crypto_mech2id(SUN_CKM_AES_CBC);
-}
-
-static int
-is_in_suites(uint16_t s, uint16_t *sarray)
-{
- int i;
-
- for (i = 0; i < CIPHER_SUITE_COUNT; i++) {
- if (s == sarray[i])
- return (1);
- }
-
- return (0);
-}
-
-static int
-is_in_mechlist(char *name, crypto_mech_name_t *mechs, int count)
-{
- int i;
-
- for (i = 0; i < count; i++) {
- if (strncmp(name, mechs[i], CRYPTO_MAX_MECH_NAME) == 0)
- return (1);
- }
-
- return (0);
-}
-
-/*
- * Callback function invoked by the crypto framework when a provider's
- * mechanism is available/unavailable. This callback updates entries in the
- * kssl_entry_tab[] to make changes to the cipher suites of an entry
- * which are affected by the mechanism.
- */
-static void
-kssl_event_callback(uint32_t event, void *event_arg)
-{
- int i, j;
- int cnt, rcnt;
- uint16_t s;
- boolean_t changed;
- crypto_mech_name_t *mechs;
- uint_t mech_count;
- mech_to_cipher_t *mc;
- kssl_entry_t *old;
- kssl_entry_t *new;
- uint16_t tmp_suites[CIPHER_SUITE_COUNT];
- uint16_t dis_list[CIPHER_SUITE_COUNT];
- crypto_notify_event_change_t *prov_change =
- (crypto_notify_event_change_t *)event_arg;
-
- /* ignore events for which we didn't register */
- if (event != CRYPTO_EVENT_MECHS_CHANGED) {
- return;
- }
-
- for (i = 0; i < NUM_MECHS; i++) {
- mc = &(mech_to_cipher_tab[i]);
- if (mc->mech == CRYPTO_MECH_INVALID)
- continue;
-
- /*
- * Check if this crypto framework provider mechanism being
- * added or removed affects us.
- */
- if (strncmp(mc->name, prov_change->ec_mech_name,
- CRYPTO_MAX_MECH_NAME) == 0)
- break;
- }
-
- if (i == NUM_MECHS)
- return;
-
- mechs = crypto_get_mech_list(&mech_count, KM_SLEEP);
- if (mechs == NULL)
- return;
-
- mutex_enter(&kssl_tab_mutex);
-
- for (i = 0; i < kssl_entry_tab_size; i++) {
- if ((old = kssl_entry_tab[i]) == NULL)
- continue;
-
- cnt = 0;
- rcnt = 0;
- changed = B_FALSE;
- for (j = 0; j < CIPHER_SUITE_COUNT; j++) {
- tmp_suites[j] = CIPHER_NOTSET;
- dis_list[j] = CIPHER_NOTSET;
- }
-
- /*
- * We start with the saved cipher suite list for the new entry.
- * If a mechanism is disabled, resulting in a cipher suite being
- * disabled now, we take it out from the list for the new entry.
- * If a mechanism is enabled, resulting in a cipher suite being
- * enabled now, we don't need to do any thing.
- */
- if (!is_in_mechlist(mc->name, mechs, mech_count)) {
- for (j = 0; j < CIPHER_SUITE_COUNT; j++) {
- s = mc->kssl_suites[j];
- if (s == 0)
- break;
- if (is_in_suites(s, old->kssl_saved_Suites)) {
- /* Disable this cipher suite */
- if (!is_in_suites(s, dis_list))
- dis_list[cnt++] = s;
- }
- }
- }
-
- for (j = 0; j < CIPHER_SUITE_COUNT; j++) {
- s = old->kssl_saved_Suites[j];
- if (!is_in_suites(s, dis_list))
- tmp_suites[rcnt] = s;
-
- if (!changed &&
- (tmp_suites[rcnt] != old->kssl_cipherSuites[rcnt]))
- changed = B_TRUE;
- rcnt++;
- }
-
- if (changed) {
- new = kmem_zalloc(sizeof (kssl_entry_t), KM_NOSLEEP);
- if (new == NULL)
- continue;
-
- *new = *old; /* Structure copy */
- old->ke_no_freeall = B_TRUE;
- new->ke_refcnt = 0;
- new->kssl_cipherSuites_nentries = rcnt;
- for (j = 0; j < CIPHER_SUITE_COUNT; j++)
- new->kssl_cipherSuites[j] = tmp_suites[j];
-
- KSSL_ENTRY_REFHOLD(new);
- kssl_entry_tab[i] = new;
- KSSL_ENTRY_REFRELE(old);
- }
- }
-
- mutex_exit(&kssl_tab_mutex);
- crypto_free_mech_list(mechs, mech_count);
-}
-
-
-kssl_stats_t *kssl_statp;
-
-static void
-kssl_global_init()
-{
- mutex_init(&kssl_tab_mutex, NULL, MUTEX_DRIVER, NULL);
-
- kssl_cache = kmem_cache_create("kssl_cache", sizeof (ssl_t),
- 0, kssl_constructor, kssl_destructor, NULL, NULL, NULL, 0);
-
- if ((kssl_ksp = kstat_create("kssl", 0, "kssl_stats", "crypto",
- KSTAT_TYPE_NAMED, sizeof (kssl_stats_t) / sizeof (kstat_named_t),
- KSTAT_FLAG_PERSISTENT)) != NULL) {
- kssl_statp = kssl_ksp->ks_data;
-
- kstat_named_init(&kssl_statp->sid_cache_lookups,
- "kssl_sid_cache_lookups", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->sid_cache_hits,
- "kssl_sid_cache_hits", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->sid_cached,
- "kssl_sid_cached", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->sid_uncached,
- "kssl_sid_uncached", KSTAT_DATA_UINT64);
-
- kstat_named_init(&kssl_statp->full_handshakes,
- "kssl_full_handshakes", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->resumed_sessions,
- "kssl_resumed_sessions", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->fallback_connections,
- "kssl_fallback_connections", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->proxy_fallback_failed,
- "kssl_proxy_fallback_failed", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->appdata_record_ins,
- "kssl_appdata_record_ins", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->appdata_record_outs,
- "kssl_appdata_record_outs", KSTAT_DATA_UINT64);
-
- kstat_named_init(&kssl_statp->alloc_fails, "kssl_alloc_fails",
- KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->fatal_alerts,
- "kssl_fatal_alerts", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->warning_alerts,
- "kssl_warning_alerts", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->no_suite_found,
- "kssl_no_suite_found", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->compute_mac_failure,
- "kssl_compute_mac_failure", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->verify_mac_failure,
- "kssl_verify_mac_failure", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->record_decrypt_failure,
- "kssl_record_decrypt_failure", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->bad_pre_master_secret,
- "kssl_bad_pre_master_secret", KSTAT_DATA_UINT64);
- kstat_named_init(&kssl_statp->internal_errors,
- "kssl_internal_errors", KSTAT_DATA_UINT64);
-
- kstat_install(kssl_ksp);
- };
-}
-
-static void
-kssl_global_fini(void)
-{
- mutex_destroy(&kssl_tab_mutex);
-
- if (kssl_cache != NULL) {
- kmem_cache_destroy(kssl_cache);
- kssl_cache = NULL;
- }
-
- if (kssl_ksp != NULL) {
- kstat_delete(kssl_ksp);
- kssl_ksp = NULL;
- }
-}
-
-/*ARGSUSED*/
-static int
-kssl_constructor(void *buf, void *arg, int kmflags)
-{
- ssl_t *ssl = buf;
-
- mutex_init(&ssl->kssl_lock, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&ssl->async_cv, NULL, CV_DEFAULT, NULL);
-
- return (0);
-}
-
-/*ARGSUSED*/
-static void
-kssl_destructor(void *buf, void *arg)
-{
- ssl_t *ssl = buf;
- mutex_destroy(&ssl->kssl_lock);
- cv_destroy(&ssl->async_cv);
-}
-
-/*
- * Handler routine called by the crypto framework when a
- * provider is unregistered or registered. We invalidate the
- * private key handle if our provider is unregistered. We set
- * a flag to reauthenticate if our provider came back.
- */
-void
-kssl_prov_evnt(uint32_t event, void *event_arg)
-{
- int i, rv;
- kssl_entry_t *ep;
- kssl_session_info_t *s;
- crypto_provider_t prov;
- crypto_provider_ext_info_t info;
-
- if (event != CRYPTO_EVENT_PROVIDER_UNREGISTERED &&
- event != CRYPTO_EVENT_PROVIDER_REGISTERED)
- return;
-
- prov = (crypto_provider_t)event_arg;
- if (event == CRYPTO_EVENT_PROVIDER_REGISTERED) {
- rv = crypto_get_provinfo(prov, &info);
- if (rv != CRYPTO_SUCCESS)
- return;
- }
-
- mutex_enter(&kssl_tab_mutex);
-
- for (i = 0; i < kssl_entry_tab_size; i++) {
- if ((ep = kssl_entry_tab[i]) == NULL)
- continue;
-
- s = ep->ke_sessinfo;
- DTRACE_PROBE1(kssl_entry_cycle, kssl_entry_t *, ep);
- switch (event) {
- case CRYPTO_EVENT_PROVIDER_UNREGISTERED:
- if (s->is_valid_handle && s->prov == prov) {
- s->is_valid_handle = B_FALSE;
- crypto_release_provider(s->prov);
- }
- break;
-
- case CRYPTO_EVENT_PROVIDER_REGISTERED:
- if (s->is_valid_handle)
- break;
- if (bcmp(s->toklabel, info.ei_label,
- CRYPTO_EXT_SIZE_LABEL) == 0) {
- s->do_reauth = B_TRUE;
- }
- break;
- }
- }
-
- mutex_exit(&kssl_tab_mutex);
-}
diff --git a/usr/src/uts/common/inet/kssl/kssl.conf b/usr/src/uts/common/inet/kssl/kssl.conf
deleted file mode 100644
index 4de42d8cb3..0000000000
--- a/usr/src/uts/common/inet/kssl/kssl.conf
+++ /dev/null
@@ -1,29 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-
-name="kssl" parent="pseudo" instance=0;
-ddi-forceattach=1;
diff --git a/usr/src/uts/common/inet/kssl/kssl.h b/usr/src/uts/common/inet/kssl/kssl.h
deleted file mode 100644
index 50e592fee7..0000000000
--- a/usr/src/uts/common/inet/kssl/kssl.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef _INET_KSSL_KSSL_H
-#define _INET_KSSL_KSSL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/crypto/common.h>
-
-/* These are re-definition from <crypto/ioctl.h> */
-typedef struct kssl_object_attribute {
- uint64_t ka_type; /* attribute type */
- uint32_t ka_value_offset; /* offset to attribute value */
- uint32_t ka_value_len; /* length of attribute value */
-} kssl_object_attribute_t;
-
-typedef struct kssl_key {
- crypto_key_format_t ks_format; /* format identifier */
- uint32_t ks_count; /* number of attributes */
- uint32_t ks_attrs_offset; /* offset to the attributes */
-} kssl_key_t;
-
-typedef struct kssl_certs_s {
- uint32_t sc_count; /* number of certificates */
- uint32_t sc_sizes_offset; /* offset to certificates sizes array */
- uint32_t sc_certs_offset; /* offset to certificates array */
-} kssl_certs_t;
-
-#define MAX_PIN_LENGTH 1024
-
-typedef struct kssl_tokinfo_s {
- uint8_t toklabel[CRYPTO_EXT_SIZE_LABEL];
- uint32_t pinlen;
- uint32_t tokpin_offset; /* offset to the pin */
- uint32_t ck_rv; /* PKCS #11 specific error */
-} kssl_tokinfo_t;
-
-/* Code point for Signalling Cipher Suite Value (SCSV) */
-#define SSL_SCSV 0x00ff
-
-/* Cipher suites */
-#define SSL_RSA_WITH_NULL_SHA 0x0002
-#define SSL_RSA_WITH_RC4_128_MD5 0x0004
-#define SSL_RSA_WITH_RC4_128_SHA 0x0005
-#define SSL_RSA_WITH_DES_CBC_SHA 0x0009
-#define SSL_RSA_WITH_3DES_EDE_CBC_SHA 0x000a
-#define TLS_RSA_WITH_AES_128_CBC_SHA 0x002f
-#define TLS_RSA_WITH_AES_256_CBC_SHA 0x0035
-/* total number of cipher suites supported */
-#define CIPHER_SUITE_COUNT 7
-#define CIPHER_NOTSET 0xffff
-
-/* TLS extension types */
-#define TLSEXT_RENEGOTIATION_INFO 0xff01
-
-#define DEFAULT_SID_TIMEOUT 86400 /* 24 hours in seconds */
-#define DEFAULT_SID_CACHE_NENTRIES 5000
-
-typedef struct kssl_params_s {
- uint64_t kssl_params_size; /* total params buf len */
- /* address and port number */
- struct sockaddr_in6 kssl_addr;
- uint16_t kssl_proxy_port;
-
- uint32_t kssl_session_cache_timeout; /* In seconds */
- uint32_t kssl_session_cache_size;
-
- /*
- * Contains ordered list of cipher suites. We do not include
- * the one suite with no encryption. Hence the -1.
- */
- uint16_t kssl_suites[CIPHER_SUITE_COUNT - 1];
-
- uint8_t kssl_is_nxkey;
- kssl_tokinfo_t kssl_token;
-
- /* certificates */
- kssl_certs_t kssl_certs;
-
- /* private key */
- kssl_key_t kssl_privkey;
-} kssl_params_t;
-
-/* The ioctls to /dev/kssl */
-#define KSSL_IOC(x) (('s' << 24) | ('s' << 16) | ('l' << 8) | (x))
-#define KSSL_ADD_ENTRY KSSL_IOC(1)
-#define KSSL_DELETE_ENTRY KSSL_IOC(2)
-
-#ifdef _KERNEL
-
-extern int kssl_add_entry(kssl_params_t *);
-extern int kssl_delete_entry(struct sockaddr_in6 *);
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INET_KSSL_KSSL_H */
diff --git a/usr/src/uts/common/inet/kssl/ksslapi.c b/usr/src/uts/common/inet/kssl/ksslapi.c
deleted file mode 100644
index 8311794a5a..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslapi.c
+++ /dev/null
@@ -1,1317 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <sys/strsun.h>
-#include <sys/kmem.h>
-#include <sys/cpuvar.h>
-#include <sys/atomic.h>
-#include <sys/sysmacros.h>
-
-#include <inet/common.h>
-#include <inet/ip.h>
-
-#include <sys/systm.h>
-#include <sys/param.h>
-#include <sys/tihdr.h>
-
-#include "ksslimpl.h"
-#include "ksslproto.h"
-#include "ksslapi.h"
-
-static kssl_cmd_t kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp,
- mblk_t **decrmp, kssl_callback_t cbfn, void *arg);
-static boolean_t kssl_enqueue(kssl_chain_t **head, void *item);
-static void kssl_dequeue(kssl_chain_t **head, void *item);
-static kssl_status_t kssl_build_single_record(ssl_t *ssl, mblk_t *mp);
-
-/*
- * The socket bind request is intercepted and re-routed here
- * to see is there is SSL relevant job to do, based on the kssl config
- * in the kssl_entry_tab.
- * Looks up the kernel SSL proxy table, to find an entry that matches the
- * same serveraddr, and has one of the following two criteria:
- * 1. in_port is an ssl_port. This endpoint can be used later as a fallback
- * to complete connections that cannot be handled by the SSL kernel proxy
- * (typically non supported ciphersuite). The cookie for the calling client
- * is saved with the kssl_entry to be retrieved for the fallback.
- * The function returns KSSL_HAS_PROXY.
- *
- * 2. in_port is a proxy port for another ssl port. The ssl port is then
- * substituted to the in_port in the bind_req TPI structure, so that
- * the bind falls through to the SSL port. At the end of this operation,
- * all the packets arriving to the SSL port will be delivered to an
- * accepted endpoint child of this bound socket.
- * The kssl_entry_t is returned in *ksslent, for later use by the
- * lower modules' SSL hooks that handle the Handshake messages.
- * The function returns KSSL_IS_PROXY.
- *
- * The function returns KSSL_NO_PROXY otherwise.
- */
-
-kssl_endpt_type_t
-kssl_check_proxy(struct sockaddr *addr, socklen_t len, void *cookie,
- kssl_ent_t *ksslent)
-{
- int i;
- kssl_endpt_type_t ret;
- kssl_entry_t *ep;
- sin_t *sin;
- sin6_t *sin6;
- in6_addr_t mapped_v4addr;
- in6_addr_t *v6addr;
- in_port_t in_port;
-
- if (kssl_entry_tab_nentries == 0) {
- return (KSSL_NO_PROXY);
- }
-
- ret = KSSL_NO_PROXY;
- sin = (struct sockaddr_in *)addr;
-
- switch (len) {
- case sizeof (sin_t):
- in_port = ntohs(sin->sin_port);
- IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &mapped_v4addr);
- v6addr = &mapped_v4addr;
- break;
-
- case sizeof (sin6_t):
- sin6 = (sin6_t *)sin;
- in_port = ntohs(sin6->sin6_port);
- v6addr = &sin6->sin6_addr;
- break;
-
- default:
- return (ret);
- }
-
- mutex_enter(&kssl_tab_mutex);
-
- for (i = 0; i < kssl_entry_tab_size; i++) {
- if ((ep = kssl_entry_tab[i]) == NULL)
- continue;
-
- if (IN6_ARE_ADDR_EQUAL(&ep->ke_laddr, v6addr) ||
- IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr)) {
-
- /* This is an SSL port to fallback to */
- if (ep->ke_ssl_port == in_port) {
-
- /*
- * Let's see first if there's at least
- * an endpoint for a proxy server.
- * If there's none, then we return as we have
- * no proxy, so that the bind() to the
- * transport layer goes through.
- * The calling module will ask for this
- * cookie if it wants to fall back to it,
- * so add this one to the list of fallback
- * clients.
- */
- if (!kssl_enqueue((kssl_chain_t **)
- &(ep->ke_fallback_head), cookie)) {
- break;
- }
-
- KSSL_ENTRY_REFHOLD(ep);
- *ksslent = (kssl_ent_t)ep;
-
- ret = KSSL_HAS_PROXY;
- break;
- }
-
- /* This is a proxy port. */
- if (ep->ke_proxy_port == in_port) {
- /* Add the caller's cookie to proxies list */
-
- if (!kssl_enqueue((kssl_chain_t **)
- &(ep->ke_proxy_head), cookie)) {
- break;
- }
-
- /*
- * Make this look like the SSL port to the
- * transport below
- */
- sin->sin_port = htons(ep->ke_ssl_port);
-
- KSSL_ENTRY_REFHOLD(ep);
- *ksslent = (kssl_ent_t)ep;
-
- ret = KSSL_IS_PROXY;
- break;
- }
- }
- }
-
- mutex_exit(&kssl_tab_mutex);
- return (ret);
-}
-
-/*
- * Retrieved an endpoint "bound" to the SSL entry.
- * Such endpoint has previously called kssl_check_proxy(), got itself
- * linked to the kssl_entry's ke_fallback_head list.
- * This routine returns the cookie from that SSL entry ke_fallback_head list.
- */
-void *
-kssl_find_fallback(kssl_ent_t ksslent)
-{
- kssl_entry_t *kssl_entry = (kssl_entry_t *)ksslent;
-
- if (kssl_entry->ke_fallback_head != NULL)
- return (kssl_entry->ke_fallback_head->fallback_bound);
-
- KSSL_COUNTER(proxy_fallback_failed, 1);
-
- return (NULL);
-}
-
-/*
- * Re-usable code for adding and removing an element to/from a chain that
- * matches "item"
- * The chain is simple-linked and NULL ended.
- */
-
-/*
- * This routine returns TRUE if the item was either successfully added to
- * the chain, or is already there. It returns FALSE otherwise.
- */
-static boolean_t
-kssl_enqueue(kssl_chain_t **head, void *item)
-{
- kssl_chain_t *newchain, *cur;
-
- /* Lookup the existing entries to avoid duplicates */
- cur = *head;
- while (cur != NULL) {
- if (cur->item == item) {
- return (B_TRUE);
- }
- cur = cur->next;
- }
-
- newchain = kmem_alloc(sizeof (kssl_chain_t), KM_NOSLEEP);
- if (newchain == NULL) {
- return (B_FALSE);
- }
-
- newchain->item = item;
- newchain->next = *head;
- *head = newchain;
- return (B_TRUE);
-}
-
-static void
-kssl_dequeue(kssl_chain_t **head, void *item)
-{
- kssl_chain_t *prev, *cur;
-
- prev = cur = *head;
- while (cur != NULL) {
- if (cur->item == item) {
- if (cur == *head)
- *head = (*head)->next;
- else
- prev->next = cur->next;
- kmem_free(cur, sizeof (kssl_chain_t));
- return;
- }
- prev = cur;
- cur = cur->next;
- }
-}
-
-/*
- * Holds the kssl_entry
- */
-void
-kssl_hold_ent(kssl_ent_t ksslent)
-{
- KSSL_ENTRY_REFHOLD((kssl_entry_t *)ksslent);
-}
-
-/*
- * Releases the kssl_entry
- * If the caller passes a cookie, then it should be removed from both
- * proxies and fallbacks chains.
- */
-void
-kssl_release_ent(kssl_ent_t ksslent, void *cookie, kssl_endpt_type_t endpt_type)
-{
- kssl_entry_t *kssl_entry = (kssl_entry_t *)ksslent;
-
- if (cookie != NULL) {
- if (endpt_type == KSSL_IS_PROXY) {
- ASSERT(kssl_entry->ke_proxy_head != NULL);
- kssl_dequeue(
- (kssl_chain_t **)&kssl_entry->ke_proxy_head,
- cookie);
- }
- if (endpt_type == KSSL_HAS_PROXY) {
- ASSERT(kssl_entry->ke_fallback_head != NULL);
- kssl_dequeue(
- (kssl_chain_t **)&kssl_entry->ke_fallback_head,
- cookie);
- }
- }
- KSSL_ENTRY_REFRELE(kssl_entry);
-}
-
-/*
- * Releases the kssl_context
- */
-void
-kssl_release_ctx(kssl_ctx_t ksslctx)
-{
- kssl_free_context((ssl_t *)ksslctx);
-}
-
-/*
- * Done with asynchronous processing
- */
-void
-kssl_async_done(kssl_ctx_t ksslctx)
-{
- ssl_t *ssl = (ssl_t *)ksslctx;
-
- mutex_enter(&ssl->kssl_lock);
- if (--ssl->async_ops_pending == 0)
- cv_signal(&ssl->async_cv);
- mutex_exit(&ssl->kssl_lock);
-}
-
-/*
- * Packets are accumulated here, if there are packets already queued,
- * or if the context is active.
- * The context is active when an incoming record processing function
- * is already executing on a different thread.
- * Queued packets are handled either when an mblk arrived and completes
- * a record, or, when the active context processor finishes the task at
- * hand.
- * The caller has to keep calling this routine in a loop until it returns
- * B_FALSE in *more. The reason for this is SSL3: The protocol
- * allows the client to send its first application_data message right
- * after it had sent its Finished message, and not wait for the server
- * ChangeCipherSpec and Finished. This overlap means we can't batch up
- * a returned Handshake message to be sent on the wire
- * with a decrypted application_data to be delivered to the application.
- */
-kssl_cmd_t
-kssl_input(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp, boolean_t *more,
- kssl_callback_t cbfn, void *arg)
-{
- mblk_t *recmp, *outmp = NULL;
- kssl_cmd_t kssl_cmd;
- ssl_t *ssl;
- uint8_t *rec_sz_p;
- int mplen;
- SSL3ContentType content_type;
- uint16_t rec_sz;
-
- ASSERT(ctx != NULL);
-
- if (mp != NULL) {
- ASSERT(mp->b_prev == NULL && mp->b_next == NULL);
- }
-
- ssl = (ssl_t *)(ctx);
-
- *decrmp = NULL;
- *more = B_FALSE;
-
- mutex_enter(&ssl->kssl_lock);
-
- if (ssl->close_notify_clnt == B_TRUE) {
- DTRACE_PROBE(kssl_err__close_notify);
- goto sendnewalert;
- }
-
- /* Whomever is currently processing this connection will get to this */
- if (ssl->activeinput) {
- if (mp != NULL) {
- KSSL_ENQUEUE_MP(ssl, mp);
- }
- mutex_exit(&ssl->kssl_lock);
- return (KSSL_CMD_NONE);
- }
-
- /*
- * Fast path for complete incoming application_data records on an empty
- * queue.
- * This is by far the most frequently encountered case
- */
-
- if ((!ssl->activeinput) && (ssl->rec_ass_head == NULL) &&
- ((mp != NULL) && (mplen = MBLKL(mp)) > SSL3_HDR_LEN)) {
-
- DTRACE_PROBE1(kssl_mblk__fast_path, mblk_t *, mp);
- content_type = (SSL3ContentType)mp->b_rptr[0];
-
- if ((content_type == content_application_data) &&
- (ssl->hs_waitstate == idle_handshake)) {
- rec_sz_p = SSL3_REC_SIZE(mp);
- rec_sz = BE16_TO_U16(rec_sz_p);
-
- if ((mp->b_cont == NULL) && (mplen == rec_sz)) {
-
- *decrmp = mp;
- mutex_exit(&ssl->kssl_lock);
- return (KSSL_CMD_DELIVER_PROXY);
- }
- }
- }
-
- ssl->activeinput = B_TRUE;
- /* Accumulate at least one record */
- if (mp != NULL) {
- KSSL_ENQUEUE_MP(ssl, mp);
- mp = NULL;
- }
- recmp = kssl_get_next_record(ssl);
-
- if (recmp == NULL) {
- ssl->activeinput = B_FALSE;
- if (ssl->alert_sendbuf != NULL) {
- DTRACE_PROBE(kssl_err__alert_to_send);
- goto sendalert;
- }
- /* Not even a complete header yet. wait for the rest */
- mutex_exit(&ssl->kssl_lock);
- return (KSSL_CMD_NONE);
- }
-
- do {
- DTRACE_PROBE1(kssl_mblk__kssl_input_cycle, mblk_t *, recmp);
- content_type = (SSL3ContentType)recmp->b_rptr[0];
-
- switch (content_type) {
- case content_application_data:
- /*
- * application_data records are decrypted and
- * MAC-verified by the stream head, and in the context
- * a read()'ing thread. This avoids unfairly charging
- * the cost of handling this record on the whole system,
- * and prevents doing it while in the shared IP
- * perimeter.
- */
- ssl->activeinput = B_FALSE;
- if (ssl->hs_waitstate != idle_handshake) {
- DTRACE_PROBE(kssl_err__waitstate_not_idle);
- goto sendnewalert;
- }
- outmp = recmp;
- kssl_cmd = KSSL_CMD_DELIVER_PROXY;
- break;
- case content_change_cipher_spec:
- case content_alert:
- case content_handshake:
- case content_handshake_v2:
- /*
- * If we're past the initial handshake, start letting
- * the stream head process all records, in particular
- * the close_notify.
- * This is needed to avoid processing them out of
- * sequence when previous application data packets are
- * waiting to be decrypted/MAC'ed and delivered.
- */
- if (ssl->hs_waitstate == idle_handshake) {
- ssl->activeinput = B_FALSE;
- outmp = recmp;
- kssl_cmd = KSSL_CMD_DELIVER_PROXY;
- } else {
- kssl_cmd = kssl_handle_any_record(ssl, recmp,
- &outmp, cbfn, arg);
- }
- break;
- default:
- ssl->activeinput = B_FALSE;
- DTRACE_PROBE(kssl_err__invalid_content_type);
- goto sendnewalert;
- }
-
- /* Priority to Alert messages */
- if (ssl->alert_sendbuf != NULL) {
- DTRACE_PROBE(kssl_err__alert_to_send_cycle);
- goto sendalert;
- }
-
- /* Then handshake messages */
- if (ssl->handshake_sendbuf) {
- if (*decrmp != NULL) {
- linkb(*decrmp, ssl->handshake_sendbuf);
- } else {
- *decrmp = ssl->handshake_sendbuf;
- }
- ssl->handshake_sendbuf = NULL;
-
- *more = ((ssl->rec_ass_head != NULL) &&
- (!ssl->activeinput));
- mutex_exit(&ssl->kssl_lock);
- return (kssl_cmd);
- }
-
- if (ssl->hs_waitstate == idle_handshake) {
- *more = ((ssl->rec_ass_head != NULL) &&
- (!ssl->activeinput));
- }
-
- if (outmp != NULL) {
- *decrmp = outmp;
- /*
- * Don't process any packet after an application_data.
- * We could well receive the close_notify which should
- * be handled separately.
- */
- mutex_exit(&ssl->kssl_lock);
- return (kssl_cmd);
- }
- /*
- * The current record isn't done yet. Don't start the next one
- */
- if (ssl->activeinput) {
- mutex_exit(&ssl->kssl_lock);
- return (kssl_cmd);
- }
- } while ((recmp = kssl_get_next_record(ssl)) != NULL);
-
- mutex_exit(&ssl->kssl_lock);
- return (kssl_cmd);
-
-sendnewalert:
- kssl_send_alert(ssl, alert_fatal, unexpected_message);
- if (mp != NULL) {
- freeb(mp);
- }
-
-sendalert:
- *decrmp = ssl->alert_sendbuf;
- ssl->alert_sendbuf = NULL;
- mutex_exit(&ssl->kssl_lock);
- return (KSSL_CMD_SEND);
-}
-
-/*
- * Decrypt and verify the MAC of an incoming chain of application_data record.
- * Each block has exactly one SSL record.
- */
-kssl_cmd_t
-kssl_handle_mblk(kssl_ctx_t ctx, mblk_t **mpp, mblk_t **outmp)
-{
- uchar_t *recend, *rec_sz_p;
- uchar_t *real_recend;
- mblk_t *prevmp = NULL, *nextmp, *firstmp, *mp, *copybp;
- int mac_sz;
- uchar_t version[2];
- uint16_t rec_sz;
- SSL3AlertDescription desc;
- SSL3ContentType content_type;
- ssl_t *ssl;
- KSSLCipherSpec *spec;
- int error, ret;
- kssl_cmd_t kssl_cmd = KSSL_CMD_DELIVER_PROXY;
- boolean_t deliverit = B_FALSE;
- crypto_data_t cipher_data;
-
- ASSERT(ctx != NULL);
-
- ssl = (ssl_t *)(ctx);
-
- mp = firstmp = *mpp;
- *outmp = NULL;
-more:
-
- while (mp != NULL) {
- ASSERT(DB_TYPE(mp) == M_DATA);
-
- if (DB_REF(mp) > 1) {
- /*
- * Fortunately copyb() preserves the offset,
- * tail space and alignment so the copy is
- * ready to be made an SSL record.
- */
- if ((copybp = copyb(mp)) == NULL)
- return (KSSL_CMD_NOT_SUPPORTED);
-
- copybp->b_cont = mp->b_cont;
- if (mp == firstmp) {
- *mpp = copybp;
- } else if (prevmp != NULL) {
- prevmp->b_cont = copybp;
- }
- freeb(mp);
- mp = copybp;
- }
-
- DTRACE_PROBE1(kssl_mblk__handle_record_cycle, mblk_t *, mp);
- content_type = (SSL3ContentType)mp->b_rptr[0];
-
- switch (content_type) {
- case content_application_data:
- break;
- case content_change_cipher_spec:
- case content_alert:
- case content_handshake:
- case content_handshake_v2:
- nextmp = mp->b_cont;
-
- /* Remove this message */
- if (prevmp != NULL) {
- prevmp->b_cont = nextmp;
-
- /*
- * If we had processed blocks that need to
- * be delivered, then remember that error code
- */
- if (kssl_cmd == KSSL_CMD_DELIVER_PROXY)
- deliverit = B_TRUE;
- }
-
- mutex_enter(&ssl->kssl_lock);
- /* NOTE: This routine could free mp. */
- kssl_cmd = kssl_handle_any_record(ssl, mp, outmp,
- NULL, NULL);
-
- if (ssl->alert_sendbuf != NULL) {
- mp = nextmp;
- DTRACE_PROBE(kssl_err__alert_after_handle_any);
- goto sendalert;
- }
- mutex_exit(&ssl->kssl_lock);
-
- if (deliverit) {
- kssl_cmd = KSSL_CMD_DELIVER_PROXY;
- }
-
- mp = nextmp;
- continue; /* to the while loop */
- default:
- desc = decode_error;
- KSSL_COUNTER(internal_errors, 1);
- DTRACE_PROBE(kssl_err__decode_error);
- goto makealert;
- }
-
- version[0] = mp->b_rptr[1];
- version[1] = mp->b_rptr[2];
- rec_sz_p = SSL3_REC_SIZE(mp);
- rec_sz = BE16_TO_U16(rec_sz_p);
-
- mp->b_rptr += SSL3_HDR_LEN;
- recend = mp->b_rptr + rec_sz;
- real_recend = recend;
-
- /*
- * Check the assumption that each mblk contains exactly
- * one complete SSL record. We bail out if the check fails.
- */
- ASSERT(recend == mp->b_wptr);
- if (recend != mp->b_wptr) {
- desc = decode_error;
- KSSL_COUNTER(internal_errors, 1);
- DTRACE_PROBE(kssl_err__not_complete_record);
- goto makealert;
- }
-
- spec = &ssl->spec[KSSL_READ];
- mac_sz = spec->mac_hashsz;
- if (spec->cipher_ctx != 0) {
-
- /*
- * The record length must be a multiple of the
- * block size for block ciphers.
- * The cipher_bsize is always a power of 2.
- */
- if ((spec->cipher_type == type_block) &&
- ((rec_sz & (spec->cipher_bsize - 1)) != 0)) {
- DTRACE_PROBE2(kssl_err__bad_record_size,
- uint16_t, rec_sz,
- int, spec->cipher_bsize);
- KSSL_COUNTER(record_decrypt_failure, 1);
- mp->b_rptr = recend;
- desc = decrypt_error;
- goto makealert;
- }
-
- cipher_data.cd_format = CRYPTO_DATA_RAW;
- cipher_data.cd_offset = 0;
- cipher_data.cd_length = rec_sz;
- cipher_data.cd_miscdata = NULL;
- cipher_data.cd_raw.iov_base = (char *)mp->b_rptr;
- cipher_data.cd_raw.iov_len = rec_sz;
- error = crypto_decrypt_update(spec->cipher_ctx,
- &cipher_data, NULL, NULL);
- if (CRYPTO_ERR(error)) {
- DTRACE_PROBE1(
- kssl_err__crypto_decrypt_update_failed,
- int, error);
- KSSL_COUNTER(record_decrypt_failure, 1);
- mp->b_rptr = recend;
- desc = decrypt_error;
- goto makealert;
- }
- }
- if (spec->cipher_type == type_block) {
- uint_t pad_sz = recend[-1];
- pad_sz++;
- if (pad_sz + mac_sz > rec_sz) {
- DTRACE_PROBE(kssl_err__pad_mac_bigger);
- mp->b_rptr = recend;
- desc = bad_record_mac;
- goto makealert;
- }
- rec_sz -= pad_sz;
- recend -= pad_sz;
- }
- if (mac_sz != 0) {
- uchar_t hash[MAX_HASH_LEN];
- if (rec_sz < mac_sz) {
- DTRACE_PROBE(kssl_err__pad_smaller_mac);
- mp->b_rptr = real_recend;
- desc = bad_record_mac;
- goto makealert;
- }
- rec_sz -= mac_sz;
- recend -= mac_sz;
- ret = kssl_compute_record_mac(ssl, KSSL_READ,
- ssl->seq_num[KSSL_READ], content_type,
- version, mp->b_rptr, rec_sz, hash);
- if (ret != CRYPTO_SUCCESS ||
- bcmp(hash, recend, mac_sz)) {
- DTRACE_PROBE1(kssl_mblk__MACmismatch_handlerec,
- mblk_t *, mp);
- mp->b_rptr = real_recend;
- desc = bad_record_mac;
- DTRACE_PROBE(kssl_err__msg_MAC_mismatch);
- KSSL_COUNTER(verify_mac_failure, 1);
- goto makealert;
- }
- ssl->seq_num[KSSL_READ]++;
- }
-
- if (ssl->hs_waitstate != idle_handshake) {
- DTRACE_PROBE1(kssl_err__unexpected_msg,
- SSL3WaitState, ssl->hs_waitstate);
- mp->b_rptr = real_recend;
- desc = unexpected_message;
- goto makealert;
- }
- mp->b_wptr = recend;
-
- DTRACE_PROBE1(kssl_mblk__dblk_cooked, mblk_t *, mp);
- KSSL_COUNTER(appdata_record_ins, 1);
-
- prevmp = mp;
- mp = mp->b_cont;
- }
-
- return (kssl_cmd);
-
-makealert:
- nextmp = mp->b_cont;
- freeb(mp);
- mp = nextmp;
- mutex_enter(&ssl->kssl_lock);
- kssl_send_alert(ssl, alert_fatal, desc);
-
- if (ssl->alert_sendbuf == NULL) {
- /* internal memory allocation failure. just return. */
- DTRACE_PROBE(kssl_err__alert_msg_alloc_failed);
- mutex_exit(&ssl->kssl_lock);
-
- if (mp) {
- prevmp = NULL;
- goto more;
- }
-
- return (KSSL_CMD_NONE);
- }
- kssl_cmd = KSSL_CMD_SEND;
-sendalert:
- if (*outmp == NULL) {
- *outmp = ssl->alert_sendbuf;
- } else {
- linkb(*outmp, ssl->alert_sendbuf);
- }
- ssl->alert_sendbuf = NULL;
- mutex_exit(&ssl->kssl_lock);
-
- if (mp) {
- prevmp = NULL;
- goto more;
- }
-
- return (kssl_cmd);
-}
-/*
- * This is the routine that handles incoming SSL records.
- * When called the first time, with a NULL context, this routine expects
- * a ClientHello SSL Handshake packet and shall allocate a context
- * of a new SSL connection.
- * During the rest of the handshake packets, the routine adjusts the
- * state of the context according to the record received.
- * After the ChangeCipherSpec message is received, the routine first
- * decrypts/authenticated the packet using the key materials in the
- * connection's context.
- * The return code tells the caller what to do with the returned packet.
- */
-static kssl_cmd_t
-kssl_handle_any_record(kssl_ctx_t ctx, mblk_t *mp, mblk_t **decrmp,
- kssl_callback_t cbfn, void *arg)
-{
- uchar_t *recend, *rec_sz_p;
- uchar_t version[2];
- uchar_t *real_recend, *save_rptr, *save_wptr;
- int rhsz = SSL3_HDR_LEN;
- uint16_t rec_sz;
- int sz;
- int mac_sz;
- SSL3AlertDescription desc;
- SSL3AlertLevel level;
- SSL3ContentType content_type;
- ssl_t *ssl;
- KSSLCipherSpec *spec;
- int error = 0, ret;
-
- ASSERT(ctx != NULL);
-
- ssl = (ssl_t *)(ctx);
-
- *decrmp = NULL;
-
- save_rptr = mp->b_rptr;
- save_wptr = mp->b_wptr;
-
- ASSERT(MUTEX_HELD(&ssl->kssl_lock));
-
- content_type = (SSL3ContentType)mp->b_rptr[0];
- if (content_type == content_handshake_v2) {
- if (ssl->hs_waitstate == wait_client_hello) {
- /* V2 compatible ClientHello */
- if (mp->b_rptr[3] == 0x03 &&
- (mp->b_rptr[4] == 0x01 ||
- mp->b_rptr[4] == 0x00)) {
- ssl->major_version = version[0] = mp->b_rptr[3];
- ssl->minor_version = version[1] = mp->b_rptr[4];
- } else {
- /* We don't support "pure" SSLv2 */
- DTRACE_PROBE(kssl_err__no_SSLv2);
- ssl->major_version = mp->b_rptr[3];
- ssl->minor_version = mp->b_rptr[4];
- desc = protocol_version;
- goto sendalert;
- }
- }
- rec_sz = (uint16_t)mp->b_rptr[1];
- rhsz = 2;
- } else {
- ssl->major_version = version[0] = mp->b_rptr[1];
- ssl->minor_version = version[1] = mp->b_rptr[2];
- rec_sz_p = SSL3_REC_SIZE(mp);
- rec_sz = BE16_TO_U16(rec_sz_p);
- }
-
- mp->b_rptr += rhsz;
- recend = mp->b_rptr + rec_sz;
- real_recend = recend;
-
- /*
- * Check the assumption that each mblk contains exactly
- * one complete SSL record. We bail out if the check fails.
- */
- ASSERT(recend == mp->b_wptr);
- if (recend != mp->b_wptr) {
- DTRACE_PROBE3(kssl_mblk__handle_any_record_recszerr,
- mblk_t *, mp, int, rhsz, int, rec_sz);
- DTRACE_PROBE(kssl_err__record_size);
- desc = decode_error;
- KSSL_COUNTER(internal_errors, 1);
- goto sendalert;
- }
-
- spec = &ssl->spec[KSSL_READ];
- mac_sz = spec->mac_hashsz;
- if (spec->cipher_ctx != 0) {
- /*
- * The record length must be a multiple of the
- * block size for block ciphers.
- */
- if ((spec->cipher_type == type_block) &&
- ((rec_sz & (spec->cipher_bsize - 1)) != 0)) {
- DTRACE_PROBE2(kssl_err__bad_record_size,
- uint16_t, rec_sz, int, spec->cipher_bsize);
- KSSL_COUNTER(record_decrypt_failure, 1);
- mp->b_rptr = recend;
- desc = decrypt_error;
- goto sendalert;
- }
-
- spec->cipher_data.cd_length = rec_sz;
- spec->cipher_data.cd_raw.iov_base = (char *)mp->b_rptr;
- spec->cipher_data.cd_raw.iov_len = rec_sz;
- error = crypto_decrypt_update(spec->cipher_ctx,
- &spec->cipher_data, NULL, NULL);
- if (CRYPTO_ERR(error)) {
- DTRACE_PROBE1(kssl_err__crypto_decrypt_update_failed,
- int, error);
- KSSL_COUNTER(record_decrypt_failure, 1);
- mp->b_rptr = recend;
- desc = decrypt_error;
- goto sendalert;
- }
- }
- if (spec->cipher_type == type_block) {
- uint_t pad_sz = recend[-1];
- pad_sz++;
- if (pad_sz + mac_sz > rec_sz) {
- DTRACE_PROBE2(kssl_err__pad_mac_mismatch,
- int, pad_sz, int, mac_sz);
- mp->b_rptr = recend;
- desc = bad_record_mac;
- goto sendalert;
- }
- rec_sz -= pad_sz;
- recend -= pad_sz;
- }
- if (mac_sz != 0) {
- uchar_t hash[MAX_HASH_LEN];
- if (rec_sz < mac_sz) {
- DTRACE_PROBE1(kssl_err__mac_size_too_big,
- int, mac_sz);
- mp->b_rptr = real_recend;
- desc = bad_record_mac;
- goto sendalert;
- }
- rec_sz -= mac_sz;
- recend -= mac_sz;
- ret = kssl_compute_record_mac(ssl, KSSL_READ,
- ssl->seq_num[KSSL_READ], content_type,
- version, mp->b_rptr, rec_sz, hash);
- if (ret != CRYPTO_SUCCESS ||
- bcmp(hash, recend, mac_sz)) {
- DTRACE_PROBE1(kssl_mblk__MACmismatch_anyrecord,
- mblk_t *, mp);
- mp->b_rptr = real_recend;
- desc = bad_record_mac;
- DTRACE_PROBE(kssl_err__msg_MAC_mismatch);
- KSSL_COUNTER(verify_mac_failure, 1);
- goto sendalert;
- }
- ssl->seq_num[KSSL_READ]++;
- DTRACE_PROBE1(kssl_mblk__after_compute_MAC,
- mblk_t *, mp);
- }
-
- switch (content_type) {
- case content_handshake:
- do {
- DTRACE_PROBE1(kssl_mblk__content_handshake_cycle,
- mblk_t *, mp);
- if (error != 0 ||
- /* ignore client renegotiation for now */
- ssl->hs_waitstate == idle_handshake) {
- mp->b_rptr = recend;
- DTRACE_PROBE(kssl_renegotiation_request);
- }
- if (mp->b_rptr == recend) {
- mp->b_rptr = real_recend;
- if (error != 0) {
- goto error;
- }
- freeb(mp);
-
- if (ssl->hs_waitstate == wait_client_key_done)
- return (KSSL_CMD_QUEUED);
-
- return ((ssl->handshake_sendbuf != NULL) ?
- KSSL_CMD_SEND : KSSL_CMD_NONE);
- }
- if (ssl->msg.state < MSG_BODY) {
- if (ssl->msg.state == MSG_INIT) {
- ssl->msg.type =
- (SSL3HandshakeType)*mp->b_rptr++;
- ssl->msg.state = MSG_INIT_LEN;
- }
- if (ssl->msg.state == MSG_INIT_LEN) {
- int msglenb =
- ssl->msg.msglen_bytes;
- int msglen = ssl->msg.msglen;
- while (mp->b_rptr < recend &&
- msglenb < 3) {
- msglen = (msglen << 8) +
- (uint_t)(*mp->b_rptr++);
- msglenb++;
- }
- ssl->msg.msglen_bytes = msglenb;
- ssl->msg.msglen = msglen;
- if (msglenb == 3) {
- ssl->msg.state = MSG_BODY;
- }
- }
- if (mp->b_rptr == recend) {
- mp->b_rptr = real_recend;
- freeb(mp);
- return (KSSL_CMD_NONE);
- }
- }
- ASSERT(ssl->msg.state == MSG_BODY);
-
- sz = recend - mp->b_rptr;
-
- if (ssl->msg.head == NULL &&
- ssl->msg.msglen <= sz) {
- continue;
- }
- if (ssl->msg.head != NULL) {
- sz += msgdsize(ssl->msg.head);
- if (ssl->msg.msglen <= sz) {
- ssl->msg.tail->b_cont = mp;
- mp = ssl->msg.head;
- ssl->sslcnt = 100;
- ssl->msg.head = NULL;
- ssl->msg.tail = NULL;
- if (pullupmsg(mp, -1)) {
- recend = mp->b_rptr + sz;
- ASSERT(recend <= mp->b_wptr);
- continue;
- }
- mp->b_rptr = real_recend;
- error = ENOMEM;
- KSSL_COUNTER(alloc_fails, 1);
- goto error;
- }
- }
-
- mp->b_wptr = recend;
-
- if (ssl->msg.head == NULL) {
- ssl->msg.head = mp;
- ssl->msg.tail = mp;
- return (KSSL_CMD_NONE);
- } else {
- ssl->msg.tail->b_cont = mp;
- ssl->msg.tail = mp;
- return (KSSL_CMD_NONE);
- }
- } while (kssl_handle_handshake_message(ssl, mp, &error, cbfn,
- arg));
- if (error == SSL_MISS) {
- mp->b_rptr = save_rptr;
- mp->b_wptr = save_wptr;
- KSSL_COUNTER(fallback_connections, 1);
- return (KSSL_CMD_NOT_SUPPORTED);
- }
- if (ssl->hs_waitstate == wait_client_key_done) {
- return (KSSL_CMD_QUEUED);
- } else {
- return (KSSL_CMD_NONE);
- }
- case content_alert:
- DTRACE_PROBE1(kssl_mblk__content_alert, mblk_t *, mp);
- if (rec_sz != 2) {
- DTRACE_PROBE(kssl_err__illegal_param);
- mp->b_rptr = real_recend;
- desc = illegal_parameter;
- goto sendalert;
- } else {
- level = *mp->b_rptr++;
- desc = *mp->b_rptr++;
- mp->b_rptr = real_recend;
- if (level != alert_warning || desc != close_notify) {
- if (ssl->sid.cached == B_TRUE) {
- kssl_uncache_sid(&ssl->sid,
- ssl->kssl_entry);
- }
- DTRACE_PROBE2(kssl_err__bad_content_alert,
- SSL3AlertLevel, level,
- SSL3AlertDescription, desc);
- ssl->fatal_alert = B_TRUE;
- error = EBADMSG;
- goto error;
- } else {
- ssl->close_notify_clnt = B_TRUE;
- ssl->activeinput = B_FALSE;
- freeb(mp);
- return (KSSL_CMD_NONE);
- }
- }
- case content_change_cipher_spec:
- DTRACE_PROBE1(kssl_mblk__change_cipher_spec,
- mblk_t *, mp);
- if (ssl->hs_waitstate != wait_change_cipher) {
- desc = unexpected_message;
- } else if (rec_sz != 1 || *mp->b_rptr != 1) {
- desc = illegal_parameter;
- } else {
- mp->b_rptr = real_recend;
- ssl->hs_waitstate = wait_finished;
- ssl->seq_num[KSSL_READ] = 0;
- if ((error = kssl_spec_init(ssl, KSSL_READ)) != 0) {
- DTRACE_PROBE1(kssl_err__kssl_spec_init_error,
- int, error);
- goto error;
- }
- ssl->activeinput = B_FALSE;
- freeb(mp);
- return (KSSL_CMD_NONE);
- }
- mp->b_rptr = real_recend;
- DTRACE_PROBE(kssl_err__change_cipher_spec);
- goto sendalert;
-
- case content_application_data:
- DTRACE_PROBE1(kssl_mblk__content_app_data,
- mblk_t *, mp);
- if (ssl->hs_waitstate != idle_handshake) {
- DTRACE_PROBE(kssl_err__content_app_data);
- mp->b_rptr = real_recend;
- desc = unexpected_message;
- goto sendalert;
- }
- mp->b_wptr = recend;
- *decrmp = mp;
- ssl->activeinput = B_FALSE;
- return (KSSL_CMD_DELIVER_PROXY);
-
- case content_handshake_v2:
- DTRACE_PROBE1(kssl_mblk__content_handshake_v2,
- mblk_t *, mp);
- error = kssl_handle_v2client_hello(ssl, mp, rec_sz);
- if (error == SSL_MISS) {
- mp->b_rptr = save_rptr;
- mp->b_wptr = save_wptr;
- KSSL_COUNTER(fallback_connections, 1);
- return (KSSL_CMD_NOT_SUPPORTED);
- } else if (error != 0) {
- DTRACE_PROBE(kssl_err__v2client_hello_failed);
- goto error;
- }
- freeb(mp);
- return (KSSL_CMD_SEND);
- default:
- DTRACE_PROBE1(kssl_mblk__unexpected_msg,
- mblk_t *, mp);
- mp->b_rptr = real_recend;
- desc = unexpected_message;
- break;
- }
-
-sendalert:
- kssl_send_alert(ssl, alert_fatal, desc);
- *decrmp = ssl->alert_sendbuf;
- ssl->alert_sendbuf = NULL;
- freeb(mp);
- return ((*decrmp != NULL) ? KSSL_CMD_SEND : KSSL_CMD_NONE);
-error:
- freeb(mp);
- return (KSSL_CMD_NONE);
-}
-
-/*
- * Initialize the context of an SSL connection, coming to the specified
- * address. The ssl structure is returned held.
- */
-kssl_status_t
-kssl_init_context(kssl_ent_t kssl_ent, struct sockaddr *addr, int mss,
- kssl_ctx_t *kssl_ctxp)
-{
- ssl_t *ssl = kmem_cache_alloc(kssl_cache, KM_NOSLEEP);
- struct sockaddr_in *sin = (struct sockaddr_in *)addr;
-
- if (ssl == NULL) {
- return (KSSL_STS_ERR);
- }
-
- bzero(ssl, sizeof (ssl_t));
-
- ssl->kssl_entry = (kssl_entry_t *)kssl_ent;
- KSSL_ENTRY_REFHOLD(ssl->kssl_entry);
-
- if (sin->sin_family == AF_INET) {
- IN6_IPADDR_TO_V4MAPPED(sin->sin_addr.s_addr, &ssl->faddr);
- } else {
- /* struct assignment */
- ssl->faddr = ((struct sockaddr_in6 *)addr)->sin6_addr;
- }
- ssl->tcp_mss = mss;
- ssl->sendalert_level = alert_warning;
- ssl->sendalert_desc = close_notify;
- ssl->sid.cached = B_FALSE;
-
- *kssl_ctxp = (kssl_ctx_t)ssl;
- return (KSSL_STS_OK);
-}
-
-void
-kssl_set_mss(kssl_ctx_t ctx, uint32_t mss)
-{
- ssl_t *ssl = (ssl_t *)ctx;
- ssl->tcp_mss = mss;
-}
-
-/*
- * Builds SSL records out of the chain of mblks, and returns it.
- * Takes a copy of the message before encrypting it if it has another
- * reference.
- * In case of failure, NULL is returned, and the message will be
- * freed by the caller.
- * A NULL mp means a close_notify is requested.
- */
-mblk_t *
-kssl_build_record(kssl_ctx_t ctx, mblk_t *mp)
-{
- ssl_t *ssl = (ssl_t *)ctx;
- mblk_t *retmp = mp, *bp = mp, *prevbp = mp, *copybp;
-
- ASSERT(ssl != NULL);
-
- /*
- * Produce new close_notify message. This is necessary to perform
- * proper cleanup w.r.t. SSL protocol spec by sending close_notify SSL
- * alert record if running with KSSL proxy.
- * This should be done prior to sending the FIN so the client side can
- * attempt to do graceful cleanup. Ideally, we should wait for client's
- * close_notify but not all clients send it which would hang the
- * connection. This way of closing the SSL session (Incomplete Close)
- * prevents truncation attacks for protocols without end-of-data
- * markers (as opposed to the Premature Close).
- * Checking the close_notify_srvr flag will prevent from sending the
- * close_notify message twice in case of duplicate shutdown() calls.
- */
- if (mp == NULL && !ssl->close_notify_srvr) {
- kssl_send_alert(ssl, alert_warning, close_notify);
- if (ssl->alert_sendbuf == NULL)
- return (NULL);
- mp = bp = retmp = prevbp = ssl->alert_sendbuf;
- ssl->alert_sendbuf = NULL;
- ssl->close_notify_srvr = B_TRUE;
- }
-
- ASSERT(mp != NULL);
- ASSERT(bp != NULL);
-
- do {
- if (DB_REF(bp) > 1) {
- /*
- * Fortunately copyb() preserves the offset,
- * tail space and alignment so the copy is
- * ready to be made an SSL record.
- */
- if ((copybp = copyb(bp)) == NULL)
- return (NULL);
-
- copybp->b_cont = bp->b_cont;
- if (bp == mp) {
- retmp = copybp;
- } else {
- prevbp->b_cont = copybp;
- }
- freeb(bp);
- bp = copybp;
- }
-
- if (kssl_build_single_record(ssl, bp) != KSSL_STS_OK)
- return (NULL);
-
- prevbp = bp;
- bp = bp->b_cont;
- } while (bp != NULL);
-
- return (retmp);
-}
-
-/*
- * Builds a single SSL record by prepending SSL header (optional) and performing
- * encryption and MAC. The encryption of the record is done in-line.
- * Expects an mblk with associated dblk's base to have space for the SSL header
- * or an mblk which already has the header present. In both cases it presumes
- * that the mblk's dblk limit has space for the MAC + padding.
- * If the close_notify_srvr flag is set it is presumed that the mblk already
- * contains SSL header in which case only the record length field will be
- * adjusted with the MAC/padding size.
- */
-static kssl_status_t
-kssl_build_single_record(ssl_t *ssl, mblk_t *mp)
-{
- int len;
- int reclen;
- uchar_t *recstart, *versionp;
- KSSLCipherSpec *spec;
- int mac_sz;
- int pad_sz;
-
- spec = &ssl->spec[KSSL_WRITE];
- mac_sz = spec->mac_hashsz;
-
- ASSERT(DB_REF(mp) == 1);
- /* The dblk must always have space for the padding and MAC suffix. */
- ASSERT(mp->b_datap->db_lim - mp->b_wptr >= mac_sz + spec->cipher_bsize);
-
- /* kssl_send_alert() constructs the SSL header by itself. */
- if (!ssl->close_notify_srvr)
- len = MBLKL(mp) - SSL3_HDR_LEN;
- else
- len = MBLKL(mp);
-
- ASSERT(len > 0);
-
- mutex_enter(&ssl->kssl_lock);
-
- recstart = mp->b_rptr;
- if (!ssl->close_notify_srvr) {
- /* The dblk must have space for the SSL header prefix. */
- ASSERT(mp->b_rptr - mp->b_datap->db_base >= SSL3_HDR_LEN);
- recstart = mp->b_rptr = mp->b_rptr - SSL3_HDR_LEN;
- recstart[0] = content_application_data;
- recstart[1] = ssl->major_version;
- recstart[2] = ssl->minor_version;
- }
- versionp = &recstart[1];
-
- reclen = len + mac_sz;
- if (spec->cipher_type == type_block) {
- pad_sz = spec->cipher_bsize -
- (reclen & (spec->cipher_bsize - 1));
- ASSERT(reclen + pad_sz <=
- SSL3_MAX_RECORD_LENGTH);
- reclen += pad_sz;
- }
- recstart[3] = (reclen >> 8) & 0xff;
- recstart[4] = reclen & 0xff;
-
- if (kssl_mac_encrypt_record(ssl, recstart[0], versionp,
- recstart, mp) != 0) {
- /* Do we need an internal_error Alert here? */
- mutex_exit(&ssl->kssl_lock);
- return (KSSL_STS_ERR);
- }
-
- /* Alert messages are accounted in kssl_send_alert(). */
- if (recstart[0] == content_application_data)
- KSSL_COUNTER(appdata_record_outs, 1);
- mutex_exit(&ssl->kssl_lock);
- return (KSSL_STS_OK);
-}
diff --git a/usr/src/uts/common/inet/kssl/ksslapi.h b/usr/src/uts/common/inet/kssl/ksslapi.h
deleted file mode 100644
index 640e3f53de..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslapi.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef _INET_KSSL_KSSLAPI_H
-#define _INET_KSSL_KSSLAPI_H
-
-/*
- * The kernel SSL proxy interface
- */
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-/* return status for the kssl API functions */
-
-typedef enum {
- KSSL_STS_OK, /* No further processing required */
- KSSL_STS_ERR /* bogus argument ... */
-} kssl_status_t;
-
-/* Endpoint type */
-typedef enum {
- KSSL_NO_PROXY = 0, /* Not configured for use with KSSL */
- KSSL_IS_PROXY, /* Acts as a proxy for someone else */
- KSSL_HAS_PROXY /* A proxy is handling its work */
-} kssl_endpt_type_t;
-
-/* Return codes/commands from kssl_handle_record */
-typedef enum {
- KSSL_CMD_NOT_SUPPORTED, /* Not supported */
- KSSL_CMD_SEND, /* send this packet out on the wire */
- KSSL_CMD_DELIVER_PROXY, /* deliver this packet to proxy listener */
- KSSL_CMD_DELIVER_SSL, /* Deliver to the SSL listener */
- KSSL_CMD_NONE, /* consider it consumed. (ACK it, ... */
- KSSL_CMD_QUEUED /* Queued, a call back will finish it */
-} kssl_cmd_t;
-
-/* Un opaque context of an SSL connection */
-typedef void *kssl_ctx_t;
-
-/* Un opaque handle for an SSL map entry */
-typedef void *kssl_ent_t;
-
-#define SSL3_HDR_LEN 5
-#define SSL3_WROFFSET 7 /* 5 hdr + 2 byte-alignment */
-#define SSL3_MAX_TAIL_LEN 36 /* 16 AES blocks + 20 SHA1 digest */
-#define SSL3_MAX_RECORD_LEN 16384 - 1 - SSL3_HDR_LEN - SSL3_MAX_TAIL_LEN
-
-
-kssl_endpt_type_t kssl_check_proxy(struct sockaddr *, socklen_t, void *,
- kssl_ent_t *);
-
-kssl_status_t kssl_init_context(kssl_ent_t, struct sockaddr *, int,
- kssl_ctx_t *);
-void kssl_set_mss(kssl_ctx_t, uint32_t);
-
-void kssl_hold_ent(kssl_ent_t);
-void kssl_release_ent(kssl_ent_t, void *, kssl_endpt_type_t);
-void *kssl_find_fallback(kssl_ent_t);
-
-void kssl_release_ctx(kssl_ctx_t);
-void kssl_async_done(kssl_ctx_t);
-
-typedef void (*kssl_callback_t)(void *arg, mblk_t *mp, kssl_cmd_t cmd);
-
-kssl_cmd_t kssl_input(kssl_ctx_t, mblk_t *, mblk_t **, boolean_t *,
- kssl_callback_t cbfn, void *arg);
-
-kssl_cmd_t kssl_handle_mblk(kssl_ctx_t, mblk_t **, mblk_t **);
-
-mblk_t *kssl_build_record(kssl_ctx_t, mblk_t *);
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INET_KSSL_KSSLAPI_H */
diff --git a/usr/src/uts/common/inet/kssl/ksslfilter.c b/usr/src/uts/common/inet/kssl/ksslfilter.c
deleted file mode 100644
index ea9e2f9232..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslfilter.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <sys/systm.h>
-#include <sys/cmn_err.h>
-#include <sys/stropts.h>
-#include <sys/strsun.h>
-#include <sys/socketvar.h>
-#include <sys/sockfilter.h>
-#include <inet/kssl/ksslapi.h>
-#include <sys/note.h>
-#include <sys/taskq.h>
-
-/*
- * Name of the KSSL filter
- */
-#define KSSL_FILNAME "ksslf"
-
-static struct modlmisc ksslf_modlmisc = {
- &mod_miscops,
- "Kernel SSL socket filter"
-};
-
-static struct modlinkage ksslf_modlinkage = {
- MODREV_1,
- &ksslf_modlmisc,
- NULL
-};
-
-/*
- * kssl filter cookie
- */
-typedef struct ksslf {
- boolean_t ksslf_pending; /* waiting for 1st SSL rec. */
- boolean_t ksslf_inhandshake; /* during SSL handshake */
- kssl_ent_t ksslf_ent; /* SSL table entry */
- kssl_ctx_t ksslf_ctx; /* SSL session */
- kssl_endpt_type_t ksslf_type; /* is proxy/is proxied/none */
- struct sockaddr_in6 ksslf_laddr; /* local address */
- socklen_t ksslf_laddrlen;
- struct ksslf *ksslf_listener;
-} ksslf_t;
-
-static void kssl_input_callback(void *, mblk_t *, kssl_cmd_t);
-
-/*
- * Allocate kssl state
- */
-sof_rval_t
-kssl_attach_passive_cb(sof_handle_t handle, sof_handle_t ph,
- void *parg, struct sockaddr *laddr, socklen_t laddrlen,
- struct sockaddr *faddr, socklen_t faddrlen, void **cookiep)
-{
- ksslf_t *listener = (ksslf_t *)parg;
- ksslf_t *new;
-
- _NOTE(ARGUNUSED(handle, ph, faddrlen, laddr, laddrlen));
-
- if (listener == NULL || listener->ksslf_ent == NULL)
- return (SOF_RVAL_DETACH);
- /*
- * Only way for a fallback listener to receive connections is when
- * a handshake fails and socket is moved from the proxy to the fallback.
- * Connections that come in directly on the fallback are denied.
- */
- if (listener->ksslf_type == KSSL_HAS_PROXY)
- return (SOF_RVAL_EACCES);
-
- /* Allocate the SSL context for the new connection */
- new = kmem_zalloc(sizeof (ksslf_t), KM_NOSLEEP);
- if (new == NULL)
- return (SOF_RVAL_ENOMEM);
-
- /*
- * The mss is initialized to SSL3_MAX_RECORD_LEN, but might be
- * updated by the mblk_prop callback.
- */
- if (kssl_init_context(listener->ksslf_ent, faddr, SSL3_MAX_RECORD_LEN,
- &new->ksslf_ctx) != KSSL_STS_OK)
- return (SOF_RVAL_ENOMEM);
-
- new->ksslf_pending = B_TRUE;
- new->ksslf_inhandshake = B_TRUE;
- ASSERT(laddrlen <= sizeof (new->ksslf_laddr));
- new->ksslf_laddrlen = laddrlen;
- bcopy(laddr, &new->ksslf_laddr, laddrlen);
- new->ksslf_laddr.sin6_port = listener->ksslf_laddr.sin6_port;
- new->ksslf_listener = listener;
-
- *cookiep = new;
- /*
- * We are in handshake, defer the notification of this connection
- * until it is completed.
- */
- return (SOF_RVAL_DEFER);
-}
-
-void
-kssl_detach_cb(sof_handle_t handle, void *cookie, cred_t *cr)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
-
- _NOTE(ARGUNUSED(handle, cr));
-
- if (kssl == NULL)
- return;
-
- if (kssl->ksslf_ent != NULL) {
- kssl_release_ent(kssl->ksslf_ent, handle, kssl->ksslf_type);
- kssl->ksslf_ent = NULL;
- }
- if (kssl->ksslf_ctx != NULL) {
- kssl_release_ctx(kssl->ksslf_ctx);
- kssl->ksslf_ctx = NULL;
- }
-
- kmem_free(kssl, sizeof (ksslf_t));
-}
-
-sof_rval_t
-kssl_bind_cb(sof_handle_t handle, void *cookie, struct sockaddr *name,
- socklen_t *namelen, cred_t *cr)
-{
- kssl_ent_t ent;
- kssl_endpt_type_t type;
- ksslf_t *kssl;
- in_port_t origport;
-
- _NOTE(ARGUNUSED(cr));
-
- if (cookie != NULL)
- return (SOF_RVAL_EINVAL);
-
- if (*namelen < sizeof (struct sockaddr_in)) {
- sof_bypass(handle);
- return (SOF_RVAL_CONTINUE);
- }
-
- origport = ((struct sockaddr_in *)name)->sin_port;
- /* Check if KSSL has been configured for this address */
- type = kssl_check_proxy(name, *namelen, handle, &ent);
-
- switch (type) {
- case KSSL_NO_PROXY:
- sof_bypass(handle);
- break;
- case KSSL_HAS_PROXY:
- case KSSL_IS_PROXY:
- kssl = kmem_zalloc(sizeof (ksslf_t), KM_SLEEP);
- kssl->ksslf_type = type;
- kssl->ksslf_ent = ent;
-
- /*
- * In the unlikely event that there are multiple simultaneous
- * bind requests, and the cookie was already swapped out, then
- * just drop this cookie and let the bind continue unmodified.
- */
- if (sof_cas_cookie(handle, cookie, kssl) != cookie) {
- kssl_release_ent(ent, handle, type);
- kmem_free(kssl, sizeof (ksslf_t));
- ((struct sockaddr_in *)name)->sin_port = origport;
- break;
- }
-
- kssl->ksslf_laddrlen = *namelen;
- bcopy(name, &kssl->ksslf_laddr, kssl->ksslf_laddrlen);
- kssl->ksslf_laddr.sin6_port = origport;
- /*
- * kssl_check_proxy updated the sockaddr, so just
- * pass it along to the protocol.
- */
- return ((type == KSSL_HAS_PROXY) ? SOF_RVAL_RETURN :
- SOF_RVAL_CONTINUE);
- }
- return (SOF_RVAL_CONTINUE);
-}
-
-sof_rval_t
-kssl_listen_cb(sof_handle_t handle, void *cookie, int *backlog, cred_t *cr)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
-
- _NOTE(ARGUNUSED(backlog, cr));
-
- /*
- * The cookie can be NULL in the unlikely event of an application doing
- * listen() without binding to an address. Those listeners are of no
- * interest.
- */
- if (kssl == NULL) {
- sof_bypass(handle);
- return (SOF_RVAL_CONTINUE);
- }
-
- return (SOF_RVAL_CONTINUE);
-
-}
-
-/*
- * Outgoing connections are not of interest, so just bypass the filter.
- */
-sof_rval_t
-kssl_connect_cb(sof_handle_t handle, void *cookie, struct sockaddr *name,
- socklen_t *namelen, cred_t *cr)
-{
- _NOTE(ARGUNUSED(cookie, name, namelen, cr));
-
- sof_bypass(handle);
- return (SOF_RVAL_CONTINUE);
-}
-
-static void
-kssl_mblk_prop_cb(sof_handle_t handle, void *cookie, ssize_t *maxblk,
- ushort_t *wroff, ushort_t *tail)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
-
- _NOTE(ARGUNUSED(handle));
-
- /* only care about passively opened sockets */
- if (kssl == NULL || !kssl->ksslf_pending)
- return;
- /*
- * If this is endpoint is handling SSL, then reserve extra
- * offset and space at the end. Also have sockfs allocate
- * SSL3_MAX_RECORD_LEN packets, overriding the previous setting.
- * The extra cost of signing and encrypting multiple MSS-size
- * records (12 of them with Ethernet), instead of a single
- * contiguous one by the stream head largely outweighs the
- * statistical reduction of ACKs, when applicable. The peer
- * will also save on decryption and verification costs.
- */
- if (*maxblk == INFPSZ || *maxblk > SSL3_MAX_RECORD_LEN)
- *maxblk = SSL3_MAX_RECORD_LEN;
- else
- kssl_set_mss(kssl->ksslf_ctx, *maxblk);
- *wroff += SSL3_WROFFSET;
- *tail += SSL3_MAX_TAIL_LEN;
-}
-
-sof_rval_t
-kssl_getsockname_cb(sof_handle_t handle, void *cookie, struct sockaddr *addr,
- socklen_t *addrlen, cred_t *cr)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
-
- _NOTE(ARGUNUSED(handle, cr));
-
- if (kssl == NULL)
- return (SOF_RVAL_CONTINUE);
-
- if (*addrlen < kssl->ksslf_laddrlen)
- return (SOF_RVAL_EINVAL);
-
- *addrlen = kssl->ksslf_laddrlen;
- bcopy(&kssl->ksslf_laddr, addr, kssl->ksslf_laddrlen);
-
- return (SOF_RVAL_RETURN);
-}
-
-/*
- * Called for every packet sent to the protocol.
- * If the message is successfully processed, then it is returned.
- */
-mblk_t *
-kssl_data_out_cb(sof_handle_t handle, void *cookie, mblk_t *mp,
- struct nmsghdr *msg, cred_t *cr, sof_rval_t *rv)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
- mblk_t *recmp;
-
- _NOTE(ARGUNUSED(handle, msg, cr));
-
- *rv = SOF_RVAL_CONTINUE;
- if (kssl == NULL || kssl->ksslf_ctx == NULL)
- return (mp);
-
- if ((recmp = kssl_build_record(kssl->ksslf_ctx, mp)) == NULL) {
- freemsg(mp);
- *rv = SOF_RVAL_EINVAL;
- return (NULL);
- }
- return (recmp);
-}
-
-/*
- * Called from shutdown() processing. This will produce close_notify message
- * to indicate the end of data to the client.
- */
-sof_rval_t
-kssl_shutdown_cb(sof_handle_t handle, void *cookie, int *howp, cred_t *cr)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
- mblk_t *outmp;
- boolean_t flowctrld;
- struct nmsghdr msg;
-
- _NOTE(ARGUNUSED(cr));
-
- if (kssl == NULL || kssl->ksslf_ctx == NULL)
- return (SOF_RVAL_CONTINUE);
-
- /*
- * We only want to send close_notify when doing SHUT_WR/SHUT_RDWR
- * because it signals that server is done writing data.
- */
- if (*howp == SHUT_RD)
- return (SOF_RVAL_CONTINUE);
-
- /* Go on if we fail to build the record. */
- if ((outmp = kssl_build_record(kssl->ksslf_ctx, NULL)) == NULL)
- return (SOF_RVAL_CONTINUE);
-
- bzero(&msg, sizeof (msg));
- (void) sof_inject_data_out(handle, outmp, &msg,
- &flowctrld);
-
- return (SOF_RVAL_CONTINUE);
-}
-
-/*
- * Called for each incoming segment.
- *
- * A packet may carry multiple SSL records, so the function calls
- * kssl_input() in a loop, until all records are handled.
- */
-mblk_t *
-kssl_data_in_cb(sof_handle_t handle, void *cookie, mblk_t *mp, int flags,
- size_t *lenp)
-{
- ksslf_t *kssl = cookie;
- kssl_cmd_t kssl_cmd;
- mblk_t *outmp, *retmp = NULL, **tail = &retmp;
- boolean_t more = B_FALSE;
- boolean_t flowctrld;
-
- _NOTE(ARGUNUSED(flags));
-
- if (kssl == NULL || kssl->ksslf_ctx == NULL) {
- sof_bypass(handle);
- return (mp);
- }
-
- *lenp = 0;
- do {
- kssl_cmd = kssl_input(kssl->ksslf_ctx, mp, &outmp,
- &more, kssl_input_callback, (void *)handle);
-
- switch (kssl_cmd) {
- case KSSL_CMD_SEND: {
- struct nmsghdr msg;
-
- DTRACE_PROBE(kssl_cmd_send);
- bzero(&msg, sizeof (msg));
- (void) sof_inject_data_out(handle, outmp, &msg,
- &flowctrld);
- }
- /* FALLTHROUGH */
- case KSSL_CMD_NONE:
- DTRACE_PROBE(kssl_cmd_none);
- if (kssl->ksslf_pending) {
- kssl->ksslf_pending = B_FALSE;
- sof_newconn_ready(handle);
- }
- break;
-
- case KSSL_CMD_QUEUED:
- DTRACE_PROBE(kssl_cmd_queued);
- break;
-
- case KSSL_CMD_DELIVER_PROXY:
- case KSSL_CMD_DELIVER_SSL:
- DTRACE_PROBE(kssl_cmd_proxy__ssl);
- /*
- * We're at a phase where records are sent upstreams,
- * past the handshake
- */
- kssl->ksslf_inhandshake = B_FALSE;
-
- *tail = outmp;
- *lenp += MBLKL(outmp);
- while (outmp->b_cont != NULL) {
- outmp = outmp->b_cont;
- *lenp += MBLKL(outmp);
- }
- tail = &outmp->b_cont;
- break;
-
- case KSSL_CMD_NOT_SUPPORTED: {
- ksslf_t *listener = kssl->ksslf_listener;
- sof_handle_t fallback;
-
- DTRACE_PROBE(kssl_cmd_not_supported);
- /*
- * Stop the SSL processing by the proxy, and
- * switch to the userland SSL
- */
- if (kssl->ksslf_pending) {
- kssl->ksslf_pending = B_FALSE;
-
- DTRACE_PROBE1(kssl_no_can_do, sof_handle_t,
- handle);
-
- sof_bypass(handle);
-
- ASSERT(listener->ksslf_ent != NULL);
- fallback =
- kssl_find_fallback(listener->ksslf_ent);
- /*
- * No fallback: the remote will timeout and
- * disconnect.
- */
- if (fallback != NULL &&
- sof_newconn_move(handle, fallback))
- sof_newconn_ready(handle);
- }
- if (mp != NULL) {
- *tail = mp;
- *lenp += MBLKL(mp);
- while (mp->b_cont != NULL) {
- mp = mp->b_cont;
- *lenp += MBLKL(mp);
- }
- tail = &mp->b_cont;
- }
- break;
- }
- }
- mp = NULL;
- } while (more);
-
- return (retmp);
-}
-
-/*
- * Process queued data before it's copied by the user.
- *
- * If the message is successfully processed, then it is returned.
- * A failed message will be freed.
- */
-mblk_t *
-kssl_data_in_proc_cb(sof_handle_t handle, void *cookie, mblk_t *mp,
- cred_t *cr, size_t *lenp)
-{
- ksslf_t *kssl = (ksslf_t *)cookie;
- kssl_cmd_t kssl_cmd;
- mblk_t *out;
-
- _NOTE(ARGUNUSED(cr));
-
- if (kssl == NULL || kssl->ksslf_ctx)
- return (mp);
-
- *lenp = 0;
-
- kssl_cmd = kssl_handle_mblk(kssl->ksslf_ctx, &mp, &out);
-
- switch (kssl_cmd) {
- case KSSL_CMD_NONE:
- return (NULL);
- case KSSL_CMD_DELIVER_PROXY:
- *lenp = msgdsize(mp);
- return (mp);
- case KSSL_CMD_SEND: {
- struct nmsghdr msg;
- boolean_t flowctrld;
-
- ASSERT(out != NULL);
- bzero(&msg, sizeof (msg));
-
- (void) sof_inject_data_out(handle, out, &msg,
- &flowctrld);
- return (NULL);
- }
- default:
- /* transient error. */
- return (NULL);
- }
-}
-
-/*
- * Continue processing the incoming flow after an asynchronous callback.
- */
-static void
-kssl_input_asynch(void *arg)
-{
- sof_handle_t handle = (sof_handle_t)arg;
- ksslf_t *kssl = (ksslf_t *)sof_get_cookie(handle);
- size_t len = 0;
- boolean_t flowctrld;
- mblk_t *mp;
-
- if ((mp = kssl_data_in_cb(handle, kssl, NULL, 0, &len)) != NULL) {
- ASSERT(len != 0);
- (void) sof_inject_data_in(handle, mp, len, 0, &flowctrld);
- }
- kssl_async_done(kssl->ksslf_ctx);
-}
-
-/*
- * Callback function for the cases kssl_input() had to submit an asynchronous
- * job and need to come back when done to carry on the input processing.
- * This routine follows the conentions of timeout and interrupt handlers.
- * (no blocking, ...)
- */
-static void
-kssl_input_callback(void *arg, mblk_t *mp, kssl_cmd_t kssl_cmd)
-{
- sof_handle_t handle = (sof_handle_t)arg;
- ksslf_t *kssl = (ksslf_t *)sof_get_cookie(handle);
- boolean_t flowctrld;
-
- ASSERT(kssl != NULL);
-
- switch (kssl_cmd) {
- case KSSL_CMD_SEND: {
- struct nmsghdr msg;
-
- if (mp == NULL)
- break;
- bzero(&msg, sizeof (msg));
-
- (void) sof_inject_data_out(handle, mp, &msg, &flowctrld);
- }
- /* FALLTHROUGH */
- case KSSL_CMD_NONE:
- break;
-
- case KSSL_CMD_DELIVER_PROXY:
- case KSSL_CMD_DELIVER_SSL:
- (void) sof_inject_data_in(handle, mp, msgdsize(mp), 0,
- &flowctrld);
- break;
-
- case KSSL_CMD_NOT_SUPPORTED:
- /* Stop the SSL processing */
- sof_bypass(handle);
- }
- /*
- * Process any input that may have accumulated while we're waiting for
- * the call-back. This must be done by a taskq because kssl_input might
- * block when handling client_finish messages.
- */
- if (taskq_dispatch(system_taskq, kssl_input_asynch, handle,
- TQ_NOSLEEP) == TASKQID_INVALID) {
- DTRACE_PROBE(kssl_err__taskq_dispatch_failed);
- kssl_async_done(kssl->ksslf_ctx);
- }
-}
-
-sof_ops_t ksslf_ops = {
- .sofop_attach_passive = kssl_attach_passive_cb,
- .sofop_detach = kssl_detach_cb,
- .sofop_bind = kssl_bind_cb,
- .sofop_connect = kssl_connect_cb,
- .sofop_listen = kssl_listen_cb,
- .sofop_data_in = kssl_data_in_cb,
- .sofop_data_in_proc = kssl_data_in_proc_cb,
- .sofop_data_out = kssl_data_out_cb,
- .sofop_mblk_prop = kssl_mblk_prop_cb,
- .sofop_getsockname = kssl_getsockname_cb,
- .sofop_shutdown = kssl_shutdown_cb,
-};
-
-int
-_init(void)
-{
- int error;
-
- if ((error = sof_register(SOF_VERSION, KSSL_FILNAME,
- &ksslf_ops, 0)) != 0)
- return (error);
- if ((error = mod_install(&ksslf_modlinkage)) != 0)
- (void) sof_unregister(KSSL_FILNAME);
-
- return (error);
-}
-
-int
-_fini(void)
-{
- int error;
-
- if ((error = sof_unregister(KSSL_FILNAME)) != 0)
- return (error);
-
- return (mod_remove(&ksslf_modlinkage));
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&ksslf_modlinkage, modinfop));
-}
diff --git a/usr/src/uts/common/inet/kssl/ksslimpl.h b/usr/src/uts/common/inet/kssl/ksslimpl.h
deleted file mode 100644
index 95e83ee6b0..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslimpl.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef _INET_KSSL_KSSLIMPL_H
-#define _INET_KSSL_KSSLIMPL_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/socket.h>
-#include <sys/atomic.h>
-#include <sys/mutex.h>
-#include <sys/crypto/common.h>
-#include <sys/kstat.h>
-#include <sys/sdt.h>
-#include <inet/kssl/ksslapi.h>
-#include <inet/kssl/ksslproto.h>
-
-/*
- * Certificate structure. The msg field is the BER data of the
- * certificate.
- */
-typedef struct Certificate {
- uchar_t *msg;
- int len;
-} Certificate_t;
-
-/* Generic linked chain type */
-typedef struct kssl_chain_s {
- struct kssl_chain_s *next;
- void *item;
-} kssl_chain_t;
-
-/* Proxies chain. follows the generic kssl_chain_t layout */
-typedef struct kssl_proxy_s {
- struct kssl_proxy_s *next;
- void *proxy_bound;
-} kssl_proxy_t;
-
-/* Fallback endpoints chain. Ditto. */
-typedef struct kssl_fallback_s {
- struct kssl_fallback_s *next;
- void *fallback_bound;
-} kssl_fallback_t;
-
-/*
- * Structure to support using a non-extractable key in
- * a crypto provider. We keep the token label and pin so
- * that we can reauthenticate when needed.
- */
-typedef struct kssl_session_info_s {
- boolean_t is_valid_handle;
- boolean_t do_reauth;
- crypto_provider_t prov;
- crypto_session_id_t sid;
- crypto_key_t key;
- crypto_notify_handle_t evnt_handle;
- char toklabel[CRYPTO_EXT_SIZE_LABEL];
- int pinlen;
- char tokpin[1];
-} kssl_session_info_t;
-
-/* kssl_entry_t structure. */
-
-typedef struct kssl_entry_s {
- uint_t ke_refcnt; /* for hold/release */
- boolean_t ke_no_freeall;
- kmutex_t ke_mutex;
-
- in6_addr_t ke_laddr;
- in_port_t ke_ssl_port; /* SSL port */
- in_port_t ke_proxy_port; /* SSL proxy port */
-
- uint32_t sid_cache_timeout; /* In seconds */
- uint32_t sid_cache_nentries;
- kssl_sid_ent_t *sid_cache;
-
- uint16_t kssl_cipherSuites[CIPHER_SUITE_COUNT];
- int kssl_cipherSuites_nentries;
- uint16_t kssl_saved_Suites[CIPHER_SUITE_COUNT];
-
- boolean_t ke_is_nxkey;
- kssl_session_info_t *ke_sessinfo;
-
- crypto_key_t *ke_private_key; /* instance's private key */
- Certificate_t *ke_server_certificate;
-
- Certificate_t **ke_cacert_chain;
-
- kssl_proxy_t *ke_proxy_head; /* Proxies chain */
- kssl_fallback_t *ke_fallback_head; /* Fall-back endpoints chain */
-
-} kssl_entry_t;
-
-typedef struct mech_to_cipher_s {
- crypto_mech_type_t mech;
- char *name;
- uint16_t kssl_suites[CIPHER_SUITE_COUNT];
-} mech_to_cipher_t;
-
-#define KSSL_ENTRY_REFHOLD(kssl_entry) { \
- atomic_inc_32(&(kssl_entry)->ke_refcnt); \
- ASSERT((kssl_entry)->ke_refcnt != 0); \
-}
-
-#define KSSL_ENTRY_REFRELE(kssl_entry) { \
- ASSERT((kssl_entry)->ke_refcnt != 0); \
- membar_exit(); \
- if (atomic_dec_32_nv(&(kssl_entry)->ke_refcnt) == 0) { \
- kssl_free_entry((kssl_entry)); \
- } \
-}
-
-#define CRYPTO_ERR(r) ((r) != CRYPTO_SUCCESS && (r) != CRYPTO_QUEUED)
-
-/*
- * Enqueue mblk into KSSL input queue. Watch for mblk b_cont chains
- * returned by tcp_reass() and enqueue them properly. Caller should
- * be aware that mp is modified by this macro.
- */
-#define KSSL_ENQUEUE_MP(ssl, mp) { \
- DTRACE_PROBE1(kssl_mblk__enqueue_mp, mblk_t *, mp); \
- if ((ssl)->rec_ass_tail == NULL) { \
- (ssl)->rec_ass_head = (mp); \
- while (mp->b_cont) \
- mp = mp->b_cont; \
- (ssl)->rec_ass_tail = (mp); \
- } else { \
- (ssl)->rec_ass_tail->b_cont = (mp); \
- while (mp->b_cont) \
- mp = mp->b_cont; \
- (ssl)->rec_ass_tail = (mp); \
- } \
-}
-
-#define SSL_MISS 123 /* Internal SSL error */
-
-extern crypto_mechanism_t rsa_x509_mech;
-extern crypto_mechanism_t hmac_md5_mech;
-extern crypto_mechanism_t hmac_sha1_mech;
-extern crypto_call_flag_t kssl_call_flag;
-extern KSSLCipherDef cipher_defs[];
-
-extern struct kmem_cache *kssl_cache;
-
-#define KSSL_TAB_INITSIZE 4
-extern kssl_entry_t **kssl_entry_tab;
-extern int kssl_entry_tab_size;
-extern int kssl_entry_tab_nentries;
-extern kmutex_t kssl_tab_mutex;
-
-typedef struct kssl_stats {
- kstat_named_t sid_cache_lookups;
- kstat_named_t sid_cache_hits;
- kstat_named_t sid_cached;
- kstat_named_t sid_uncached;
- kstat_named_t full_handshakes;
- kstat_named_t resumed_sessions;
- kstat_named_t fallback_connections;
- kstat_named_t proxy_fallback_failed;
- kstat_named_t appdata_record_ins;
- kstat_named_t appdata_record_outs;
- kstat_named_t alloc_fails;
- kstat_named_t fatal_alerts;
- kstat_named_t warning_alerts;
- kstat_named_t no_suite_found;
- kstat_named_t compute_mac_failure;
- kstat_named_t verify_mac_failure;
- kstat_named_t record_decrypt_failure;
- kstat_named_t bad_pre_master_secret;
- kstat_named_t internal_errors;
-} kssl_stats_t;
-
-extern kssl_stats_t *kssl_statp;
-
-#define KSSL_COUNTER(p, v) atomic_add_64(&kssl_statp->p.value.ui64, v)
-
-#define IS_SSL_PORT 1
-#define IS_PROXY_PORT 2
-
-extern void kssl_free_entry(kssl_entry_t *);
-extern void kssl_free_context(ssl_t *);
-extern int kssl_compute_record_mac(ssl_t *, int, uint64_t, SSL3ContentType,
- uchar_t *, uchar_t *, int, uchar_t *);
-extern int kssl_handle_handshake_message(ssl_t *, mblk_t *, int *,
- kssl_callback_t, void *);
-extern int kssl_handle_v2client_hello(ssl_t *, mblk_t *, int);
-extern void kssl_uncache_sid(sslSessionID *, kssl_entry_t *);
-extern int kssl_mac_encrypt_record(ssl_t *, SSL3ContentType, uchar_t *,
- uchar_t *, mblk_t *);
-extern mblk_t *kssl_get_next_record(ssl_t *);
-extern int kssl_get_obj_handle(kssl_entry_t *);
-extern void kssl_prov_evnt(uint32_t, void *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INET_KSSL_KSSLIMPL_H */
diff --git a/usr/src/uts/common/inet/kssl/ksslioctl.c b/usr/src/uts/common/inet/kssl/ksslioctl.c
deleted file mode 100644
index 5542d13158..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslioctl.c
+++ /dev/null
@@ -1,767 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-/*
- * The kernel SSL module ioctls.
- */
-
-#include <sys/types.h>
-#include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/kmem.h>
-#include <sys/errno.h>
-#include <sys/file.h>
-#include <sys/cred.h>
-#include <sys/proc.h>
-#include <sys/task.h>
-#include <sys/model.h>
-#include <sys/sysmacros.h>
-#include <sys/policy.h>
-#include <sys/crypto/common.h>
-#include <sys/crypto/api.h>
-#include <inet/common.h>
-#include <inet/ip.h>
-
-#include "ksslimpl.h"
-#include "kssl.h"
-#include "ksslproto.h"
-
-kssl_entry_t **kssl_entry_tab;
-int kssl_entry_tab_size;
-int kssl_entry_tab_nentries;
-uint_t null_cipher_suite; /* setable in /etc/system */
-kmutex_t kssl_tab_mutex;
-
-static void
-certificate_free(Certificate_t *cert)
-{
- kmem_free(cert->msg, cert->len);
- kmem_free(cert, sizeof (struct Certificate));
-}
-
-static void
-privateKey_free(crypto_key_t *privkey)
-{
- int i;
- size_t attrs_size;
- crypto_object_attribute_t *attrs;
-
- attrs = privkey->ck_attrs;
- attrs_size = privkey->ck_count * sizeof (crypto_object_attribute_t);
- for (i = 0; i < privkey->ck_count; i++) {
- bzero(attrs[i].oa_value, attrs[i].oa_value_len);
- kmem_free(attrs[i].oa_value, attrs[i].oa_value_len);
- }
- kmem_free(attrs, attrs_size);
- kmem_free(privkey, sizeof (crypto_key_t));
-}
-
-static void
-sess_free(kssl_session_info_t *s)
-{
- if (s->is_valid_handle) {
- (void) crypto_session_logout(s->prov, s->sid, NULL);
- (void) crypto_session_close(s->prov, s->sid, NULL);
- crypto_release_provider(s->prov);
- s->is_valid_handle = B_FALSE;
- }
-
- if (s->evnt_handle != NULL) {
- crypto_unnotify_events(s->evnt_handle);
- s->evnt_handle = NULL;
- }
-
- bzero(s->tokpin, s->pinlen);
- kmem_free(s, sizeof (kssl_session_info_t) + s->pinlen);
-}
-
-/*
- * Frees the space for the entry and the keys and certs
- * it carries.
- */
-void
-kssl_free_entry(kssl_entry_t *kssl_entry)
-{
- int i;
- Certificate_t *cert;
- crypto_key_t *privkey;
- kssl_session_info_t *s;
-
- if (kssl_entry->ke_no_freeall) {
- kmem_free(kssl_entry, sizeof (kssl_entry_t));
- return;
- }
-
- if ((cert = kssl_entry->ke_server_certificate) != NULL) {
- certificate_free(cert);
- }
-
- if ((privkey = kssl_entry->ke_private_key) != NULL) {
- privateKey_free(privkey);
- }
-
- for (i = 0; i < kssl_entry->sid_cache_nentries; i++)
- mutex_destroy(&(kssl_entry->sid_cache[i].se_lock));
-
- kmem_free(kssl_entry->sid_cache,
- kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t));
-
- ASSERT(kssl_entry->ke_proxy_head == NULL);
- ASSERT(kssl_entry->ke_fallback_head == NULL);
-
- if ((s = kssl_entry->ke_sessinfo) != NULL) {
- ASSERT(kssl_entry->ke_is_nxkey);
- sess_free(s);
- }
-
- kmem_free(kssl_entry, sizeof (kssl_entry_t));
-}
-
-/*
- * Returns the index of the entry in kssl_entry_tab[] that matches
- * the address and port. Returns -1 if no match is found.
- */
-static int
-kssl_find_entry(in6_addr_t laddr, in_port_t port, int type,
- boolean_t wild_card_match)
-{
- int i;
- kssl_entry_t *ep;
-
- ASSERT(MUTEX_HELD(&kssl_tab_mutex));
-
- for (i = 0; i < kssl_entry_tab_size; i++) {
- ep = kssl_entry_tab[i];
- if (ep == NULL)
- continue;
-
- if (!((type == IS_SSL_PORT && ep->ke_ssl_port == port) ||
- (type == IS_PROXY_PORT && ep->ke_proxy_port == port)))
- continue;
-
- if (IN6_ARE_ADDR_EQUAL(&laddr, &ep->ke_laddr) ||
- (wild_card_match && (IN6_IS_ADDR_UNSPECIFIED(&laddr) ||
- IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr))))
- break;
- }
-
- if (i == kssl_entry_tab_size)
- return (-1);
-
- return (i);
-}
-
-static void
-copy_int_to_bytearray(int x, uchar_t *buf)
-{
- buf[0] = (x >> 16) & 0xff;
- buf[1] = (x >> 8) & 0xff;
- buf[2] = (x) & 0xff;
-}
-
-static int
-extract_certificate(kssl_params_t *kssl_params, Certificate_t **certpp)
-{
- int i, len;
- uint64_t in_size;
- uchar_t *end_pos;
- uint32_t ncert;
- uint32_t *cert_sizes;
- Certificate_t *cert;
- char *begin = (char *)kssl_params;
- uchar_t *cert_buf;
- int cert_buf_len;
- uchar_t *cert_from, *cert_to;
-
- ASSERT(kssl_params);
-
- in_size = kssl_params->kssl_params_size;
- end_pos = (uchar_t *)kssl_params + in_size;
-
- /*
- * Get the certs array. First the array of sizes, then the actual
- * certs.
- */
- ncert = kssl_params->kssl_certs.sc_count;
-
- if (ncert == 0) {
- /* no certs in here! why did ya call? */
- return (EINVAL);
- }
- if (in_size < (sizeof (kssl_params_t) + ncert * sizeof (uint32_t))) {
- return (EINVAL);
- }
-
- /* Trusting that the system call preserved the 4-byte alignment */
- cert_sizes = (uint32_t *)(begin +
- kssl_params->kssl_certs.sc_sizes_offset);
-
- /* should this be an ASSERT()? */
- if (!IS_P2ALIGNED(cert_sizes, sizeof (uint32_t))) {
- return (EINVAL);
- }
-
- len = 0;
- for (i = 0; i < ncert; i++) {
- if (cert_sizes[i] < 1) {
- return (EINVAL);
- }
- len += cert_sizes[i] + 3;
- }
-
- len += 3; /* length of certificate message without msg header */
-
- cert_buf_len = len + 4 + 4; /* add space for msg headers */
-
- cert_buf = kmem_alloc(cert_buf_len, KM_SLEEP);
-
- cert_buf[0] = (uchar_t)certificate;
- copy_int_to_bytearray(len, & cert_buf[1]);
- copy_int_to_bytearray(len - 3, & cert_buf[4]);
-
- cert_from = (uchar_t *)(begin +
- kssl_params->kssl_certs.sc_certs_offset);
- cert_to = &cert_buf[7];
-
- for (i = 0; i < ncert; i++) {
- copy_int_to_bytearray(cert_sizes[i], cert_to);
- cert_to += 3;
-
- if (cert_from + cert_sizes[i] > end_pos) {
- kmem_free(cert_buf, cert_buf_len);
- return (EINVAL);
- }
-
- bcopy(cert_from, cert_to, cert_sizes[i]);
- cert_from += cert_sizes[i];
- cert_to += cert_sizes[i];
- }
-
- len += 4;
- cert_buf[len] = (uchar_t)server_hello_done;
- copy_int_to_bytearray(0, & cert_buf[len + 1]);
-
- cert = kmem_alloc(sizeof (Certificate_t), KM_SLEEP);
- cert->msg = cert_buf;
- cert->len = cert_buf_len;
-
- *certpp = cert;
-
- return (0);
-}
-
-static int
-extract_private_key(kssl_params_t *kssl_params, crypto_key_t **privkey)
-{
- char *begin = (char *)kssl_params;
- char *end_pos;
- int i, j, rv;
- size_t attrs_size;
- crypto_object_attribute_t *newattrs;
- char *mp_attrs;
- kssl_object_attribute_t att;
- char *attval;
- uint32_t attlen;
- crypto_key_t *kssl_privkey;
-
- end_pos = (char *)kssl_params + kssl_params->kssl_params_size;
-
- kssl_privkey = kmem_alloc(sizeof (crypto_key_t), KM_SLEEP);
-
- kssl_privkey->ck_format = kssl_params->kssl_privkey.ks_format;
- kssl_privkey->ck_count = kssl_params->kssl_privkey.ks_count;
-
- switch (kssl_privkey->ck_format) {
- case CRYPTO_KEY_ATTR_LIST:
- break;
- case CRYPTO_KEY_RAW:
- case CRYPTO_KEY_REFERENCE:
- default:
- rv = EINVAL;
- goto err1;
- }
-
- /* allocate the attributes */
- attrs_size = kssl_privkey->ck_count *
- sizeof (crypto_object_attribute_t);
-
- mp_attrs = begin + kssl_params->kssl_privkey.ks_attrs_offset;
- if (mp_attrs + attrs_size > end_pos) {
- rv = EINVAL;
- goto err1;
- }
-
- newattrs = kmem_alloc(attrs_size, KM_SLEEP);
-
- /* Now the individual attributes */
- for (i = 0; i < kssl_privkey->ck_count; i++) {
- bcopy(mp_attrs, &att, sizeof (kssl_object_attribute_t));
-
- mp_attrs += sizeof (kssl_object_attribute_t);
-
- attval = begin + att.ka_value_offset;
- attlen = att.ka_value_len;
-
- if (attval + attlen > end_pos) {
- rv = EINVAL;
- goto err2;
- }
-
- newattrs[i].oa_type = att.ka_type;
- newattrs[i].oa_value_len = attlen;
- newattrs[i].oa_value = kmem_alloc(attlen, KM_SLEEP);
-
- bcopy(attval, newattrs[i].oa_value, attlen);
- }
-
- kssl_privkey->ck_attrs = newattrs;
-
- *privkey = kssl_privkey;
-
- return (0);
-
-err2:
- for (j = 0; j < i; j++) {
- bzero(newattrs[j].oa_value, newattrs[j].oa_value_len);
- kmem_free(newattrs[j].oa_value, newattrs[j].oa_value_len);
- }
- kmem_free(newattrs, attrs_size);
-err1:
- kmem_free(kssl_privkey, sizeof (crypto_key_t));
- return (rv);
-}
-
-static int
-create_sessinfo(kssl_params_t *kssl_params, kssl_entry_t *kssl_entry)
-{
- int rv;
- char *p;
- kssl_session_info_t *s;
- kssl_tokinfo_t *t;
-
- t = &kssl_params->kssl_token;
- /* Do a sanity check */
- if (t->pinlen > MAX_PIN_LENGTH) {
- return (EINVAL);
- }
-
- s = kmem_zalloc(sizeof (kssl_session_info_t) + t->pinlen, KM_SLEEP);
- s->pinlen = t->pinlen;
- bcopy(t->toklabel, s->toklabel, CRYPTO_EXT_SIZE_LABEL);
- p = (char *)kssl_params + t->tokpin_offset;
- bcopy(p, s->tokpin, s->pinlen);
- ASSERT(kssl_entry->ke_sessinfo == NULL);
- kssl_entry->ke_sessinfo = s;
-
- /* Get the handle to the non extractable key */
- rv = kssl_get_obj_handle(kssl_entry);
- kssl_params->kssl_token.ck_rv = rv;
- if (rv != CRYPTO_SUCCESS) {
- sess_free(s);
- kssl_entry->ke_sessinfo = NULL;
- return (EINVAL);
- }
-
- kssl_entry->ke_sessinfo->is_valid_handle = B_TRUE;
- kssl_entry->ke_sessinfo->do_reauth = B_FALSE;
- kssl_entry->ke_sessinfo->evnt_handle =
- crypto_notify_events(kssl_prov_evnt,
- CRYPTO_EVENT_PROVIDER_REGISTERED |
- CRYPTO_EVENT_PROVIDER_UNREGISTERED);
-
- return (0);
-}
-
-static kssl_entry_t *
-create_kssl_entry(kssl_params_t *kssl_params, Certificate_t *cert,
- crypto_key_t *privkey)
-{
- int i;
- uint16_t s;
- kssl_entry_t *kssl_entry, *ep;
- uint_t cnt, mech_count;
- crypto_mech_name_t *mechs;
- boolean_t got_rsa, got_md5, got_sha1, got_rc4, got_des, got_3des;
- boolean_t got_aes;
-
- kssl_entry = kmem_zalloc(sizeof (kssl_entry_t), KM_SLEEP);
-
- kssl_entry->ke_laddr = kssl_params->kssl_addr.sin6_addr;
- kssl_entry->ke_ssl_port = kssl_params->kssl_addr.sin6_port;
- kssl_entry->ke_proxy_port = kssl_params->kssl_proxy_port;
- if (kssl_params->kssl_session_cache_timeout == 0)
- kssl_entry->sid_cache_timeout = DEFAULT_SID_TIMEOUT;
- else
- kssl_entry->sid_cache_timeout =
- kssl_params->kssl_session_cache_timeout;
- if (kssl_params->kssl_session_cache_size == 0)
- kssl_entry->sid_cache_nentries = DEFAULT_SID_CACHE_NENTRIES;
- else
- kssl_entry->sid_cache_nentries =
- kssl_params->kssl_session_cache_size;
- kssl_entry->ke_private_key = privkey;
- kssl_entry->ke_server_certificate = cert;
-
- kssl_entry->ke_is_nxkey = kssl_params->kssl_is_nxkey;
- if (kssl_entry->ke_is_nxkey) {
- if (create_sessinfo(kssl_params, kssl_entry) != 0) {
- kmem_free(kssl_entry, sizeof (kssl_entry_t));
- return (NULL);
- }
- }
-
- mechs = crypto_get_mech_list(&mech_count, KM_SLEEP);
- if (mechs != NULL) {
- got_rsa = got_md5 = got_sha1 = got_rc4 =
- got_des = got_3des = got_aes = B_FALSE;
- for (i = 0; i < mech_count; i++) {
- if (strncmp(SUN_CKM_RSA_X_509, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_rsa = B_TRUE;
- else if (strncmp(SUN_CKM_MD5_HMAC, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_md5 = B_TRUE;
- else if (strncmp(SUN_CKM_SHA1_HMAC, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_sha1 = B_TRUE;
- else if (strncmp(SUN_CKM_RC4, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_rc4 = B_TRUE;
- else if (strncmp(SUN_CKM_DES_CBC, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_des = B_TRUE;
- else if (strncmp(SUN_CKM_DES3_CBC, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_3des = B_TRUE;
- else if (strncmp(SUN_CKM_AES_CBC, mechs[i],
- CRYPTO_MAX_MECH_NAME) == 0)
- got_aes = B_TRUE;
- }
-
- cnt = 0;
- ep = kssl_entry;
- for (i = 0; i < CIPHER_SUITE_COUNT - 1; i++) {
- switch (s = kssl_params->kssl_suites[i]) {
- case SSL_RSA_WITH_RC4_128_MD5:
- if (got_rsa && got_rc4 && got_md5)
- ep->kssl_cipherSuites[cnt++] = s;
- break;
- case SSL_RSA_WITH_RC4_128_SHA:
- if (got_rsa && got_rc4 && got_sha1)
- ep->kssl_cipherSuites[cnt++] = s;
- break;
- case SSL_RSA_WITH_DES_CBC_SHA:
- if (got_rsa && got_des && got_sha1)
- ep->kssl_cipherSuites[cnt++] = s;
- break;
- case SSL_RSA_WITH_3DES_EDE_CBC_SHA:
- if (got_rsa && got_3des && got_sha1)
- ep->kssl_cipherSuites[cnt++] = s;
- break;
- case TLS_RSA_WITH_AES_128_CBC_SHA:
- if (got_rsa && got_aes && got_sha1)
- ep->kssl_cipherSuites[cnt++] = s;
- break;
- case TLS_RSA_WITH_AES_256_CBC_SHA:
- if (got_rsa && got_aes && got_sha1)
- ep->kssl_cipherSuites[cnt++] = s;
- break;
- case CIPHER_NOTSET:
- default:
- break;
- }
- }
-
- crypto_free_mech_list(mechs, mech_count);
- }
-
- /*
- * Add the no encryption suite to the end if requested by the
- * kssl:null_cipher_suite /etc/system tunable since we do not want
- * to be running with it by default.
- */
- if (null_cipher_suite && got_rsa && got_sha1)
- kssl_entry->kssl_cipherSuites[cnt++] = SSL_RSA_WITH_NULL_SHA;
- kssl_entry->kssl_cipherSuites_nentries = cnt;
- for (i = 0; i < cnt; i++)
- kssl_entry->kssl_saved_Suites[i] =
- kssl_entry->kssl_cipherSuites[i];
-
- kssl_entry->sid_cache = kmem_alloc(
- kssl_entry->sid_cache_nentries * sizeof (kssl_sid_ent_t), KM_SLEEP);
-
- for (i = 0; i < kssl_entry->sid_cache_nentries; i++) {
- mutex_init(&(kssl_entry->sid_cache[i].se_lock), NULL,
- MUTEX_DEFAULT, NULL);
- kssl_entry->sid_cache[i].se_used = 0;
- kssl_entry->sid_cache[i].se_sid.cached = B_FALSE;
- }
-
- KSSL_ENTRY_REFHOLD(kssl_entry);
-
- return (kssl_entry);
-}
-
-int
-kssl_add_entry(kssl_params_t *kssl_params)
-{
- int rv, index, i;
- Certificate_t *cert;
- crypto_key_t *privkey;
- kssl_entry_t *kssl_entry;
- in6_addr_t laddr;
-
- if ((rv = extract_certificate(kssl_params, &cert)) != 0) {
- return (rv);
- }
-
- if ((rv = extract_private_key(kssl_params, &privkey)) != 0) {
- certificate_free(cert);
- return (rv);
- }
-
- kssl_entry = create_kssl_entry(kssl_params, cert, privkey);
- if (kssl_entry == NULL) {
- certificate_free(cert);
- privateKey_free(privkey);
- return (EINVAL);
- }
-
- laddr = kssl_params->kssl_addr.sin6_addr;
-
-retry:
- mutex_enter(&kssl_tab_mutex);
- /* Allocate the array first time here */
- if (kssl_entry_tab == NULL) {
- size_t allocsize;
- kssl_entry_t **tmp_tab;
- int tmp_size;
-
- tmp_size = KSSL_TAB_INITSIZE;
- allocsize = tmp_size * sizeof (kssl_entry_t *);
- mutex_exit(&kssl_tab_mutex);
- tmp_tab = kmem_zalloc(allocsize, KM_SLEEP);
- mutex_enter(&kssl_tab_mutex);
- if (kssl_entry_tab != NULL) {
- mutex_exit(&kssl_tab_mutex);
- kmem_free(tmp_tab, allocsize);
- goto retry;
- }
- kssl_entry_tab_size = tmp_size;
- kssl_entry_tab = tmp_tab;
- index = 0;
- } else {
- /* Check if a matching entry exists already */
- index = kssl_find_entry(laddr,
- kssl_params->kssl_addr.sin6_port, IS_SSL_PORT, B_TRUE);
-
- if (index == -1) {
- /* Check if an entry with the same proxy port exists */
- if (kssl_find_entry(laddr, kssl_params->kssl_proxy_port,
- IS_PROXY_PORT, B_TRUE) != -1) {
- mutex_exit(&kssl_tab_mutex);
- kssl_free_entry(kssl_entry);
- return (EADDRINUSE);
- }
-
- /* No matching entry, find an empty spot */
- for (i = 0; i < kssl_entry_tab_size; i++) {
- if (kssl_entry_tab[i] == NULL)
- break;
- }
- /* Table full. Gotta grow it */
- if (i == kssl_entry_tab_size) {
- kssl_entry_t **new_tab, **old_tab;
- size_t allocsize;
- size_t oldtabsize = kssl_entry_tab_size *
- sizeof (kssl_entry_t *);
- int tmp_size, old_size;
-
- tmp_size = old_size = kssl_entry_tab_size;
- tmp_size += KSSL_TAB_INITSIZE;
- allocsize = tmp_size * sizeof (kssl_entry_t *);
- mutex_exit(&kssl_tab_mutex);
- new_tab = kmem_zalloc(allocsize, KM_SLEEP);
- mutex_enter(&kssl_tab_mutex);
- if (kssl_entry_tab_size > old_size) {
- mutex_exit(&kssl_tab_mutex);
- kmem_free(new_tab, allocsize);
- goto retry;
- }
-
- kssl_entry_tab_size = tmp_size;
- bcopy(kssl_entry_tab, new_tab, oldtabsize);
-
- old_tab = kssl_entry_tab;
- kssl_entry_tab = new_tab;
-
- kmem_free(old_tab, oldtabsize);
- }
- index = i;
- } else {
- kssl_entry_t *ep;
-
- /*
- * We do not want an entry with a specific address and
- * an entry with IN_ADDR_ANY to coexist. We could
- * replace the existing entry. But, most likely this
- * is misconfiguration. Better bail out with an error.
- */
- ep = kssl_entry_tab[index];
-
- if ((IN6_IS_ADDR_UNSPECIFIED(&laddr) &&
- !IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr)) ||
- (!IN6_IS_ADDR_UNSPECIFIED(&laddr) &&
- IN6_IS_ADDR_UNSPECIFIED(&ep->ke_laddr))) {
- mutex_exit(&kssl_tab_mutex);
- kssl_free_entry(kssl_entry);
- return (EEXIST);
- }
-
- /* Replace the existing entry */
- KSSL_ENTRY_REFRELE(kssl_entry_tab[index]);
- kssl_entry_tab[index] = NULL;
- kssl_entry_tab_nentries--;
- }
- }
-
- kssl_entry_tab[index] = kssl_entry;
- kssl_entry_tab_nentries++;
- mutex_exit(&kssl_tab_mutex);
-
- return (0);
-}
-
-int
-kssl_delete_entry(struct sockaddr_in6 *kssl_addr)
-{
- in6_addr_t laddr;
- int index;
-
- laddr = kssl_addr->sin6_addr;
-
- mutex_enter(&kssl_tab_mutex);
- index = kssl_find_entry(laddr, kssl_addr->sin6_port,
- IS_SSL_PORT, B_FALSE);
-
- if (index == -1) {
- mutex_exit(&kssl_tab_mutex);
- return (ENOENT);
- }
-
- KSSL_ENTRY_REFRELE(kssl_entry_tab[index]);
- kssl_entry_tab[index] = NULL;
- kssl_entry_tab_nentries--;
-
- mutex_exit(&kssl_tab_mutex);
-
- return (0);
-}
-
-/*
- * We care about only one private key object.
- * So, set the max count to only 1.
- */
-#define MAX_OBJECT_COUNT 1
-
-/*
- * Open a session to the provider specified by the label and
- * authenticate to it. Find the private key object with the
- * specified attributes and save the handle. The userland component
- * must set all the attributes in the template so as to uniquely
- * identify the object.
- *
- * Note that the handle will be invalid if we logout or close
- * the session to the provider.
- */
-int
-kssl_get_obj_handle(kssl_entry_t *kp)
-{
- int rv;
- unsigned int count;
- void *cookie = NULL;
- crypto_provider_t prov;
- kssl_session_info_t *s;
- crypto_session_id_t sid;
- crypto_object_attribute_t *attrs;
- crypto_object_id_t ohndl[MAX_OBJECT_COUNT];
- char label[CRYPTO_EXT_SIZE_LABEL + 1];
-
- ASSERT(kp->ke_is_nxkey);
- s = kp->ke_sessinfo;
-
- bcopy(s->toklabel, label, CRYPTO_EXT_SIZE_LABEL);
- label[CRYPTO_EXT_SIZE_LABEL] = '\0';
- prov = crypto_get_provider(label, NULL, NULL);
- if (prov == NULL)
- return (CRYPTO_UNKNOWN_PROVIDER);
-
- rv = crypto_session_open(prov, &sid, NULL);
- if (rv != CRYPTO_SUCCESS) {
- goto err1;
- }
-
- rv = crypto_session_login(prov, sid, CRYPTO_USER,
- s->tokpin, s->pinlen, NULL);
- if (rv != CRYPTO_SUCCESS) {
- goto err2;
- }
-
- count = kp->ke_private_key->ck_count;
- attrs = kp->ke_private_key->ck_attrs;
-
- rv = crypto_object_find_init(prov, sid, attrs, count, &cookie, NULL);
- if (rv != CRYPTO_SUCCESS) {
- goto err3;
- }
-
- rv = crypto_object_find(prov, cookie, ohndl, &count,
- MAX_OBJECT_COUNT, NULL);
- if (rv != CRYPTO_SUCCESS || count == 0) {
- if (count == 0)
- rv = CRYPTO_FAILED;
- goto err3;
- }
-
- (void) crypto_object_find_final(prov, cookie, NULL);
-
- s->sid = sid;
- s->prov = prov;
- s->key.ck_format = CRYPTO_KEY_REFERENCE;
- /* Keep the handle around for later use */
- s->key.ck_obj_id = ohndl[0];
-
- return (CRYPTO_SUCCESS);
-
-err3:
- (void) crypto_session_logout(prov, sid, NULL);
-err2:
- (void) crypto_session_close(prov, sid, NULL);
-err1:
- crypto_release_provider(prov);
- return (rv);
-}
diff --git a/usr/src/uts/common/inet/kssl/ksslproto.h b/usr/src/uts/common/inet/kssl/ksslproto.h
deleted file mode 100644
index c982fe9dfd..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslproto.h
+++ /dev/null
@@ -1,339 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#ifndef _INET_KSSL_KSSLPROTO_H
-#define _INET_KSSL_KSSLPROTO_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <sys/md5.h>
-#include <sys/sha1.h>
-#include <sys/crypto/common.h>
-#include <sys/crypto/api.h>
-#include <inet/kssl/kssl.h> /* Cipher suite definitions */
-#include <inet/kssl/ksslapi.h>
-#include <inet/kssl/ksslimpl.h>
-
-#define SSL3_RANDOM_LENGTH 32
-#define SSL3_SESSIONID_BYTES 32
-#define SSL3_HDR_LEN 5
-#define SSL3_ALERT_LEN 2
-#define SSL3_MAX_RECORD_LENGTH 16384
-#define SSL3_PRE_MASTER_SECRET_LEN 48
-#define SSL3_MASTER_SECRET_LEN 48
-#define SSL3_MD5_PAD_LEN 48
-#define SSL3_SHA1_PAD_LEN 40
-
-#define SSL_MIN_CHALLENGE_BYTES 16
-#define SSL_MAX_CHALLENGE_BYTES 32
-
-#define SHA1_HASH_LEN 20
-#define MD5_HASH_LEN 16
-#define MAX_HASH_LEN SHA1_HASH_LEN
-
-#define KSSL_READ 0
-#define KSSL_WRITE 1
-
-#define KSSL_ENCRYPT 0
-#define KSSL_DECRYPT 1
-
-#define MSG_INIT 0
-#define MSG_INIT_LEN 1
-#define MSG_BODY 2
-
-/*
- * More than enough for the cipher suite that needs the
- * largest key material (AES_256_CBC_SHA needs 136 bytes).
- */
-#define MAX_KEYBLOCK_LENGTH 160
-
-#define TLS_MASTER_SECRET_LABEL "master secret"
-#define TLS_CLIENT_WRITE_KEY_LABEL "client write key"
-#define TLS_SERVER_WRITE_KEY_LABEL "server write key"
-#define TLS_CLIENT_FINISHED_LABEL "client finished"
-#define TLS_SERVER_FINISHED_LABEL "server finished"
-#define TLS_KEY_EXPANSION_LABEL "key expansion"
-#define TLS_IV_BLOCK_LABEL "IV block"
-#define TLS_MAX_LABEL_SIZE 24
-
-#define TLS_FINISHED_SIZE 12
-
-/*
- * The following constants try to insure an input buffer is optimally aligned
- * for MAC hash computation. SHA1/MD5 code prefers 4 byte alignment of each
- * 64byte input block to avoid a copy. Our goal is to reach 4 byte alignment
- * starting form the 3rd MAC block (input buffer starts in the 3rd block). The
- * 3rd block includes the first 53 (MD5 SSL3 MAC) or 57 (SHA1 SSL3 MAC) bytes
- * of the input buffer. This means input buffer should start at offset 3
- * within a 4 byte word so that its next block is 4 byte aligned. Since the
- * SSL3 record header is 5 bytes long it should start at at offset 2 within a
- * 4 byte word. To insure the next record (for buffers that don't fit into 1
- * SSL3 record) also starts at offset 2 within a 4 byte word the previous
- * record length should be 3 mod 8 since 5 + 3 mod 8 is 0 i.e. the next record
- * starts at the same offset within a 4 byte word as the the previous record.
- */
-#define SSL3_MAX_OPTIMAL_RECORD_LENGTH (SSL3_MAX_RECORD_LENGTH - 1)
-#define SSL3_OPTIMAL_RECORD_ALIGNMENT 2
-
-/* session state */
-typedef struct sslSessionIDStr {
- uchar_t session_id[SSL3_SESSIONID_BYTES];
- uchar_t master_secret[SSL3_MASTER_SECRET_LEN];
- clock_t time;
- in6_addr_t client_addr;
- boolean_t cached;
- uint16_t cipher_suite;
-} sslSessionID;
-
-/* An element of the session cache */
-typedef struct kssl_sid_ent {
- kmutex_t se_lock;
- uint64_t se_used; /* Counter to check hash distribution */
- sslSessionID se_sid;
-} kssl_sid_ent_t;
-
-typedef enum {
- content_change_cipher_spec = 20,
- content_alert = 21,
- content_handshake = 22,
- content_application_data = 23,
- content_handshake_v2 = 128
-} SSL3ContentType;
-
-typedef enum {
- hello_request = 0,
- client_hello = 1,
- server_hello = 2,
- certificate = 11,
- server_key_exchange = 12,
- certificate_request = 13,
- server_hello_done = 14,
- certificate_verify = 15,
- client_key_exchange = 16,
- finished = 20
-} SSL3HandshakeType;
-
-typedef struct SSL3HandshakeMsgStr {
- int state;
- SSL3HandshakeType type;
- int msglen;
- int msglen_bytes;
- mblk_t *head;
- mblk_t *tail;
-} SSL3HandshakeMsg;
-
-typedef struct KSSLJOBStr {
- struct ssl_s *ssl;
- crypto_req_id_t kjob;
- char *buf;
- size_t buflen;
- int status;
-} KSSLJOB;
-
-
-typedef struct {
- uchar_t md5[MD5_HASH_LEN];
- uchar_t sha1[SHA1_HASH_LEN];
- uchar_t tlshash[TLS_FINISHED_SIZE];
-} SSL3Hashes;
-
-typedef enum {
- close_notify = 0,
- unexpected_message = 10,
- bad_record_mac = 20,
- decompression_failure = 30,
- handshake_failure = 40,
- no_certificate = 41,
- bad_certificate = 42,
- unsupported_certificate = 43,
- certificate_revoked = 44,
- certificate_expired = 45,
- certificate_unknown = 46,
- illegal_parameter = 47,
- unknown_ca = 48,
- access_denied = 49,
- decode_error = 50,
- decrypt_error = 51,
- export_restriction = 60,
- protocol_version = 70,
- insufficient_security = 71,
- internal_error = 80,
- user_canceled = 90,
- no_renegotiation = 100
-} SSL3AlertDescription;
-
-typedef enum {
- alert_warning = 1,
- alert_fatal = 2
-} SSL3AlertLevel;
-
-typedef enum {
- wait_client_hello = 0,
- wait_client_key = 1,
- wait_client_key_done = 2,
- wait_change_cipher = 3,
- wait_finished = 4,
- idle_handshake = 5
-} SSL3WaitState;
-
-typedef enum {
- sender_client = 0x434c4e54,
- sender_server = 0x53525652
-} SSL3Sender;
-
-typedef enum {
- mac_md5 = 0,
- mac_sha = 1
-} SSL3MACAlgorithm;
-
-/* The SSL bulk cipher definition */
-typedef enum {
- cipher_null = 0,
- cipher_rc4 = 1,
- cipher_des = 2,
- cipher_3des = 3,
- cipher_aes128 = 4,
- cipher_aes256 = 5,
-} SSL3BulkCipher;
-
-typedef enum { type_stream = 0, type_block = 1 } CipherType;
-
-typedef struct ssl3CipherSuiteDefStr {
- uint16_t suite;
- SSL3BulkCipher calg;
- SSL3MACAlgorithm malg;
- int keyblksz;
-} ssl3CipherSuiteDef;
-
-typedef void (*hashinit_func_t)(void *);
-typedef void (*hashupdate_func_t)(void *, uchar_t *, uint32_t);
-typedef void (*hashfinal_func_t)(uchar_t *, void *);
-
-typedef struct KSSLMACDefStr {
- int hashsz;
- int padsz;
- hashinit_func_t HashInit;
- hashupdate_func_t HashUpdate;
- hashfinal_func_t HashFinal;
-} KSSLMACDef;
-
-typedef struct KSSLCipherDefStr {
- CipherType type;
- int bsize;
- int keysz;
- crypto_mech_type_t mech_type;
-} KSSLCipherDef;
-
-typedef union KSSL_HASHCTXUnion {
- SHA1_CTX sha;
- MD5_CTX md5;
-} KSSL_HASHCTX;
-
-typedef struct KSSLCipherSpecStr {
- int mac_hashsz;
- int mac_padsz;
- void (*MAC_HashInit)(void *);
- void (*MAC_HashUpdate)(void *, uchar_t *, uint32_t);
- void (*MAC_HashFinal)(uchar_t *, void *);
-
- CipherType cipher_type;
- int cipher_bsize;
- int cipher_keysz;
-
- crypto_mechanism_t cipher_mech;
- crypto_mechanism_t hmac_mech; /* for TLS */
- crypto_key_t cipher_key;
- crypto_key_t hmac_key; /* for TLS */
-
- crypto_context_t cipher_ctx;
- crypto_data_t cipher_data;
-
-} KSSLCipherSpec;
-
-/*
- * SSL connection state. This one hangs off of a ksslf_t structure.
- */
-typedef struct ssl_s {
- kmutex_t kssl_lock;
- struct kssl_entry_s *kssl_entry;
- mblk_t *rec_ass_head;
- mblk_t *rec_ass_tail;
- in6_addr_t faddr;
- uint32_t tcp_mss;
- SSL3WaitState hs_waitstate;
- boolean_t resumed;
- boolean_t close_notify_clnt;
- boolean_t close_notify_srvr;
- boolean_t fatal_alert;
- boolean_t fatal_error;
- boolean_t alert_sent;
- boolean_t appdata_sent;
- boolean_t activeinput;
- SSL3AlertLevel sendalert_level;
- SSL3AlertDescription sendalert_desc;
- mblk_t *handshake_sendbuf;
- mblk_t *alert_sendbuf;
- kssl_callback_t cke_callback_func;
- void *cke_callback_arg;
- uint16_t pending_cipher_suite;
- SSL3MACAlgorithm pending_malg;
- SSL3BulkCipher pending_calg;
- int pending_keyblksz;
- uint64_t seq_num[2];
- SSL3HandshakeMsg msg;
- KSSLJOB job;
- KSSLCipherSpec spec[2];
- uchar_t pending_keyblock[MAX_KEYBLOCK_LENGTH];
- uchar_t mac_secret[2][MAX_HASH_LEN];
- KSSL_HASHCTX mac_ctx[2][2]; /* inner 'n outer per dir */
- sslSessionID sid;
- SHA1_CTX hs_sha1;
- MD5_CTX hs_md5;
- SSL3Hashes hs_hashes;
- uchar_t client_random[SSL3_RANDOM_LENGTH];
- uchar_t server_random[SSL3_RANDOM_LENGTH];
- int sslcnt;
- uchar_t major_version;
- uchar_t minor_version;
- boolean_t secure_renegotiation;
- uint_t async_ops_pending;
- kcondvar_t async_cv;
-} ssl_t;
-
-#define IS_TLS(s) (s->major_version == 3 && s->minor_version == 1)
-
-#define SSL3_REC_SIZE(mp) (uint8_t *)(mp)->b_rptr + 3
-
-extern int kssl_spec_init(ssl_t *, int);
-extern void kssl_send_alert(ssl_t *, SSL3AlertLevel, SSL3AlertDescription);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _INET_KSSL_KSSLPROTO_H */
diff --git a/usr/src/uts/common/inet/kssl/ksslrec.c b/usr/src/uts/common/inet/kssl/ksslrec.c
deleted file mode 100644
index e609893c73..0000000000
--- a/usr/src/uts/common/inet/kssl/ksslrec.c
+++ /dev/null
@@ -1,2531 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <sys/strsubr.h>
-#include <sys/stropts.h>
-#include <sys/strsun.h>
-#define _SUN_TPI_VERSION 2
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/debug.h>
-#include <sys/vtrace.h>
-#include <sys/kmem.h>
-#include <sys/cpuvar.h>
-#include <sys/atomic.h>
-#include <sys/sysmacros.h>
-
-#include <sys/errno.h>
-#include <sys/isa_defs.h>
-#include <sys/md5.h>
-#include <sys/sha1.h>
-#include <sys/random.h>
-#include <inet/common.h>
-#include <netinet/in.h>
-
-#include <sys/systm.h>
-#include <sys/param.h>
-
-#include "ksslimpl.h"
-#include "ksslapi.h"
-#include "ksslproto.h"
-
-static ssl3CipherSuiteDef cipher_suite_defs[] = {
- /* 2 X 16 byte keys + 2 x 20 byte MAC secrets, no IVs */
- {SSL_RSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, 72},
-
- /* 2 X 16 byte keys + 2 x 16 byte MAC secrets, no IVs */
- {SSL_RSA_WITH_RC4_128_MD5, cipher_rc4, mac_md5, 64},
-
- /* 2 X 8 byte keys + 2 x 20 byte MAC secrets, 2 x 8 byte IVs */
- {SSL_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, 72},
-
- /* 2 X 24 byte keys + 2 x 20 byte MAC secrets, 2 x 8 byte IVs */
- {SSL_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, 104},
-
- /* 2 X 16 byte keys + 2 x 20 byte MAC secrets, 2 x 16 byte IVs */
- {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes128, mac_sha, 104},
-
- /* 2 X 32 byte keys + 2 x 20 byte MAC secrets, 2 x 16 byte IVs */
- {TLS_RSA_WITH_AES_256_CBC_SHA, cipher_aes256, mac_sha, 136},
-
- {SSL_RSA_WITH_NULL_SHA, cipher_null, mac_sha, 40}
-};
-
-static int cipher_suite_defs_nentries =
- sizeof (cipher_suite_defs) / sizeof (cipher_suite_defs[0]);
-
-static void KSSL_SHA1Update(void *, uchar_t *, uint32_t);
-
-static KSSLMACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
- /* macsz padsz HashInit HashUpdate HashFinal */
-
- {
- .hashsz = MD5_HASH_LEN,
- .padsz = SSL3_MD5_PAD_LEN,
- .HashInit = (hashinit_func_t)MD5Init,
- .HashUpdate = (hashupdate_func_t)MD5Update,
- .HashFinal = (hashfinal_func_t)MD5Final
- },
- {
- .hashsz = SHA1_HASH_LEN,
- .padsz = SSL3_SHA1_PAD_LEN,
- .HashInit = (hashinit_func_t)SHA1Init,
- .HashUpdate = KSSL_SHA1Update,
- .HashFinal = (hashfinal_func_t)SHA1Final
- }
-};
-
-static uchar_t kssl_pad_1[60] = {
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
- 0x36, 0x36, 0x36, 0x36
-};
-static uchar_t kssl_pad_2[60] = {
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
- 0x5c, 0x5c, 0x5c, 0x5c
-};
-
-static boolean_t kssl_synchronous = B_FALSE;
-
-static void kssl_update_handshake_hashes(ssl_t *, uchar_t *, uint_t);
-static int kssl_compute_handshake_hashes(ssl_t *, SSL3Hashes *, uint32_t);
-static int kssl_handle_client_hello(ssl_t *, mblk_t *, int);
-static int kssl_handle_client_key_exchange(ssl_t *, mblk_t *, int,
- kssl_callback_t, void *);
-static int kssl_send_server_hello(ssl_t *);
-static int kssl_send_certificate_and_server_hello_done(ssl_t *);
-static int kssl_send_change_cipher_specs(ssl_t *);
-static int kssl_send_finished(ssl_t *, int);
-static int kssl_handle_finished(ssl_t *, mblk_t *, int);
-static void kssl_get_hello_random(uchar_t *);
-static uchar_t *kssl_rsa_unwrap(uchar_t *, size_t *);
-static void kssl_cache_sid(sslSessionID *, kssl_entry_t *);
-static void kssl_lookup_sid(sslSessionID *, uchar_t *, in6_addr_t *,
- kssl_entry_t *);
-static int kssl_generate_tls_ms(ssl_t *, uchar_t *, size_t);
-static void kssl_generate_ssl_ms(ssl_t *, uchar_t *, size_t);
-static int kssl_generate_tls_keyblock(ssl_t *);
-static void kssl_generate_keyblock(ssl_t *);
-static void kssl_ssl3_key_material_derive_step(ssl_t *, uchar_t *, size_t,
- int, uchar_t *, int);
-static int kssl_tls_PRF(ssl_t *, uchar_t *, size_t,
- uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
-static int kssl_tls_P_hash(crypto_mechanism_t *, crypto_key_t *,
- size_t, uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
-static void kssl_cke_done(void *, int);
-
-#define HMAC_INIT(m, k, c) \
- rv = crypto_mac_init(m, k, NULL, c, NULL); if (CRYPTO_ERR(rv)) goto end;
-
-#define HMAC_UPDATE(c, d, l) \
- dd.cd_raw.iov_base = (char *)d; \
- dd.cd_length = dd.cd_raw.iov_len = l; \
- rv = crypto_mac_update(c, &dd, NULL); if (CRYPTO_ERR(rv)) goto end;
-
-#define HMAC_FINAL(c, d, l) \
- mac.cd_raw.iov_base = (char *)d; \
- mac.cd_length = mac.cd_raw.iov_len = l; \
- rv = crypto_mac_final(c, &mac, NULL); if (CRYPTO_ERR(rv)) goto end;
-
-/*
- * Wrapper for SHA1Update to translate arguments. We need this because
- * the KSSL hash update function expects the size argument to be a
- * uint32_t, but SHA1Update uses a size_t.
- */
-static void
-KSSL_SHA1Update(void *ctx, uchar_t *in, uint32_t size)
-{
- SHA1Update(ctx, in, size);
-}
-
-/*
- * This hack can go away once we have SSL3 MAC support by KCF
- * software providers (See 4873559).
- */
-extern int kcf_md5_threshold;
-
-int
-kssl_compute_record_mac(
- ssl_t *ssl,
- int direction,
- uint64_t seq_num,
- SSL3ContentType ct,
- uchar_t *versionp,
- uchar_t *buf,
- int len,
- uchar_t *digest)
-{
- KSSL_HASHCTX mac_ctx;
- KSSL_HASHCTX *ctx = &mac_ctx;
- uchar_t temp[16], *p;
- KSSLCipherSpec *spec;
- boolean_t hash_use_ok = B_FALSE;
- int rv = 0;
-
- spec = &ssl->spec[direction];
-
- if (spec->mac_hashsz == 0) {
- return (1);
- }
-
- p = temp;
-
- *p++ = (seq_num >> 56) & 0xff;
- *p++ = (seq_num >> 48) & 0xff;
- *p++ = (seq_num >> 40) & 0xff;
- *p++ = (seq_num >> 32) & 0xff;
- *p++ = (seq_num >> 24) & 0xff;
- *p++ = (seq_num >> 16) & 0xff;
- *p++ = (seq_num >> 8) & 0xff;
- *p++ = (seq_num) & 0xff;
- *p++ = (uchar_t)ct;
- if (IS_TLS(ssl)) {
- *p++ = versionp[0];
- *p++ = versionp[1];
- }
- *p++ = (len >> 8) & 0xff;
- *p++ = (len) & 0xff;
-
- if (IS_TLS(ssl) || (spec->hmac_mech.cm_type != CRYPTO_MECH_INVALID &&
- len >= kcf_md5_threshold)) {
- crypto_data_t dd, mac;
- struct uio uio_pt;
- struct iovec iovarray_pt[2];
-
- /* init the array of iovecs for use in the uio struct */
- iovarray_pt[0].iov_base = (char *)temp;
- iovarray_pt[0].iov_len = (p - temp);
- iovarray_pt[1].iov_base = (char *)buf;
- iovarray_pt[1].iov_len = len;
-
- /* init the uio struct for use in the crypto_data_t struct */
- bzero(&uio_pt, sizeof (uio_pt));
- uio_pt.uio_iov = iovarray_pt;
- uio_pt.uio_iovcnt = 2;
- uio_pt.uio_segflg = UIO_SYSSPACE;
-
- dd.cd_format = CRYPTO_DATA_UIO;
- dd.cd_offset = 0;
- dd.cd_length = (p - temp) + len;
- dd.cd_miscdata = NULL;
- dd.cd_uio = &uio_pt;
-
- mac.cd_format = CRYPTO_DATA_RAW;
- mac.cd_offset = 0;
- mac.cd_raw.iov_base = (char *)digest;
- mac.cd_length = mac.cd_raw.iov_len = spec->mac_hashsz;
-
- /*
- * The calling context can tolerate a blocking call here.
- * For outgoing traffic, we are in user context when called
- * from kssl_data_out_cb(). For incoming traffic past the
- * SSL handshake, we are in user context when called from
- * kssl_data_in_proc_cb(). During the SSL handshake, we are
- * called for client_finished message handling from a taskq
- * thread.
- */
- rv = crypto_mac(&spec->hmac_mech, &dd, &spec->hmac_key,
- NULL, &mac, NULL);
-
- if (CRYPTO_ERR(rv)) {
- hash_use_ok = (rv == CRYPTO_MECH_NOT_SUPPORTED &&
- !IS_TLS(ssl));
- if (!hash_use_ok) {
- DTRACE_PROBE1(kssl_err__crypto_mac_error,
- int, rv);
- KSSL_COUNTER(compute_mac_failure, 1);
- }
- }
- } else
- hash_use_ok = B_TRUE;
-
- if (hash_use_ok) {
- bcopy(&(ssl->mac_ctx[direction][0]), ctx,
- sizeof (KSSL_HASHCTX));
- spec->MAC_HashUpdate((void *)ctx, temp, p - temp);
- spec->MAC_HashUpdate((void *)ctx, buf, len);
- spec->MAC_HashFinal(digest, (void *)ctx);
-
- bcopy(&(ssl->mac_ctx[direction][1]), ctx,
- sizeof (KSSL_HASHCTX));
- spec->MAC_HashUpdate((void *)ctx, digest, spec->mac_hashsz);
- spec->MAC_HashFinal(digest, (void *)ctx);
- }
-
- return (rv);
-}
-
-/*
- * Handles handshake messages.
- * Messages to be replied are returned in handshake_sendbuf.
- */
-int
-kssl_handle_handshake_message(ssl_t *ssl, mblk_t *mp, int *err,
- kssl_callback_t cbfn, void *arg)
-{
- uint32_t msglen;
- uchar_t msghdr[4];
-
- ASSERT(ssl->msg.state == MSG_BODY);
- ASSERT(ssl->msg.msglen_bytes == 3);
- ASSERT(mp->b_wptr >= mp->b_rptr + ssl->msg.msglen);
-
- ssl->sslcnt++;
- msglen = ssl->msg.msglen;
-
- if (ssl->msg.type == client_hello) {
- MD5Init(&ssl->hs_md5);
- SHA1Init(&ssl->hs_sha1);
- }
-
- if (ssl->msg.type == finished && ssl->resumed == B_FALSE) {
- if (kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
- sender_client) != 0) {
- *err = SSL_MISS;
- return (0);
- }
- }
-
- if (ssl->msg.type != finished || ssl->resumed == B_FALSE) {
- msghdr[0] = (uchar_t)ssl->msg.type;
-
- msghdr[1] = (uchar_t)(msglen >> 16);
- msghdr[2] = (uchar_t)(msglen >> 8);
- msghdr[3] = (uchar_t)(msglen);
- kssl_update_handshake_hashes(ssl, msghdr, 4);
- kssl_update_handshake_hashes(ssl, mp->b_rptr, msglen);
- }
-
- ssl->msg.state = MSG_INIT;
- ssl->msg.msglen = 0;
- ssl->msg.msglen_bytes = 0;
-
- switch (ssl->msg.type) {
- case client_hello:
- if (ssl->hs_waitstate != wait_client_hello) {
- kssl_send_alert(ssl, alert_fatal,
- unexpected_message);
- *err = EBADMSG;
- ssl->activeinput = B_FALSE;
- return (1);
- }
- *err = kssl_handle_client_hello(ssl, mp, msglen);
- if (*err == SSL_MISS) {
- ssl->activeinput = B_FALSE;
- return (0);
- }
- return (1);
- case client_key_exchange:
- if (ssl->hs_waitstate != wait_client_key) {
- kssl_send_alert(ssl, alert_fatal,
- unexpected_message);
- *err = EBADMSG;
- ssl->activeinput = B_FALSE;
- return (1);
- }
- *err = kssl_handle_client_key_exchange(ssl, mp,
- msglen, cbfn, arg);
- return (1);
- case finished:
- if (ssl->hs_waitstate != wait_finished) {
- kssl_send_alert(ssl, alert_fatal,
- unexpected_message);
- *err = EBADMSG;
- ssl->activeinput = B_FALSE;
- return (1);
- }
- *err = kssl_handle_finished(ssl, mp, msglen);
- return (1);
- default:
- kssl_send_alert(ssl, alert_fatal, unexpected_message);
- ssl->activeinput = B_FALSE;
- *err = EBADMSG;
- return (1);
- }
-}
-
-static void
-kssl_update_handshake_hashes(ssl_t *ssl, uchar_t *buf, uint_t len)
-{
- MD5Update(&ssl->hs_md5, buf, len);
- SHA1Update(&ssl->hs_sha1, buf, len);
-}
-
-static int
-kssl_compute_handshake_hashes(
- ssl_t *ssl,
- SSL3Hashes *hashes,
- uint32_t sender)
-{
- MD5_CTX md5 = ssl->hs_md5; /* clone md5 context */
- SHA1_CTX sha1 = ssl->hs_sha1; /* clone sha1 context */
- MD5_CTX *md5ctx = &md5;
- SHA1_CTX *sha1ctx = &sha1;
-
- if (IS_TLS(ssl)) {
- uchar_t seed[MD5_HASH_LEN + SHA1_HASH_LEN];
- char *label;
-
- /*
- * Do not take another hash step here.
- * Just complete the operation.
- */
- MD5Final(hashes->md5, md5ctx);
- SHA1Final(hashes->sha1, sha1ctx);
-
- bcopy(hashes->md5, seed, MD5_HASH_LEN);
- bcopy(hashes->sha1, seed + MD5_HASH_LEN, SHA1_HASH_LEN);
-
- if (sender == sender_client)
- label = TLS_CLIENT_FINISHED_LABEL;
- else
- label = TLS_SERVER_FINISHED_LABEL;
-
- return (kssl_tls_PRF(ssl,
- ssl->sid.master_secret,
- (size_t)SSL3_MASTER_SECRET_LEN,
- (uchar_t *)label, strlen(label),
- seed, (size_t)(MD5_HASH_LEN + SHA1_HASH_LEN),
- hashes->tlshash, (size_t)TLS_FINISHED_SIZE));
- } else {
- uchar_t s[4];
- s[0] = (sender >> 24) & 0xff;
- s[1] = (sender >> 16) & 0xff;
- s[2] = (sender >> 8) & 0xff;
- s[3] = (sender) & 0xff;
-
- MD5Update(md5ctx, s, 4);
- MD5Update(md5ctx, ssl->sid.master_secret,
- SSL3_MASTER_SECRET_LEN);
- MD5Update(md5ctx, kssl_pad_1, SSL3_MD5_PAD_LEN);
- MD5Final(hashes->md5, md5ctx);
-
- MD5Init(md5ctx);
- MD5Update(md5ctx, ssl->sid.master_secret,
- SSL3_MASTER_SECRET_LEN);
- MD5Update(md5ctx, kssl_pad_2, SSL3_MD5_PAD_LEN);
- MD5Update(md5ctx, hashes->md5, MD5_HASH_LEN);
- MD5Final(hashes->md5, md5ctx);
-
- SHA1Update(sha1ctx, s, 4);
- SHA1Update(sha1ctx, ssl->sid.master_secret,
- SSL3_MASTER_SECRET_LEN);
- SHA1Update(sha1ctx, kssl_pad_1, SSL3_SHA1_PAD_LEN);
- SHA1Final(hashes->sha1, sha1ctx);
-
- SHA1Init(sha1ctx);
- SHA1Update(sha1ctx, ssl->sid.master_secret,
- SSL3_MASTER_SECRET_LEN);
- SHA1Update(sha1ctx, kssl_pad_2, SSL3_SHA1_PAD_LEN);
- SHA1Update(sha1ctx, hashes->sha1, SHA1_HASH_LEN);
- SHA1Final(hashes->sha1, sha1ctx);
- return (0);
- }
-}
-
-
-/*
- * Minimum message length for a client hello =
- * 2-byte client_version +
- * 32-byte random +
- * 1-byte session_id length +
- * 2-byte cipher_suites length +
- * 1-byte compression_methods length +
- * 1-byte CompressionMethod.null
- */
-#define KSSL_SSL3_CH_MIN_MSGLEN (39)
-
-/*
- * Process SSL/TLS Client Hello message. Return 0 on success, errno value
- * or SSL_MISS if no cipher suite of the server matches the list received
- * in the message.
- */
-static int
-kssl_handle_client_hello(ssl_t *ssl, mblk_t *mp, int msglen)
-{
- uchar_t *msgend;
- int err;
- SSL3AlertDescription desc = illegal_parameter;
- uint_t sidlen, cslen, cmlen;
- uchar_t *suitesp;
- uint_t i, j;
- uint16_t suite, selected_suite;
- int ch_msglen = KSSL_SSL3_CH_MIN_MSGLEN;
- boolean_t suite_found = B_FALSE;
-
- ASSERT(mp->b_wptr >= mp->b_rptr + msglen);
- ASSERT(ssl->msg.type == client_hello);
- ASSERT(ssl->hs_waitstate == wait_client_hello);
- ASSERT(ssl->resumed == B_FALSE);
-
- if (msglen < ch_msglen) {
- DTRACE_PROBE2(kssl_err__msglen_less_than_minimum,
- int, msglen, int, ch_msglen);
- goto falert;
- }
-
- msgend = mp->b_rptr + msglen;
-
- /* Support SSLv3 (version == 3.0) or TLS (version == 3.1) */
- if (ssl->major_version != 3 || (ssl->major_version == 3 &&
- ssl->minor_version != 0 && ssl->minor_version != 1)) {
- DTRACE_PROBE2(kssl_err__SSL_version_not_supported,
- uchar_t, ssl->major_version,
- uchar_t, ssl->minor_version);
- desc = handshake_failure;
- goto falert;
- }
- mp->b_rptr += 2; /* skip the version bytes */
-
- /* read client random field */
- bcopy(mp->b_rptr, ssl->client_random, SSL3_RANDOM_LENGTH);
- mp->b_rptr += SSL3_RANDOM_LENGTH;
-
- /* read session ID length */
- ASSERT(ssl->sid.cached == B_FALSE);
- sidlen = *mp->b_rptr++;
- ch_msglen += sidlen;
- if (msglen < ch_msglen) {
- DTRACE_PROBE2(kssl_err__invalid_message_length_after_ver,
- int, msglen, int, ch_msglen);
- goto falert;
- }
- if (sidlen != SSL3_SESSIONID_BYTES) {
- mp->b_rptr += sidlen;
- } else {
- kssl_lookup_sid(&ssl->sid, mp->b_rptr, &ssl->faddr,
- ssl->kssl_entry);
- mp->b_rptr += SSL3_SESSIONID_BYTES;
- }
-
- /* read cipher suite length */
- cslen = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
- mp->b_rptr += 2;
- ch_msglen += cslen;
-
- /*
- * This check can't be a "!=" since there can be
- * compression methods other than CompressionMethod.null.
- * Also, there can be extra data (TLS extensions) after the
- * compression methods field.
- */
- if (msglen < ch_msglen) {
- DTRACE_PROBE2(kssl_err__invalid_message_length_after_cslen,
- int, msglen, int, ch_msglen);
- goto falert;
- }
-
- /* The length has to be even since a cipher suite is 2-byte long. */
- if (cslen & 0x1) {
- DTRACE_PROBE1(kssl_err__uneven_cipher_suite_length,
- uint_t, cslen);
- goto falert;
- }
- suitesp = mp->b_rptr;
-
- /* session resumption checks */
- if (ssl->sid.cached == B_TRUE) {
- suite = ssl->sid.cipher_suite;
- for (j = 0; j < cslen; j += 2) {
- DTRACE_PROBE2(kssl_cipher_suite_check_resumpt,
- uint16_t, suite,
- uint16_t,
- (uint16_t)((suitesp[j] << 8) + suitesp[j+1]));
- /* Check for regular (true) cipher suite. */
- if (suitesp[j] == ((suite >> 8) & 0xff) &&
- suitesp[j + 1] == (suite & 0xff)) {
- DTRACE_PROBE1(kssl_cipher_suite_found_resumpt,
- uint16_t, suite);
- suite_found = B_TRUE;
- selected_suite = suite;
- }
-
- /* Check for SCSV. */
- if (suitesp[j] == ((SSL_SCSV >> 8) & 0xff) &&
- suitesp[j + 1] == (SSL_SCSV & 0xff)) {
- DTRACE_PROBE(kssl_scsv_found_resumpt);
- ssl->secure_renegotiation = B_TRUE;
- }
-
- /*
- * If we got cipher suite match and SCSV we can
- * terminate the cycle now.
- */
- if (suite_found && ssl->secure_renegotiation)
- break;
- }
- if (suite_found)
- goto suite_found;
- kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
- }
-
- /* Check if this server is capable of the cipher suite. */
- for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
- suite = ssl->kssl_entry->kssl_cipherSuites[i];
- for (j = 0; j < cslen; j += 2) {
- DTRACE_PROBE2(kssl_cipher_suite_check, uint16_t, suite,
- uint16_t,
- (uint16_t)((suitesp[j] << 8) + suitesp[j+1]));
- /* Check for regular (true) cipher suite. */
- if (suitesp[j] == ((suite >> 8) & 0xff) &&
- suitesp[j + 1] == (suite & 0xff)) {
- DTRACE_PROBE1(kssl_cipher_suite_found,
- uint16_t, suite);
- suite_found = B_TRUE;
- selected_suite = suite;
- }
-
- /* Check for SCSV. */
- if (suitesp[j] == ((SSL_SCSV >> 8) & 0xff) &&
- suitesp[j + 1] == (SSL_SCSV & 0xff)) {
- DTRACE_PROBE(kssl_scsv_found);
- ssl->secure_renegotiation = B_TRUE;
- }
-
- /*
- * If we got cipher suite match and SCSV or went
- * through the whole list of client cipher suites
- * (hence we know if SCSV was present or not) we
- * can terminate the cycle now.
- */
- if (suite_found &&
- (ssl->secure_renegotiation || (i > 0)))
- break;
- }
- if (suite_found)
- break;
- }
- if (!suite_found) {
- if (ssl->sslcnt == 1) {
- DTRACE_PROBE(kssl_no_cipher_suite_found);
- KSSL_COUNTER(no_suite_found, 1);
- /*
- * If there is no fallback point terminate the
- * handshake with SSL alert otherwise return with
- * SSL_MISS.
- */
- if (ssl->kssl_entry->ke_fallback_head == NULL) {
- DTRACE_PROBE(kssl_no_fallback);
- desc = handshake_failure;
- goto falert;
- } else {
- return (SSL_MISS);
- }
- }
- desc = handshake_failure;
- DTRACE_PROBE(kssl_err__no_cipher_suites_found);
- goto falert;
- }
-
-suite_found:
- mp->b_rptr += cslen;
-
- /*
- * Check for the mandatory CompressionMethod.null. We do not
- * support any other compression methods.
- */
- cmlen = *mp->b_rptr++;
- ch_msglen += cmlen - 1; /* -1 accounts for the null method */
- if (msglen < ch_msglen) {
- DTRACE_PROBE2(kssl_err__invalid_message_length_after_complen,
- int, msglen, int, ch_msglen);
- goto falert;
- }
-
- /*
- * Search for null compression method (encoded as 0 byte) in the
- * compression methods field.
- */
- while (cmlen >= 1) {
- if (*mp->b_rptr++ == 0)
- break;
- cmlen--;
- }
-
- if (cmlen == 0) {
- desc = handshake_failure;
- DTRACE_PROBE(kssl_err__no_null_compression_method);
- goto falert;
- }
-
- /* Find the suite in the internal cipher suite table. */
- for (i = 0; i < cipher_suite_defs_nentries; i++) {
- if (selected_suite == cipher_suite_defs[i].suite) {
- break;
- }
- }
-
- /* Get past the remaining compression methods (minus null method). */
- mp->b_rptr += cmlen - 1;
-
- ASSERT(i < cipher_suite_defs_nentries);
-
- ssl->pending_cipher_suite = selected_suite;
- ssl->pending_malg = cipher_suite_defs[i].malg;
- ssl->pending_calg = cipher_suite_defs[i].calg;
- ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
-
- /* Parse TLS extensions (if any). */
- if (ch_msglen + 2 < msglen) {
- /* Get the length of the extensions. */
- uint16_t ext_total_len = ((uint_t)mp->b_rptr[0] << 8) +
- (uint_t)mp->b_rptr[1];
- DTRACE_PROBE1(kssl_total_length_extensions, uint16_t,
- ext_total_len);
- /*
- * Consider zero extensions length as invalid extension
- * encoding.
- */
- if (ext_total_len == 0) {
- DTRACE_PROBE1(kssl_err__zero_extensions_length,
- mblk_t *, mp);
- goto falert;
- }
- ch_msglen += 2;
- if (ch_msglen + ext_total_len > msglen) {
- DTRACE_PROBE2(kssl_err__invalid_extensions_length,
- int, msglen, int, ch_msglen);
- goto falert;
- }
- mp->b_rptr += 2;
-
- /*
- * Go through the TLS extensions. This is only done to check
- * for the presence of renegotiation_info extension. We do not
- * support any other TLS extensions and hence ignore them.
- */
- while (mp->b_rptr < msgend) {
- uint16_t ext_len, ext_type;
-
- /*
- * Check that the extension has at least type and
- * length (2 + 2 bytes).
- */
- if (ch_msglen + 4 > msglen) {
- DTRACE_PROBE(kssl_err__invalid_ext_format);
- goto falert;
- }
-
- /* Get extension type and length */
- ext_type = ((uint_t)mp->b_rptr[0] << 8) +
- (uint_t)mp->b_rptr[1];
- mp->b_rptr += 2;
- ext_len = ((uint_t)mp->b_rptr[0] << 8) +
- (uint_t)mp->b_rptr[1];
- mp->b_rptr += 2;
- ch_msglen += 4;
- DTRACE_PROBE3(kssl_ext_detected, uint16_t, ext_type,
- uint16_t, ext_len, mblk_t *, mp);
-
- /*
- * Make sure the contents of the extension are
- * accessible.
- */
- if (ch_msglen + ext_len > msglen) {
- DTRACE_PROBE1(
- kssl_err__invalid_ext_len,
- uint16_t, ext_len);
- goto falert;
- }
-
- switch (ext_type) {
- case TLSEXT_RENEGOTIATION_INFO:
- /*
- * Search for empty "renegotiation_info"
- * extension (encoded as ff 01 00 01 00).
- */
- DTRACE_PROBE(kssl_reneg_info_found);
- if ((ext_len != 1) ||
- (*mp->b_rptr != 0)) {
- DTRACE_PROBE2(
- kssl_err__non_empty_reneg_info,
- uint16_t, ext_len,
- mblk_t *, mp);
- goto falert;
- }
- ssl->secure_renegotiation = B_TRUE;
- break;
- default:
- /* FALLTHRU */
- break;
- }
-
- /* jump to the next extension */
- ch_msglen += ext_len;
- mp->b_rptr += ext_len;
- }
- }
-
- mp->b_rptr = msgend;
-
- if (ssl->sid.cached == B_TRUE) {
- err = kssl_send_server_hello(ssl);
- if (err != 0) {
- return (err);
- }
- if (IS_TLS(ssl))
- err = kssl_generate_tls_keyblock(ssl);
- else
- kssl_generate_keyblock(ssl);
-
- err = kssl_send_change_cipher_specs(ssl);
- if (err != 0) {
- return (err);
- }
-
- err = kssl_send_finished(ssl, 1);
- if (err != 0)
- return (err);
-
- err = kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
- sender_client);
- if (err != 0)
- return (err);
-
- ssl->hs_waitstate = wait_change_cipher;
- ssl->resumed = B_TRUE;
- ssl->activeinput = B_FALSE;
- KSSL_COUNTER(resumed_sessions, 1);
- return (0);
- }
-
- (void) random_get_pseudo_bytes(ssl->sid.session_id,
- SSL3_SESSIONID_BYTES);
- ssl->sid.client_addr = ssl->faddr;
- ssl->sid.cipher_suite = selected_suite;
-
- err = kssl_send_server_hello(ssl);
- if (err != 0) {
- return (err);
- }
- err = kssl_send_certificate_and_server_hello_done(ssl);
- if (err != 0) {
- return (err);
- }
- KSSL_COUNTER(full_handshakes, 1);
- ssl->hs_waitstate = wait_client_key;
- ssl->activeinput = B_FALSE;
- return (0);
-
-falert:
- kssl_send_alert(ssl, alert_fatal, desc);
- return (EBADMSG);
-}
-
-#define SET_HASH_INDEX(index, s, clnt_addr) { \
- int addr; \
- \
- IN6_V4MAPPED_TO_IPADDR(clnt_addr, addr); \
- index = addr ^ (((int)(s)[0] << 24) | ((int)(s)[1] << 16) | \
- ((int)(s)[2] << 8) | (int)(s)[SSL3_SESSIONID_BYTES - 1]); \
-}
-
-/*
- * Creates a cache entry. Sets the sid->cached flag
- * and sid->time fields. So, the caller should not set them.
- */
-static void
-kssl_cache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
-{
- uint_t index;
- uchar_t *s = sid->session_id;
- kmutex_t *lock;
-
- ASSERT(sid->cached == B_FALSE);
-
- /* set the values before creating the cache entry */
- sid->cached = B_TRUE;
- sid->time = ddi_get_lbolt();
-
- SET_HASH_INDEX(index, s, &sid->client_addr);
- index %= kssl_entry->sid_cache_nentries;
-
- lock = &(kssl_entry->sid_cache[index].se_lock);
- mutex_enter(lock);
- kssl_entry->sid_cache[index].se_used++;
- bcopy(sid, &(kssl_entry->sid_cache[index].se_sid), sizeof (*sid));
- mutex_exit(lock);
-
- KSSL_COUNTER(sid_cached, 1);
-}
-
-/*
- * Invalidates the cache entry, if any. Clears the sid->cached flag
- * as a side effect.
- */
-void
-kssl_uncache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
-{
- uint_t index;
- uchar_t *s = sid->session_id;
- sslSessionID *csid;
- kmutex_t *lock;
-
- ASSERT(sid->cached == B_TRUE);
- sid->cached = B_FALSE;
-
- SET_HASH_INDEX(index, s, &sid->client_addr);
- index %= kssl_entry->sid_cache_nentries;
-
- lock = &(kssl_entry->sid_cache[index].se_lock);
- mutex_enter(lock);
- csid = &(kssl_entry->sid_cache[index].se_sid);
- if (!(IN6_ARE_ADDR_EQUAL(&csid->client_addr, &sid->client_addr)) ||
- bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
- mutex_exit(lock);
- return;
- }
- csid->cached = B_FALSE;
- mutex_exit(lock);
-
- KSSL_COUNTER(sid_uncached, 1);
-}
-
-static void
-kssl_lookup_sid(sslSessionID *sid, uchar_t *s, in6_addr_t *faddr,
- kssl_entry_t *kssl_entry)
-{
- uint_t index;
- kmutex_t *lock;
- sslSessionID *csid;
-
- KSSL_COUNTER(sid_cache_lookups, 1);
-
- SET_HASH_INDEX(index, s, faddr);
- index %= kssl_entry->sid_cache_nentries;
-
- lock = &(kssl_entry->sid_cache[index].se_lock);
- mutex_enter(lock);
- csid = &(kssl_entry->sid_cache[index].se_sid);
- if (csid->cached == B_FALSE ||
- !IN6_ARE_ADDR_EQUAL(&csid->client_addr, faddr) ||
- bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
- mutex_exit(lock);
- return;
- }
-
- if (TICK_TO_SEC(ddi_get_lbolt() - csid->time) >
- kssl_entry->sid_cache_timeout) {
- csid->cached = B_FALSE;
- mutex_exit(lock);
- return;
- }
-
- bcopy(csid, sid, sizeof (*sid));
- mutex_exit(lock);
- ASSERT(sid->cached == B_TRUE);
-
- KSSL_COUNTER(sid_cache_hits, 1);
-}
-
-static uchar_t *
-kssl_rsa_unwrap(uchar_t *buf, size_t *lenp)
-{
- size_t len = *lenp;
- int i = 2;
-
- if (buf[0] != 0 || buf[1] != 2) {
- return (NULL);
- }
-
- while (i < len) {
- if (buf[i++] == 0) {
- *lenp = len - i;
- break;
- }
- }
-
- if (i == len) {
- return (NULL);
- }
-
- return (buf + i);
-}
-
-
-#define KSSL_SSL3_SH_RECLEN (74)
-#define KSSL_SSL3_FIN_MSGLEN (36)
-#define KSSL_EMPTY_RENEG_INFO_LEN (7)
-
-#define KSSL_SSL3_MAX_CCP_FIN_MSGLEN (128) /* comfortable upper bound */
-
-/*
- * Send ServerHello record to the client.
- */
-static int
-kssl_send_server_hello(ssl_t *ssl)
-{
- mblk_t *mp;
- uchar_t *buf;
- uchar_t *msgstart;
- uint16_t reclen = KSSL_SSL3_SH_RECLEN;
-
- mp = allocb(ssl->tcp_mss, BPRI_HI);
- if (mp == NULL) {
- KSSL_COUNTER(alloc_fails, 1);
- return (ENOMEM);
- }
- ssl->handshake_sendbuf = mp;
- buf = mp->b_wptr;
-
- if (ssl->secure_renegotiation)
- reclen += KSSL_EMPTY_RENEG_INFO_LEN;
-
- /* 5 byte record header */
- buf[0] = content_handshake;
- buf[1] = ssl->major_version;
- buf[2] = ssl->minor_version;
- buf[3] = reclen >> 8;
- buf[4] = reclen & 0xff;
- buf += SSL3_HDR_LEN;
-
- msgstart = buf;
-
- /* 6 byte message header */
- buf[0] = (uchar_t)server_hello; /* message type */
- buf[1] = 0; /* message len byte 0 */
- buf[2] = ((reclen - 4) >> 8) &
- 0xff; /* message len byte 1 */
- buf[3] = (reclen - 4) & 0xff; /* message len byte 2 */
-
- buf[4] = ssl->major_version; /* version byte 0 */
- buf[5] = ssl->minor_version; /* version byte 1 */
-
- buf += 6;
-
- kssl_get_hello_random(ssl->server_random);
- bcopy(ssl->server_random, buf, SSL3_RANDOM_LENGTH);
- buf += SSL3_RANDOM_LENGTH;
-
- buf[0] = SSL3_SESSIONID_BYTES;
- bcopy(ssl->sid.session_id, buf + 1, SSL3_SESSIONID_BYTES);
- buf += SSL3_SESSIONID_BYTES + 1;
-
- buf[0] = (ssl->pending_cipher_suite >> 8) & 0xff;
- buf[1] = ssl->pending_cipher_suite & 0xff;
-
- buf[2] = 0; /* No compression */
- buf += 3;
-
- /*
- * Add "renegotiation_info" extension if the ClientHello message
- * contained either SCSV value in cipher suite list or
- * "renegotiation_info" extension. This is per RFC 5746, section 3.6.
- */
- if (ssl->secure_renegotiation) {
- /* Extensions length */
- buf[0] = 0x00;
- buf[1] = 0x05;
- /* empty renegotiation_info extension encoding (section 3.2) */
- buf[2] = 0xff;
- buf[3] = 0x01;
- buf[4] = 0x00;
- buf[5] = 0x01;
- buf[6] = 0x00;
- buf += KSSL_EMPTY_RENEG_INFO_LEN;
- }
-
- mp->b_wptr = buf;
- ASSERT(mp->b_wptr < mp->b_datap->db_lim);
-
- kssl_update_handshake_hashes(ssl, msgstart, reclen);
- return (0);
-}
-
-static void
-kssl_get_hello_random(uchar_t *buf)
-{
- timestruc_t ts;
- time_t sec;
-
- gethrestime(&ts);
- sec = ts.tv_sec;
-
- buf[0] = (sec >> 24) & 0xff;
- buf[1] = (sec >> 16) & 0xff;
- buf[2] = (sec >> 8) & 0xff;
- buf[3] = (sec) & 0xff;
-
- (void) random_get_pseudo_bytes(&buf[4], SSL3_RANDOM_LENGTH - 4);
-
- /* Should this be caching? */
-}
-
-static int
-kssl_tls_P_hash(crypto_mechanism_t *mech, crypto_key_t *key, size_t hashlen,
- uchar_t *label, size_t label_len, uchar_t *seed, size_t seedlen,
- uchar_t *data, size_t datalen)
-{
- int rv = 0;
- uchar_t A1[MAX_HASH_LEN], result[MAX_HASH_LEN];
- int bytes_left = (int)datalen;
- crypto_data_t dd, mac;
- crypto_context_t ctx;
-
- dd.cd_format = CRYPTO_DATA_RAW;
- dd.cd_offset = 0;
- mac.cd_format = CRYPTO_DATA_RAW;
- mac.cd_offset = 0;
-
- /*
- * A(i) = HMAC_hash(secret, seed + A(i-1));
- * A(0) = seed;
- *
- * Compute A(1):
- * A(1) = HMAC_hash(secret, label + seed)
- *
- */
- HMAC_INIT(mech, key, &ctx);
- HMAC_UPDATE(ctx, label, label_len);
- HMAC_UPDATE(ctx, seed, seedlen);
- HMAC_FINAL(ctx, A1, hashlen);
-
- /* Compute A(2) ... A(n) */
- while (bytes_left > 0) {
- HMAC_INIT(mech, key, &ctx);
- HMAC_UPDATE(ctx, A1, hashlen);
- HMAC_UPDATE(ctx, label, label_len);
- HMAC_UPDATE(ctx, seed, seedlen);
- HMAC_FINAL(ctx, result, hashlen);
-
- /*
- * The A(i) value is stored in "result".
- * Save the results of the MAC so it can be input to next
- * iteration.
- */
- if (bytes_left > hashlen) {
- /* Store the chunk result */
- bcopy(result, data, hashlen);
- data += hashlen;
-
- bytes_left -= hashlen;
-
- /* Update A1 for next iteration */
- HMAC_INIT(mech, key, &ctx);
- HMAC_UPDATE(ctx, A1, hashlen);
- HMAC_FINAL(ctx, A1, hashlen);
-
- } else {
- bcopy(result, data, bytes_left);
- data += bytes_left;
- bytes_left = 0;
- }
- }
-end:
- if (CRYPTO_ERR(rv)) {
- DTRACE_PROBE1(kssl_err__crypto_mac_error, int, rv);
- KSSL_COUNTER(compute_mac_failure, 1);
- }
- return (rv);
-}
-
-/* ARGSUSED */
-static int
-kssl_tls_PRF(ssl_t *ssl, uchar_t *secret, size_t secret_len, uchar_t *label,
- size_t label_len, uchar_t *seed, size_t seed_len, uchar_t *prfresult,
- size_t prfresult_len)
-{
- /*
- * RFC 2246:
- * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
- * P_SHA1(S2, label + seed);
- * S1 = 1st half of secret.
- * S1 = 2nd half of secret.
- *
- */
-
- int rv, i;
- uchar_t psha1[MAX_KEYBLOCK_LENGTH];
- crypto_key_t S1, S2;
-
- /* length of secret keys is ceil(length/2) */
- size_t slen = roundup(secret_len, 2) / 2;
-
- if (prfresult_len > MAX_KEYBLOCK_LENGTH) {
- DTRACE_PROBE1(kssl_err__unexpected_keyblock_size,
- size_t, prfresult_len);
- return (CRYPTO_ARGUMENTS_BAD);
- }
-
- ASSERT(prfresult != NULL);
- ASSERT(label != NULL);
- ASSERT(seed != NULL);
-
- S1.ck_data = secret;
- S1.ck_length = slen * 8; /* bits */
- S1.ck_format = CRYPTO_KEY_RAW;
-
- S2.ck_data = secret + slen;
- S2.ck_length = slen * 8; /* bits */
- S2.ck_format = CRYPTO_KEY_RAW;
-
- rv = kssl_tls_P_hash(&hmac_md5_mech, &S1, MD5_HASH_LEN,
- label, label_len,
- seed, seed_len,
- prfresult, prfresult_len);
- if (CRYPTO_ERR(rv))
- goto end;
-
- rv = kssl_tls_P_hash(&hmac_sha1_mech, &S2, SHA1_HASH_LEN,
- label, label_len,
- seed, seed_len,
- psha1, prfresult_len);
- if (CRYPTO_ERR(rv))
- goto end;
-
- for (i = 0; i < prfresult_len; i++)
- prfresult[i] ^= psha1[i];
-
-end:
- if (CRYPTO_ERR(rv))
- bzero(prfresult, prfresult_len);
-
- return (rv);
-}
-
-#define IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl) \
- (pms == NULL || pmslen != SSL3_PRE_MASTER_SECRET_LEN || \
- pms[0] != ssl->major_version || pms[1] != ssl->minor_version)
-
-#define FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf) { \
- KSSL_COUNTER(bad_pre_master_secret, 1); \
- pms = buf; \
- pmslen = SSL3_PRE_MASTER_SECRET_LEN; \
- pms[0] = ssl->major_version; \
- pms[1] = ssl->minor_version; \
- (void) random_get_pseudo_bytes(&buf[2], pmslen - 2); \
-}
-
-static int
-kssl_generate_tls_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
-{
- uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
- uchar_t seed[SSL3_RANDOM_LENGTH * 2];
-
- /*
- * Computing the master secret:
- * ----------------------------
- * master_secret = PRF (pms, "master secret",
- * ClientHello.random + ServerHello.random);
- */
- bcopy(ssl->client_random, seed, SSL3_RANDOM_LENGTH);
- bcopy(ssl->server_random, seed + SSL3_RANDOM_LENGTH,
- SSL3_RANDOM_LENGTH);
-
- /* if pms is bad fake it to thwart Bleichenbacher attack */
- if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
- DTRACE_PROBE(kssl_err__under_Bleichenbacher_attack);
- FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
- }
-
- return (kssl_tls_PRF(ssl,
- pms, pmslen,
- (uchar_t *)TLS_MASTER_SECRET_LABEL,
- (size_t)strlen(TLS_MASTER_SECRET_LABEL),
- seed, sizeof (seed),
- ssl->sid.master_secret,
- (size_t)sizeof (ssl->sid.master_secret)));
-}
-
-
-static void
-kssl_generate_ssl_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
-{
- uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
- uchar_t *ms;
- int hlen = MD5_HASH_LEN;
-
- ms = ssl->sid.master_secret;
-
- /* if pms is bad fake it to thwart Bleichenbacher attack */
- if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
- DTRACE_PROBE(kssl_err__under_Bleichenbacher_attack);
- FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
- }
-
- kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 1, ms, 0);
- kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 2, ms + hlen, 0);
- kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 3, ms + 2 * hlen,
- 0);
-}
-
-static int
-kssl_generate_tls_keyblock(ssl_t *ssl)
-{
- uchar_t seed[2 * SSL3_RANDOM_LENGTH];
-
- bcopy(ssl->server_random, seed, SSL3_RANDOM_LENGTH);
- bcopy(ssl->client_random, seed + SSL3_RANDOM_LENGTH,
- SSL3_RANDOM_LENGTH);
-
- return (kssl_tls_PRF(ssl, ssl->sid.master_secret,
- (size_t)SSL3_MASTER_SECRET_LEN,
- (uchar_t *)TLS_KEY_EXPANSION_LABEL,
- (size_t)strlen(TLS_KEY_EXPANSION_LABEL),
- seed, (size_t)sizeof (seed),
- ssl->pending_keyblock,
- (size_t)ssl->pending_keyblksz));
-
-}
-
-static void
-kssl_generate_keyblock(ssl_t *ssl)
-{
- uchar_t *ms;
- size_t mslen = SSL3_MASTER_SECRET_LEN;
- int hlen = MD5_HASH_LEN;
- uchar_t *keys = ssl->pending_keyblock;
- int steps = howmany(ssl->pending_keyblksz, hlen);
- int i;
-
- ms = ssl->sid.master_secret;
-
- ASSERT(hlen * steps <= MAX_KEYBLOCK_LENGTH);
-
- for (i = 1; i <= steps; i++) {
- kssl_ssl3_key_material_derive_step(ssl, ms, mslen, i, keys, 1);
- keys += hlen;
- }
-}
-
-static char *ssl3_key_derive_seeds[9] = {"A", "BB", "CCC", "DDDD", "EEEEE",
- "FFFFFF", "GGGGGGG", "HHHHHHHH", "IIIIIIIII"};
-
-static void
-kssl_ssl3_key_material_derive_step(ssl_t *ssl, uchar_t *secret,
- size_t secretlen, int step, uchar_t *dst, int sr_first)
-{
- SHA1_CTX sha1, *sha1ctx;
- MD5_CTX md5, *md5ctx;
- uchar_t sha1_hash[SHA1_HASH_LEN];
-
- sha1ctx = &sha1;
- md5ctx = &md5;
-
- ASSERT(step <=
- sizeof (ssl3_key_derive_seeds) /
- sizeof (ssl3_key_derive_seeds[0]));
- step--;
-
- SHA1Init(sha1ctx);
- SHA1Update(sha1ctx, (uchar_t *)ssl3_key_derive_seeds[step],
- step + 1);
- SHA1Update(sha1ctx, secret, secretlen);
- if (sr_first) {
- SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
- SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
- } else {
- SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
- SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
- }
- SHA1Final(sha1_hash, sha1ctx);
-
- MD5Init(md5ctx);
- MD5Update(md5ctx, secret, secretlen);
- MD5Update(md5ctx, sha1_hash, SHA1_HASH_LEN);
- MD5Final(dst, md5ctx);
-}
-
-static int
-kssl_send_certificate_and_server_hello_done(ssl_t *ssl)
-{
- int cur_reclen;
- int mss;
- int len, copylen;
- mblk_t *mp;
- uchar_t *cert_buf;
- int cert_len;
- uchar_t *msgbuf;
- Certificate_t *cert;
- uint16_t reclen = KSSL_SSL3_SH_RECLEN;
-
- cert = ssl->kssl_entry->ke_server_certificate;
- if (cert == NULL) {
- return (ENOENT);
- }
- cert_buf = cert->msg;
- cert_len = cert->len;
-
- if (ssl->secure_renegotiation)
- reclen += KSSL_EMPTY_RENEG_INFO_LEN;
-
- mp = ssl->handshake_sendbuf;
- mss = ssl->tcp_mss;
- ASSERT(mp != NULL);
- cur_reclen = mp->b_wptr - mp->b_rptr - SSL3_HDR_LEN;
- ASSERT(cur_reclen == reclen);
- /* Assume MSS is at least 80 bytes */
- ASSERT(mss > cur_reclen + SSL3_HDR_LEN);
- ASSERT(cur_reclen < SSL3_MAX_RECORD_LENGTH); /* XXX */
-
- copylen = mss - (cur_reclen + SSL3_HDR_LEN);
- len = cert_len;
- copylen = MIN(copylen, len);
- copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
-
- /* new record always starts in a new mblk for simplicity */
- msgbuf = cert_buf;
- for (;;) {
- ASSERT(mp->b_wptr + copylen <= mp->b_datap->db_lim);
- bcopy(msgbuf, mp->b_wptr, copylen);
- msgbuf += copylen;
- mp->b_wptr += copylen;
- cur_reclen += copylen;
- len -= copylen;
- if (len == 0) {
- break;
- }
- if (cur_reclen == SSL3_MAX_RECORD_LENGTH) {
- cur_reclen = 0;
- }
- copylen = MIN(len, mss);
- copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
- mp->b_cont = allocb(copylen, BPRI_HI);
- if (mp->b_cont == NULL) {
- KSSL_COUNTER(alloc_fails, 1);
- freemsg(ssl->handshake_sendbuf);
- ssl->handshake_sendbuf = NULL;
- return (ENOMEM);
- }
- mp = mp->b_cont;
- if (cur_reclen == 0) {
- mp->b_wptr[0] = content_handshake;
- mp->b_wptr[1] = ssl->major_version;
- mp->b_wptr[2] = ssl->minor_version;
- cur_reclen = MIN(len, reclen);
- mp->b_wptr[3] = (cur_reclen >> 8) & 0xff;
- mp->b_wptr[4] = (cur_reclen) & 0xff;
- mp->b_wptr += SSL3_HDR_LEN;
- cur_reclen = 0;
- copylen = MIN(copylen, mss - SSL3_HDR_LEN);
- }
- }
-
- /* adjust the record length field for the first record */
- mp = ssl->handshake_sendbuf;
- cur_reclen = MIN(reclen + cert_len, SSL3_MAX_RECORD_LENGTH);
- mp->b_rptr[3] = (cur_reclen >> 8) & 0xff;
- mp->b_rptr[4] = (cur_reclen) & 0xff;
-
- kssl_update_handshake_hashes(ssl, cert_buf, cert_len);
-
- return (0);
-}
-
-static int
-kssl_send_change_cipher_specs(ssl_t *ssl)
-{
- mblk_t *mp, *newmp;
- uchar_t *buf;
-
- mp = ssl->handshake_sendbuf;
-
- /* We're most likely to hit the fast path for resumed sessions */
- if ((mp != NULL) &&
- (mp->b_datap->db_lim - mp->b_wptr > KSSL_SSL3_MAX_CCP_FIN_MSGLEN)) {
- buf = mp->b_wptr;
- } else {
- newmp = allocb(KSSL_SSL3_MAX_CCP_FIN_MSGLEN, BPRI_HI);
-
- if (newmp == NULL)
- return (ENOMEM); /* need to do better job! */
-
- if (mp == NULL) {
- ssl->handshake_sendbuf = newmp;
- } else {
- linkb(ssl->handshake_sendbuf, newmp);
- }
- mp = newmp;
- buf = mp->b_rptr;
- }
-
- /* 5 byte record header */
- buf[0] = content_change_cipher_spec;
- buf[1] = ssl->major_version;
- buf[2] = ssl->minor_version;
- buf[3] = 0;
- buf[4] = 1;
- buf += SSL3_HDR_LEN;
-
- buf[0] = 1;
-
- mp->b_wptr = buf + 1;
- ASSERT(mp->b_wptr < mp->b_datap->db_lim);
-
- ssl->seq_num[KSSL_WRITE] = 0;
- return (kssl_spec_init(ssl, KSSL_WRITE));
-}
-
-int
-kssl_spec_init(ssl_t *ssl, int dir)
-{
- KSSL_HASHCTX *ctx;
- KSSLCipherSpec *spec = &ssl->spec[dir];
- int ret = 0;
-
- spec->mac_hashsz = mac_defs[ssl->pending_malg].hashsz;
- spec->mac_padsz = mac_defs[ssl->pending_malg].padsz;
-
- spec->MAC_HashInit = mac_defs[ssl->pending_malg].HashInit;
- spec->MAC_HashUpdate = mac_defs[ssl->pending_malg].HashUpdate;
- spec->MAC_HashFinal = mac_defs[ssl->pending_malg].HashFinal;
-
- if (dir == KSSL_READ) {
- bcopy(ssl->pending_keyblock, ssl->mac_secret[dir],
- spec->mac_hashsz);
- } else {
- bcopy(&(ssl->pending_keyblock[spec->mac_hashsz]),
- ssl->mac_secret[dir], spec->mac_hashsz);
- }
-
- /* Pre-compute these here. will save cycles on each record later */
- if (!IS_TLS(ssl)) {
- ctx = &ssl->mac_ctx[dir][0];
- spec->MAC_HashInit((void *)ctx);
- spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
- spec->mac_hashsz);
- spec->MAC_HashUpdate((void *)ctx, kssl_pad_1,
- spec->mac_padsz);
-
- ctx = &ssl->mac_ctx[dir][1];
- spec->MAC_HashInit((void *)ctx);
- spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
- spec->mac_hashsz);
- spec->MAC_HashUpdate((void *)ctx, kssl_pad_2,
- spec->mac_padsz);
- }
-
- spec->cipher_type = cipher_defs[ssl->pending_calg].type;
- spec->cipher_mech.cm_type = cipher_defs[ssl->pending_calg].mech_type;
- spec->cipher_bsize = cipher_defs[ssl->pending_calg].bsize;
- spec->cipher_keysz = cipher_defs[ssl->pending_calg].keysz;
-
- if (spec->cipher_ctx != NULL) {
- crypto_cancel_ctx(spec->cipher_ctx);
- spec->cipher_ctx = 0;
- }
-
- /*
- * Initialize HMAC keys for TLS and SSL3 HMAC keys
- * for SSL 3.0.
- */
- if (IS_TLS(ssl)) {
- if (ssl->pending_malg == mac_md5) {
- spec->hmac_mech = hmac_md5_mech;
- } else if (ssl->pending_malg == mac_sha) {
- spec->hmac_mech = hmac_sha1_mech;
- }
-
- spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
- spec->hmac_key.ck_data = ssl->mac_secret[dir];
- spec->hmac_key.ck_length = spec->mac_hashsz * 8;
- } else {
- static uint32_t param;
-
- spec->hmac_mech.cm_type = CRYPTO_MECH_INVALID;
- spec->hmac_mech.cm_param = (caddr_t)&param;
- spec->hmac_mech.cm_param_len = sizeof (param);
- if (ssl->pending_malg == mac_md5) {
- spec->hmac_mech.cm_type =
- crypto_mech2id("CKM_SSL3_MD5_MAC");
- param = MD5_HASH_LEN;
- } else if (ssl->pending_malg == mac_sha) {
- spec->hmac_mech.cm_type =
- crypto_mech2id("CKM_SSL3_SHA1_MAC");
- param = SHA1_HASH_LEN;
- }
-
- spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
- spec->hmac_key.ck_data = ssl->mac_secret[dir];
- spec->hmac_key.ck_length = spec->mac_hashsz * 8;
- }
-
- /* We're done if this is the nil cipher */
- if (spec->cipher_keysz == 0) {
- return (0);
- }
-
- /* Initialize the key and the active context */
- spec->cipher_key.ck_format = CRYPTO_KEY_RAW;
- spec->cipher_key.ck_length = 8 * spec->cipher_keysz; /* in bits */
-
- if (cipher_defs[ssl->pending_calg].bsize > 0) {
- /* client_write_IV */
- spec->cipher_mech.cm_param =
- (caddr_t)&(ssl->pending_keyblock[2 * spec->mac_hashsz +
- 2 * spec->cipher_keysz]);
- spec->cipher_mech.cm_param_len = spec->cipher_bsize;
- }
- spec->cipher_data.cd_format = CRYPTO_DATA_RAW;
- if (dir == KSSL_READ) {
- spec->cipher_mech.cm_param_len =
- cipher_defs[ssl->pending_calg].bsize;
-
- /* client_write_key */
- spec->cipher_key.ck_data =
- &(ssl->pending_keyblock[2 * spec->mac_hashsz]);
-
- ret = crypto_decrypt_init(&(spec->cipher_mech),
- &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
- if (CRYPTO_ERR(ret)) {
- DTRACE_PROBE1(kssl_err__crypto_decrypt_init_read,
- int, ret);
- }
- } else {
- if (cipher_defs[ssl->pending_calg].bsize > 0) {
- /* server_write_IV */
- spec->cipher_mech.cm_param += spec->cipher_bsize;
- }
-
- /* server_write_key */
- spec->cipher_key.ck_data =
- &(ssl->pending_keyblock[2 * spec->mac_hashsz +
- spec->cipher_keysz]);
-
- ret = crypto_encrypt_init(&(spec->cipher_mech),
- &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
- if (CRYPTO_ERR(ret))
- DTRACE_PROBE1(kssl_err__crypto_encrypt_init_non_read,
- int, ret);
- }
- return (ret);
-}
-
-static int
-kssl_send_finished(ssl_t *ssl, int update_hsh)
-{
- mblk_t *mp;
- uchar_t *buf;
- uchar_t *rstart;
- uchar_t *versionp;
- SSL3Hashes ssl3hashes;
- uchar_t finish_len;
- int ret;
- uint16_t adj_len = 0;
-
- mp = ssl->handshake_sendbuf;
- ASSERT(mp != NULL);
- buf = mp->b_wptr;
- if (ssl->secure_renegotiation)
- adj_len = KSSL_EMPTY_RENEG_INFO_LEN;
- /*
- * It should be either a message with Server Hello record or just plain
- * SSL header (data packet).
- */
- ASSERT(buf - mp->b_rptr ==
- SSL3_HDR_LEN + KSSL_SSL3_SH_RECLEN + SSL3_HDR_LEN + 1 + adj_len ||
- buf - mp->b_rptr == SSL3_HDR_LEN + 1);
-
- rstart = buf;
-
- if (IS_TLS(ssl))
- finish_len = TLS_FINISHED_SIZE;
- else
- finish_len = KSSL_SSL3_FIN_MSGLEN;
-
- /* 5 byte record header */
- buf[0] = content_handshake;
- buf[1] = ssl->major_version;
- buf[2] = ssl->minor_version;
- buf[3] = 0;
- buf[4] = 4 + finish_len;
-
- versionp = &buf[1];
-
- buf += SSL3_HDR_LEN;
-
- /* 4 byte message header */
- buf[0] = (uchar_t)finished; /* message type */
- buf[1] = 0; /* message len byte 0 */
- buf[2] = 0; /* message len byte 1 */
- buf[3] = finish_len; /* message len byte 2 */
- buf += 4;
-
- if (IS_TLS(ssl)) {
- bcopy(ssl->hs_hashes.md5, ssl3hashes.md5,
- sizeof (ssl3hashes.md5));
- bcopy(ssl->hs_hashes.sha1, ssl3hashes.sha1,
- sizeof (ssl3hashes.sha1));
- }
-
- /* Compute hashes for the SENDER side */
- ret = kssl_compute_handshake_hashes(ssl, &ssl3hashes, sender_server);
- if (ret != 0)
- return (ret);
-
- if (IS_TLS(ssl)) {
- bcopy(ssl3hashes.tlshash, buf, sizeof (ssl3hashes.tlshash));
- } else {
- bcopy(ssl3hashes.md5, buf, MD5_HASH_LEN);
- bcopy(ssl3hashes.sha1, buf + MD5_HASH_LEN, SHA1_HASH_LEN);
- }
-
- if (update_hsh) {
- kssl_update_handshake_hashes(ssl, buf - 4, finish_len + 4);
- }
-
- mp->b_wptr = buf + finish_len;
-
- ret = kssl_mac_encrypt_record(ssl, content_handshake, versionp,
- rstart, mp);
- ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
-
- return (ret);
-}
-
-int
-kssl_mac_encrypt_record(ssl_t *ssl, SSL3ContentType ct, uchar_t *versionp,
- uchar_t *rstart, mblk_t *mp)
-{
- KSSLCipherSpec *spec;
- int mac_sz;
- int ret = 0;
- uint16_t rec_sz;
- int pad_sz;
- int i;
-
- ASSERT(ssl != NULL);
- ASSERT(rstart >= mp->b_rptr);
- ASSERT(rstart < mp->b_wptr);
-
- spec = &ssl->spec[KSSL_WRITE];
- mac_sz = spec->mac_hashsz;
-
- rec_sz = (mp->b_wptr - rstart) - SSL3_HDR_LEN;
- ASSERT(rec_sz > 0);
-
- if (mac_sz != 0) {
- ASSERT(mp->b_wptr + mac_sz <= mp->b_datap->db_lim);
- ret = kssl_compute_record_mac(ssl, KSSL_WRITE,
- ssl->seq_num[KSSL_WRITE], ct, versionp,
- rstart + SSL3_HDR_LEN, rec_sz, mp->b_wptr);
- if (ret == CRYPTO_SUCCESS) {
- ssl->seq_num[KSSL_WRITE]++;
- mp->b_wptr += mac_sz;
- rec_sz += mac_sz;
- } else {
- return (ret);
- }
- }
-
- if (spec->cipher_type == type_block) {
- pad_sz = spec->cipher_bsize -
- (rec_sz & (spec->cipher_bsize - 1));
- ASSERT(mp->b_wptr + pad_sz <= mp->b_datap->db_lim);
- for (i = 0; i < pad_sz; i++) {
- mp->b_wptr[i] = pad_sz - 1;
- }
- mp->b_wptr += pad_sz;
- rec_sz += pad_sz;
- }
-
- ASSERT(rec_sz <= SSL3_MAX_RECORD_LENGTH);
-
- U16_TO_BE16(rec_sz, rstart + 3);
-
- if (spec->cipher_ctx == 0)
- return (ret);
-
- spec->cipher_data.cd_length = rec_sz;
- spec->cipher_data.cd_raw.iov_base = (char *)(rstart + SSL3_HDR_LEN);
- spec->cipher_data.cd_raw.iov_len = rec_sz;
- /* One record at a time. Otherwise, gotta allocate the crypt_data_t */
- ret = crypto_encrypt_update(spec->cipher_ctx, &spec->cipher_data,
- NULL, NULL);
- if (CRYPTO_ERR(ret)) {
- DTRACE_PROBE1(kssl_err__crypto_encrypt_update,
- int, ret);
- }
- return (ret);
-}
-
-/*
- * Produce SSL alert message (SSLv3/TLS) or error message (SSLv2). For SSLv2
- * it is only done to tear down the SSL connection so it has fixed encoding.
- */
-void
-kssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc)
-{
- mblk_t *mp;
- uchar_t *buf;
- KSSLCipherSpec *spec;
- size_t len;
-
- ASSERT(ssl != NULL);
-
- ssl->sendalert_level = level;
- ssl->sendalert_desc = desc;
-
- if (level == alert_fatal) {
- DTRACE_PROBE2(kssl_sending_alert,
- SSL3AlertLevel, level, SSL3AlertDescription, desc);
- if (ssl->sid.cached == B_TRUE) {
- kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
- }
- ssl->fatal_alert = B_TRUE;
- KSSL_COUNTER(fatal_alerts, 1);
- } else
- KSSL_COUNTER(warning_alerts, 1);
-
- spec = &ssl->spec[KSSL_WRITE];
-
- ASSERT(ssl->alert_sendbuf == NULL);
- if (ssl->major_version == 0x03) {
- len = SSL3_HDR_LEN + SSL3_ALERT_LEN;
- } else {
- /* KSSL generates 5 byte SSLv2 alert messages only. */
- len = 5;
- }
- ssl->alert_sendbuf = mp = allocb(len + spec->mac_hashsz +
- spec->cipher_bsize, BPRI_HI);
- if (mp == NULL) {
- KSSL_COUNTER(alloc_fails, 1);
- return;
- }
- buf = mp->b_wptr;
-
- /* SSLv3/TLS */
- if (ssl->major_version == 0x03) {
- /* 5 byte record header */
- buf[0] = content_alert;
- buf[1] = ssl->major_version;
- buf[2] = ssl->minor_version;
- buf[3] = 0;
- buf[4] = 2;
- buf += SSL3_HDR_LEN;
-
- /* alert contents */
- buf[0] = (uchar_t)level;
- buf[1] = (uchar_t)desc;
- buf += SSL3_ALERT_LEN;
- } else {
- /* SSLv2 has different encoding. */
- /* 2-byte encoding of the length */
- buf[0] = 0x80;
- buf[1] = 0x03;
- buf += 2;
-
- /* Protocol Message Code = Error */
- buf[0] = 0;
- /* Error Message Code = Undefined Error */
- buf[1] = 0;
- buf[2] = 0;
- buf += 3;
- }
-
- mp->b_wptr = buf;
-}
-
-/* Assumes RSA encryption */
-static int
-kssl_handle_client_key_exchange(ssl_t *ssl, mblk_t *mp, int msglen,
- kssl_callback_t cbfn, void *arg)
-{
- char *buf;
- uchar_t *pms;
- size_t pmslen;
- int allocated;
- int err, rverr = ENOMEM;
- kssl_entry_t *ep;
- crypto_key_t *privkey;
- crypto_data_t *wrapped_pms_data, *pms_data;
- crypto_call_req_t creq, *creqp;
-
- ep = ssl->kssl_entry;
- privkey = ep->ke_private_key;
- if (privkey == NULL) {
- return (ENOENT);
- }
-
- ASSERT(ssl->msg.type == client_key_exchange);
- ASSERT(ssl->hs_waitstate == wait_client_key);
-
- /*
- * TLS adds an extra 2 byte length field before the data.
- */
- if (IS_TLS(ssl)) {
- msglen = (mp->b_rptr[0] << 8) | mp->b_rptr[1];
- mp->b_rptr += 2;
- }
-
- /*
- * Allocate all we need in one shot. about 300 bytes total, for
- * 1024 bit RSA modulus.
- * The buffer layout will be: pms_data, wrapped_pms_data, the
- * value of the wrapped pms from the client, then room for the
- * resulting decrypted premaster secret.
- */
- allocated = 2 * (sizeof (crypto_data_t) + msglen);
- buf = kmem_alloc(allocated, KM_NOSLEEP);
- if (buf == NULL) {
- return (ENOMEM);
- }
-
- pms_data = (crypto_data_t *)buf;
- wrapped_pms_data = &(((crypto_data_t *)buf)[1]);
-
- wrapped_pms_data->cd_format = pms_data->cd_format = CRYPTO_DATA_RAW;
- wrapped_pms_data->cd_offset = pms_data->cd_offset = 0;
- wrapped_pms_data->cd_length = pms_data->cd_length = msglen;
- wrapped_pms_data->cd_miscdata = pms_data->cd_miscdata = NULL;
- wrapped_pms_data->cd_raw.iov_len = pms_data->cd_raw.iov_len = msglen;
- wrapped_pms_data->cd_raw.iov_base = buf + 2 * sizeof (crypto_data_t);
- pms_data->cd_raw.iov_base = wrapped_pms_data->cd_raw.iov_base + msglen;
-
- bcopy(mp->b_rptr, wrapped_pms_data->cd_raw.iov_base, msglen);
- mp->b_rptr += msglen;
-
- /* Proceed synchronously if out of interrupt and configured to do so */
- if ((kssl_synchronous) && (!servicing_interrupt())) {
- creqp = NULL;
- } else {
- ssl->cke_callback_func = cbfn;
- ssl->cke_callback_arg = arg;
- creq.cr_flag = kssl_call_flag;
- creq.cr_callback_func = kssl_cke_done;
- creq.cr_callback_arg = ssl;
-
- creqp = &creq;
- }
-
- if (ep->ke_is_nxkey) {
- kssl_session_info_t *s;
-
- s = ep->ke_sessinfo;
- err = CRYPTO_SUCCESS;
- if (!s->is_valid_handle) {
- /* Reauthenticate to the provider */
- if (s->do_reauth) {
- err = kssl_get_obj_handle(ep);
- if (err == CRYPTO_SUCCESS) {
- s->is_valid_handle = B_TRUE;
- s->do_reauth = B_FALSE;
- }
- } else
- err = CRYPTO_FAILED;
- }
-
- if (err == CRYPTO_SUCCESS) {
- ASSERT(s->is_valid_handle);
- err = crypto_decrypt_prov(s->prov, s->sid,
- &rsa_x509_mech, wrapped_pms_data, &s->key,
- NULL, pms_data, creqp);
- }
-
- /*
- * Deal with session specific errors. We translate to
- * the closest errno.
- */
- switch (err) {
- case CRYPTO_KEY_HANDLE_INVALID:
- case CRYPTO_SESSION_HANDLE_INVALID:
- s->is_valid_handle = B_FALSE;
- s->do_reauth = B_TRUE;
- rverr = EINVAL;
- break;
- case CRYPTO_PIN_EXPIRED:
- case CRYPTO_PIN_LOCKED:
- rverr = EACCES;
- break;
- case CRYPTO_UNKNOWN_PROVIDER:
- rverr = ENXIO;
- break;
- }
- } else {
- err = crypto_decrypt(&rsa_x509_mech, wrapped_pms_data,
- privkey, NULL, pms_data, creqp);
- }
-
- switch (err) {
- case CRYPTO_SUCCESS:
- break;
-
- case CRYPTO_QUEUED:
- /*
- * Finish the master secret then the rest of key material
- * derivation later.
- */
- ssl->job.kjob = creq.cr_reqid;
- ssl->job.buf = buf;
- ssl->job.buflen = allocated;
- ssl->hs_waitstate = wait_client_key_done;
- return (0);
- default:
- DTRACE_PROBE1(kssl_err__crypto_decrypt, int, err);
- kmem_free(buf, allocated);
- return (rverr);
- }
-
- pmslen = pms_data->cd_length;
- pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
-
- /* generate master key and save it in the ssl sid structure */
- if (IS_TLS(ssl)) {
- err = kssl_generate_tls_ms(ssl, pms, pmslen);
- if (!CRYPTO_ERR(err))
- err = kssl_generate_tls_keyblock(ssl);
- } else {
- kssl_generate_ssl_ms(ssl, pms, pmslen);
- kssl_generate_keyblock(ssl);
- }
-
- if (err == CRYPTO_SUCCESS)
- ssl->hs_waitstate = wait_change_cipher;
-
- ssl->activeinput = B_FALSE;
-
- kmem_free(buf, allocated);
-
- return (0);
-}
-
-static int
-kssl_handle_finished(ssl_t *ssl, mblk_t *mp, int msglen)
-{
- int err;
- size_t finish_len;
- int hashcompare;
-
- ASSERT(ssl->msg.type == finished);
- ASSERT(ssl->hs_waitstate == wait_finished);
-
- if (IS_TLS(ssl))
- finish_len = TLS_FINISHED_SIZE;
- else
- finish_len = KSSL_SSL3_FIN_MSGLEN;
-
- if (msglen != finish_len) {
- kssl_send_alert(ssl, alert_fatal, illegal_parameter);
- return (EBADMSG);
- }
-
- if (IS_TLS(ssl)) {
- hashcompare = bcmp(mp->b_rptr, ssl->hs_hashes.tlshash,
- finish_len);
- } else {
- hashcompare = bcmp(mp->b_rptr, &ssl->hs_hashes, finish_len);
- }
-
- /* The handshake hashes should be computed by now */
- if (hashcompare != 0) {
- kssl_send_alert(ssl, alert_fatal, handshake_failure);
- return (EBADMSG);
- }
-
- mp->b_rptr += msglen;
-
- ssl->hs_waitstate = idle_handshake;
-
- if (ssl->resumed == B_TRUE) {
- ssl->activeinput = B_FALSE;
- return (0);
- }
-
- err = kssl_send_change_cipher_specs(ssl);
- if (err != 0) {
- return (err);
- }
- err = kssl_send_finished(ssl, 0);
- if (err != 0) {
- return (err);
- }
-
- kssl_cache_sid(&ssl->sid, ssl->kssl_entry);
- ssl->activeinput = B_FALSE;
-
- return (0);
-}
-
-#define KSSL2_CH_MIN_RECSZ (9)
-
-/*
- * This method is needed to handle clients which send the
- * SSLv2/SSLv3 handshake for backwards compat with SSLv2 servers.
- * We are not really doing SSLv2 here, just handling the header
- * and then switching to SSLv3.
- */
-int
-kssl_handle_v2client_hello(ssl_t *ssl, mblk_t *mp, int recsz)
-{
- uchar_t *recend;
- int err;
- SSL3AlertDescription desc = illegal_parameter;
- uint_t randlen;
- uint_t sidlen;
- uint_t cslen;
- uchar_t *suitesp;
- uchar_t *rand;
- uint_t i, j;
- uint16_t suite, selected_suite;
- int ch_recsz = KSSL2_CH_MIN_RECSZ;
- boolean_t suite_found = B_FALSE;
-
- ASSERT(mp->b_wptr >= mp->b_rptr + recsz);
- ASSERT(ssl->hs_waitstate == wait_client_hello);
- ASSERT(ssl->resumed == B_FALSE);
-
- if (recsz < ch_recsz) {
- DTRACE_PROBE2(kssl_err__reclen_less_than_minimum,
- int, recsz, int, ch_recsz);
- goto falert;
- }
-
- MD5Init(&ssl->hs_md5);
- SHA1Init(&ssl->hs_sha1);
-
- kssl_update_handshake_hashes(ssl, mp->b_rptr, recsz);
-
- recend = mp->b_rptr + recsz;
-
- if (*mp->b_rptr != 1) {
- DTRACE_PROBE1(kssl_err__invalid_version, uint_t, *mp->b_rptr);
- goto falert;
- }
- mp->b_rptr += 3;
-
- cslen = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
- sidlen = ((uint_t)mp->b_rptr[2] << 8) + (uint_t)mp->b_rptr[3];
- randlen = ((uint_t)mp->b_rptr[4] << 8) + (uint_t)mp->b_rptr[5];
- if (cslen % 3 != 0) {
- DTRACE_PROBE1(kssl_err__cipher_suites_len_error, uint_t, cslen);
- goto falert;
- }
- if (randlen < SSL_MIN_CHALLENGE_BYTES ||
- randlen > SSL_MAX_CHALLENGE_BYTES) {
- DTRACE_PROBE1(kssl_err__randlen_out_of_range,
- uint_t, randlen);
- goto falert;
- }
- mp->b_rptr += 6;
- ch_recsz += cslen + sidlen + randlen;
- if (recsz != ch_recsz) {
- DTRACE_PROBE2(kssl_err__invalid_message_len_sum,
- int, recsz, int, ch_recsz);
- goto falert;
- }
- suitesp = mp->b_rptr;
- rand = suitesp + cslen + sidlen;
- if (randlen < SSL3_RANDOM_LENGTH) {
- bzero(ssl->client_random, SSL3_RANDOM_LENGTH);
- }
- bcopy(rand, &ssl->client_random[SSL3_RANDOM_LENGTH - randlen],
- randlen);
-
- for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
- suite = ssl->kssl_entry->kssl_cipherSuites[i];
- for (j = 0; j < cslen; j += 3) {
- DTRACE_PROBE2(kssl_cipher_suite_check_v2,
- uint16_t, suite,
- uint16_t,
- (uint16_t)((suitesp[j+1] << 8) + suitesp[j+2]));
- if (suitesp[j] != 0) {
- continue;
- }
-
- /* Check for regular (true) cipher suite. */
- if (suitesp[j + 1] == ((suite >> 8) & 0xff) &&
- suitesp[j + 2] == (suite & 0xff)) {
- DTRACE_PROBE1(kssl_cipher_suite_found,
- uint16_t, suite);
- suite_found = B_TRUE;
- selected_suite = suite;
- }
-
- /* Check for SCSV. */
- if (suitesp[j + 1] == ((SSL_SCSV >> 8) & 0xff) &&
- suitesp[j + 2] == (SSL_SCSV & 0xff)) {
- DTRACE_PROBE(kssl_scsv_found);
- ssl->secure_renegotiation = B_TRUE;
- }
- /*
- * If we got cipher suite match and SCSV or went
- * through the whole list of client cipher suites
- * (hence we know if SCSV was present or not) we
- * can terminate the cycle now.
- */
- if (suite_found &&
- (ssl->secure_renegotiation || (i > 0)))
- break;
- }
- if (suite_found)
- break;
- }
- if (!suite_found) {
- DTRACE_PROBE(kssl_err__no_SSLv2_cipher_suite);
- ssl->activeinput = B_FALSE;
- /*
- * If there is no fallback point terminate the handshake with
- * SSL alert otherwise return with SSL_MISS.
- */
- if (ssl->kssl_entry->ke_fallback_head == NULL) {
- DTRACE_PROBE(kssl_no_fallback);
- desc = handshake_failure;
- goto falert;
- } else {
- return (SSL_MISS);
- }
- }
-
- mp->b_rptr = recend;
-
- for (i = 0; i < cipher_suite_defs_nentries; i++) {
- if (selected_suite == cipher_suite_defs[i].suite) {
- break;
- }
- }
-
- ASSERT(i < cipher_suite_defs_nentries);
-
- ssl->pending_cipher_suite = selected_suite;
- ssl->pending_malg = cipher_suite_defs[i].malg;
- ssl->pending_calg = cipher_suite_defs[i].calg;
- ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
-
- ASSERT(ssl->sid.cached == B_FALSE);
-
- (void) random_get_pseudo_bytes(ssl->sid.session_id,
- SSL3_SESSIONID_BYTES);
- ssl->sid.client_addr = ssl->faddr;
- ssl->sid.cipher_suite = selected_suite;
-
- err = kssl_send_server_hello(ssl);
- if (err != 0) {
- return (err);
- }
- err = kssl_send_certificate_and_server_hello_done(ssl);
- if (err != 0) {
- return (err);
- }
- KSSL_COUNTER(full_handshakes, 1);
- ssl->hs_waitstate = wait_client_key;
- ssl->activeinput = B_FALSE;
- return (0);
-
-falert:
- kssl_send_alert(ssl, alert_fatal, desc);
- ssl->activeinput = B_FALSE;
- return (EBADMSG);
-}
-
-/*
- * Call back routine for asynchronously submitted RSA decryption jobs.
- * This routine retrieves the pre-master secret, and proceeds to generate
- * the remaining key materials.
- */
-static void
-kssl_cke_done(void *arg, int status)
-{
- int ret = 0;
- uchar_t *pms;
- size_t pmslen;
- crypto_data_t *pms_data;
- kssl_cmd_t kssl_cmd = KSSL_CMD_NONE;
- ssl_t *ssl = (ssl_t *)arg;
- mblk_t *alertmp;
- kssl_callback_t cbfn;
- void *cbarg;
-
- mutex_enter(&ssl->kssl_lock);
-
- ASSERT(ssl->msg.type == client_key_exchange);
- ASSERT(ssl->hs_waitstate == wait_client_key_done);
-
- if (status != CRYPTO_SUCCESS) {
- kssl_send_alert(ssl, alert_fatal, decrypt_error);
- kssl_cmd = KSSL_CMD_SEND;
- goto out;
- }
-
- pms_data = (crypto_data_t *)(ssl->job.buf);
-
- ASSERT(pms_data != NULL);
-
- pmslen = pms_data->cd_length;
- pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
-
- /* generate master key and save it in the ssl sid structure */
- if (IS_TLS(ssl)) {
- ret = kssl_generate_tls_ms(ssl, pms, pmslen);
- if (!CRYPTO_ERR(ret))
- ret = kssl_generate_tls_keyblock(ssl);
- } else {
- kssl_generate_ssl_ms(ssl, pms, pmslen);
- kssl_generate_keyblock(ssl);
- }
-
- if (ret == CRYPTO_SUCCESS)
- ssl->hs_waitstate = wait_change_cipher;
-
-out:
- kmem_free(ssl->job.buf, ssl->job.buflen);
-
- ssl->job.kjob = 0;
- ssl->job.buf = NULL;
- ssl->job.buflen = 0;
-
- ssl->activeinput = B_FALSE;
-
- cbfn = ssl->cke_callback_func;
- cbarg = ssl->cke_callback_arg;
- alertmp = ssl->alert_sendbuf;
- ssl->alert_sendbuf = NULL;
-
- /* dropped by callback when it has completed */
- ssl->async_ops_pending++;
- mutex_exit(&ssl->kssl_lock);
-
- /* Now call the callback routine */
- (*(cbfn))(cbarg, alertmp, kssl_cmd);
-}
-
-/*
- * Returns the first complete contiguous record out of rec_ass_head
- * The record is returned in a separate contiguous mblk, rec_ass_head is
- * left pointing to the next record in the queue.
- *
- * The output looks as follows:
- *
- * |--------|---------- .... -----|<---------->|<----------->|--- ... ---|
- * ^ ^ ^ mac_size pad_size ^
- * | |___ b_rptr b_wptr __| |
- * | |
- * |___ db_base db_lim ___|
- */
-mblk_t *
-kssl_get_next_record(ssl_t *ssl)
-{
- mblk_t *mp, *retmp;
- int rhsz = SSL3_HDR_LEN;
- uint16_t rec_sz;
- int mpsz, total_size;
- SSL3ContentType content_type;
-
- ASSERT(MUTEX_HELD(&ssl->kssl_lock));
-
- mp = ssl->rec_ass_head;
- if (mp == NULL)
- return (NULL);
-
- /* Fast path: when mp has at least a complete record */
- if (MBLKL(mp) < rhsz) {
- DTRACE_PROBE1(kssl_mblk__incomplete_header,
- mblk_t *, mp);
- /* Not even a complete header in there yet */
- if (msgdsize(mp) < rhsz) {
- return (NULL);
- }
-
- if (!pullupmsg(mp, rhsz)) {
- kssl_send_alert(ssl, alert_fatal, internal_error);
- freemsg(mp);
- ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
- return (NULL);
- }
- }
- content_type = (SSL3ContentType)mp->b_rptr[0];
- if (content_type == content_handshake_v2) {
- DTRACE_PROBE1(kssl_mblk__ssl_v2, mblk_t *, mp);
- rec_sz = (uint16_t)mp->b_rptr[1];
- rhsz = 2;
- } else {
- DTRACE_PROBE1(kssl_mblk__ssl_v3, mblk_t *, mp);
- uint8_t *rec_sz_p = (uint8_t *)mp->b_rptr + 3;
- rec_sz = BE16_TO_U16(rec_sz_p);
- }
-
- /*
- * same tests as above. Only rare very fragmented cases will
- * incur the cost of msgdsize() and msgpullup(). Well formed
- * packets will fall in the most frequent fast path.
- */
- total_size = rhsz + rec_sz;
-
- /*
- * Missing: defensive against record fabricated with longer than
- * MAX record length.
- */
- if (MBLKL(mp) < total_size) {
- DTRACE_PROBE2(kssl_mblk__smaller_than_total_size,
- mblk_t *, mp, int, total_size);
- /* Not a complete record yet. Keep accumulating */
- if (msgdsize(mp) < total_size) {
- return (NULL);
- }
-
- if (!pullupmsg(mp, total_size)) {
- kssl_send_alert(ssl, alert_fatal, internal_error);
- freemsg(mp);
- ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
- return (NULL);
- }
- }
- mpsz = MBLKL(mp); /* could've changed after the pullup */
-
- if (mpsz > total_size) {
- DTRACE_PROBE2(kssl_mblk__bigger_than_total_size,
- mblk_t *, mp, int, total_size);
- /* gotta allocate a new block */
- if ((retmp = dupb(mp)) == NULL) {
- kssl_send_alert(ssl, alert_fatal, internal_error);
- freemsg(mp);
- ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
- return (NULL);
- }
-
- retmp->b_wptr = retmp->b_rptr + total_size;
- mp->b_rptr += total_size;
- ssl->rec_ass_head = mp;
- } else {
- DTRACE_PROBE2(kssl_mblk__equal_to_total_size,
- mblk_t *, mp, int, total_size);
- ASSERT(mpsz == total_size);
- ssl->rec_ass_head = mp->b_cont;
- mp->b_cont = NULL;
- retmp = mp;
- }
- /* Adjust the tail */
- if ((mp = ssl->rec_ass_tail = ssl->rec_ass_head) != NULL) {
- for (; mp->b_cont != NULL; mp = mp->b_cont) {
- ssl->rec_ass_tail = mp->b_cont;
- }
- }
-
- return (retmp);
-}
-
-
-static void
-kssl_mblksfree(ssl_t *ssl)
-{
-
- ASSERT(ssl != NULL);
-
- if (ssl->rec_ass_head != NULL) {
- freemsg(ssl->rec_ass_head);
- }
- ssl->rec_ass_head = NULL;
- ssl->rec_ass_tail = NULL;
-
- if (ssl->msg.head != NULL) {
- freemsg(ssl->msg.head);
- }
- ssl->msg.head = NULL;
- ssl->msg.tail = NULL;
-
- if (ssl->handshake_sendbuf != NULL) {
- freemsg(ssl->handshake_sendbuf);
- ssl->handshake_sendbuf = NULL;
- }
- if (ssl->alert_sendbuf != NULL) {
- freemsg(ssl->alert_sendbuf);
- ssl->alert_sendbuf = NULL;
- }
-}
-
-static void
-kssl_specsfree(ssl_t *ssl)
-{
- KSSLCipherSpec *spec = &ssl->spec[KSSL_READ];
-
- if (spec->cipher_ctx != NULL) {
- crypto_cancel_ctx(spec->cipher_ctx);
- spec->cipher_ctx = 0;
- }
-
- spec = &ssl->spec[KSSL_WRITE];
-
- if (spec->cipher_ctx != NULL) {
- crypto_cancel_ctx(spec->cipher_ctx);
- spec->cipher_ctx = 0;
- }
-}
-
-/*
- * Frees the ssl structure (aka the context of an SSL session).
- * Any pending crypto jobs are cancelled.
- * Any initiated crypto contexts are freed as well.
- */
-void
-kssl_free_context(ssl_t *ssl)
-{
- crypto_req_id_t reqid;
-
- ASSERT(ssl != NULL);
- if (!(MUTEX_HELD(&ssl->kssl_lock))) {
- /* we're coming from an external API entry point */
- mutex_enter(&ssl->kssl_lock);
- }
-
- /*
- * Cancel any active crypto request and wait for pending async
- * operations to complete. We loop here because the async thread
- * might submit a new cryto request.
- */
- do {
- if (ssl->job.kjob != 0) {
- /*
- * Drop the lock before canceling the request;
- * otherwise we might deadlock if the completion
- * callback is running.
- */
- reqid = ssl->job.kjob;
- mutex_exit(&ssl->kssl_lock);
- crypto_cancel_req(reqid);
- mutex_enter(&ssl->kssl_lock);
-
- /* completion callback might have done the cleanup */
- if (ssl->job.kjob != 0) {
- kmem_free(ssl->job.buf, ssl->job.buflen);
- ssl->job.kjob = 0;
- ssl->job.buf = NULL;
- ssl->job.buflen = 0;
- }
- }
- while (ssl->async_ops_pending > 0)
- cv_wait(&ssl->async_cv, &ssl->kssl_lock);
- } while (ssl->job.kjob != 0);
-
- kssl_mblksfree(ssl);
- kssl_specsfree(ssl);
-
- KSSL_ENTRY_REFRELE(ssl->kssl_entry);
- ssl->kssl_entry = NULL;
-
- mutex_exit(&ssl->kssl_lock);
-
- kmem_cache_free(kssl_cache, ssl);
-}
diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel
index baeb7b4f05..a3708e086a 100644
--- a/usr/src/uts/intel/Makefile.intel
+++ b/usr/src/uts/intel/Makefile.intel
@@ -23,7 +23,7 @@
# Copyright (c) 2013 Andrew Stormont. All rights reserved.
# Copyright (c) 2014 by Delphix. All rights reserved.
# Copyright 2019 Joyent, Inc.
-# Copyright 2016 Garrett D'Amore <garrett@damore.org>
+# Copyright 2022 Garrett D'Amore <garrett@damore.org>
# Copyright 2018 Nexenta Systems, Inc.
# Copyright 2019 RackTop Systems
# Copyright 2019 Peter Tribble.
@@ -264,7 +264,6 @@ DRV_KMODS += iwp
DRV_KMODS += iwscn
DRV_KMODS += kb8042
DRV_KMODS += keysock
-DRV_KMODS += kssl
DRV_KMODS += kstat
DRV_KMODS += ksyms
DRV_KMODS += kmdb
@@ -713,7 +712,6 @@ SOCKET_KMODS += sockpfp
SOCKET_KMODS += socksctp
SOCKET_KMODS += socksdp
SOCKET_KMODS += sockrds
-SOCKET_KMODS += ksslf
#
# kiconv modules (/kernel/kiconv):
diff --git a/usr/src/uts/intel/kssl/Makefile b/usr/src/uts/intel/kssl/Makefile
deleted file mode 100644
index b3ec5ff0a0..0000000000
--- a/usr/src/uts/intel/kssl/Makefile
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# This makefile drives the production of the kernel SSL driver
-# kernel module.
-#
-# intel architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = kssl
-OBJECTS = $(KSSL_OBJS:%=$(OBJS_DIR)/%)
-ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/common/inet/kssl
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
-
-LDFLAGS += -Nmisc/md5 -Nmisc/kcf
-
-#
-# For now, disable these warnings; maintainers should endeavor
-# to investigate and remove these for maximum coverage.
-# Please do not carry these forward to new Makefiles.
-#
-
-CERRWARN += $(CNOWARN_UNINIT)
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
diff --git a/usr/src/uts/intel/ksslf/Makefile b/usr/src/uts/intel/ksslf/Makefile
deleted file mode 100644
index d574e450cc..0000000000
--- a/usr/src/uts/intel/ksslf/Makefile
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-#
-# This makefile drives the production of the kssl socket filter
-# kernel module.
-#
-# intel architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = ksslf
-OBJECTS = $(KSSL_SOCKFIL_MOD_OBJS:%=$(OBJS_DIR)/%)
-ROOTMODULE = $(ROOT_SOCK_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-LDFLAGS += -Nmisc/md5 -Nmisc/kcf -Ndrv/kssl -Nfs/sockfs
-
-#
-# For now, disable these warnings; maintainers should endeavor
-# to investigate and remove these for maximum coverage.
-# Please do not carry these forward to new Makefiles.
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-switch
-CERRWARN += $(CNOWARN_UNINIT)
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
diff --git a/usr/src/uts/intel/ml/modstubs.s b/usr/src/uts/intel/ml/modstubs.s
index 4143c181a3..0f97c21ac6 100644
--- a/usr/src/uts/intel/ml/modstubs.s
+++ b/usr/src/uts/intel/ml/modstubs.s
@@ -23,6 +23,7 @@
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2019 Joyent, Inc.
* Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2022 Garrett D'Amore <garrett@damore.org>
*/
#include <sys/asm_linkage.h>
@@ -858,7 +859,6 @@ fcnname/**/_info: \
NO_UNLOAD_STUB(c2audit, audit_devpolicy, nomod_zero);
NO_UNLOAD_STUB(c2audit, audit_setfsat_path, nomod_zero);
NO_UNLOAD_STUB(c2audit, audit_cryptoadm, nomod_zero);
- NO_UNLOAD_STUB(c2audit, audit_kssl, nomod_zero);
NO_UNLOAD_STUB(c2audit, audit_pf_policy, nomod_zero);
NO_UNLOAD_STUB(c2audit, au_doormsg, nomod_zero);
NO_UNLOAD_STUB(c2audit, au_uwrite, nomod_zero);
diff --git a/usr/src/uts/sparc/Makefile.sparc b/usr/src/uts/sparc/Makefile.sparc
index 879d6dc1d9..a031e1606c 100644
--- a/usr/src/uts/sparc/Makefile.sparc
+++ b/usr/src/uts/sparc/Makefile.sparc
@@ -28,6 +28,7 @@
# Copyright 2016 Nexenta Systems, Inc.
# Copyright 2019 Peter Tribble.
# Copyright 2019 RackTop Systems
+# Copyright 2022 Garrett D'Amore <garrett@damore.org>
#
#
@@ -206,7 +207,7 @@ DRV_KMODS += dtrace fasttrap fbt lockstat profile sdt systrace dcpc
DRV_KMODS += fssnap icmp icmp6 ip ip6 ipnet ipsecah
DRV_KMODS += ipsecesp iptun iwscn keysock kmdb kstat ksyms llc1
DRV_KMODS += lofi
-DRV_KMODS += log logindmux kssl mm nca physmem pm poll pool
+DRV_KMODS += log logindmux mm nca physmem pm poll pool
DRV_KMODS += pseudo ptc ptm pts ptsl ramdisk random rsm rts sad
DRV_KMODS += simnet softmac sppp sppptun sy sysevent sysmsg
DRV_KMODS += spdsock
@@ -497,7 +498,6 @@ SOCKET_KMODS += sockpfp
SOCKET_KMODS += socksctp
SOCKET_KMODS += socksdp
SOCKET_KMODS += sockrds
-SOCKET_KMODS += ksslf
#
# kiconv modules (/kernel/kiconv):
diff --git a/usr/src/uts/sparc/kssl/Makefile b/usr/src/uts/sparc/kssl/Makefile
deleted file mode 100644
index 93f85f46ee..0000000000
--- a/usr/src/uts/sparc/kssl/Makefile
+++ /dev/null
@@ -1,85 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-
-#
-# This makefile drives the production of the kernel SSL driver
-# kernel module.
-#
-# sparc architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = kssl
-OBJECTS = $(KSSL_OBJS:%=$(OBJS_DIR)/%)
-ROOTMODULE = $(ROOT_DRV_DIR)/$(MODULE)
-CONF_SRCDIR = $(UTSBASE)/common/inet/kssl
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sparc/Makefile.sparc
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY) $(SRC_CONFFILE)
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
-
-LDFLAGS += -Nmisc/md5 -Nmisc/kcf
-
-#
-# For now, disable these warnings; maintainers should endeavor
-# to investigate and remove these for maximum coverage.
-# Please do not carry these forward to new Makefiles.
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += $(CNOWARN_UNINIT)
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sparc/Makefile.targ
diff --git a/usr/src/uts/sparc/ksslf/Makefile b/usr/src/uts/sparc/ksslf/Makefile
deleted file mode 100644
index def63e8420..0000000000
--- a/usr/src/uts/sparc/ksslf/Makefile
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# CDDL HEADER START
-#
-# The contents of this file are subject to the terms of the
-# Common Development and Distribution License (the "License").
-# You may not use this file except in compliance with the License.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
-#
-# This makefile drives the production of the kssl socket filter
-# kernel module.
-#
-# sparc architecture dependent
-#
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = ksslf
-OBJECTS = $(KSSL_SOCKFIL_MOD_OBJS:%=$(OBJS_DIR)/%)
-ROOTMODULE = $(ROOT_SOCK_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sparc/Makefile.sparc
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-LDFLAGS += -Nmisc/md5 -Nmisc/kcf -Ndrv/kssl -Nfs/sockfs
-
-#
-# For now, disable these warnings; maintainers should endeavor
-# to investigate and remove these for maximum coverage.
-# Please do not carry these forward to new Makefiles.
-#
-CFLAGS += $(CCVERBOSE)
-CERRWARN += -_gcc=-Wno-switch
-CERRWARN += $(CNOWARN_UNINIT)
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sparc/Makefile.targ
diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s
index 07de0dffff..f43346fd48 100644
--- a/usr/src/uts/sparc/ml/modstubs.s
+++ b/usr/src/uts/sparc/ml/modstubs.s
@@ -23,6 +23,7 @@
* Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright 2016 Nexenta Systems, Inc.
* Copyright (c) 2017, Joyent, Inc. All rights reserved.
+ * Copyright 2022 Garrett D'Amore <garrett@damore.org>
*/
#include "assym.h"
@@ -891,7 +892,6 @@ stubs_base:
NO_UNLOAD_STUB(c2audit, audit_devpolicy, nomod_zero);
NO_UNLOAD_STUB(c2audit, audit_setfsat_path, nomod_zero);
NO_UNLOAD_STUB(c2audit, audit_cryptoadm, nomod_zero);
- NO_UNLOAD_STUB(c2audit, audit_kssl, nomod_zero);
NO_UNLOAD_STUB(c2audit, audit_pf_policy, nomod_zero);
NO_UNLOAD_STUB(c2audit, au_doormsg, nomod_zero);
NO_UNLOAD_STUB(c2audit, au_uwrite, nomod_zero);