c28749e97052f09388969427adf7df641cdcdc22kais/*
c28749e97052f09388969427adf7df641cdcdc22kais * CDDL HEADER START
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * The contents of this file are subject to the terms of the
968d6dde54d2efa62910a3cf36438325d0b69031krishna * Common Development and Distribution License (the "License").
968d6dde54d2efa62910a3cf36438325d0b69031krishna * You may not use this file except in compliance with the License.
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
c28749e97052f09388969427adf7df641cdcdc22kais * or http://www.opensolaris.org/os/licensing.
c28749e97052f09388969427adf7df641cdcdc22kais * See the License for the specific language governing permissions
c28749e97052f09388969427adf7df641cdcdc22kais * and limitations under the License.
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * When distributing Covered Code, include this CDDL HEADER in each
c28749e97052f09388969427adf7df641cdcdc22kais * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
c28749e97052f09388969427adf7df641cdcdc22kais * If applicable, add the following below this CDDL HEADER, with the
c28749e97052f09388969427adf7df641cdcdc22kais * fields enclosed by brackets "[]" replaced with your own identifying
c28749e97052f09388969427adf7df641cdcdc22kais * information: Portions Copyright [yyyy] [name of copyright owner]
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * CDDL HEADER END
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais/*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/types.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/stream.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/strsubr.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/stropts.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/strsun.h>
c28749e97052f09388969427adf7df641cdcdc22kais#define _SUN_TPI_VERSION 2
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/ddi.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/sunddi.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/debug.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/vtrace.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/kmem.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/cpuvar.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/atomic.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/sysmacros.h>
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/errno.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/isa_defs.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/md5.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/sha1.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/random.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <inet/common.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <netinet/in.h>
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/systm.h>
c28749e97052f09388969427adf7df641cdcdc22kais#include <sys/param.h>
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#include "ksslimpl.h"
c28749e97052f09388969427adf7df641cdcdc22kais#include "ksslapi.h"
c28749e97052f09388969427adf7df641cdcdc22kais#include "ksslproto.h"
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic ssl3CipherSuiteDef cipher_suite_defs[] = {
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna /* 2 X 16 byte keys + 2 x 20 byte MAC secrets, no IVs */
c28749e97052f09388969427adf7df641cdcdc22kais {SSL_RSA_WITH_RC4_128_SHA, cipher_rc4, mac_sha, 72},
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna /* 2 X 16 byte keys + 2 x 16 byte MAC secrets, no IVs */
c28749e97052f09388969427adf7df641cdcdc22kais {SSL_RSA_WITH_RC4_128_MD5, cipher_rc4, mac_md5, 64},
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna /* 2 X 8 byte keys + 2 x 20 byte MAC secrets, 2 x 8 byte IVs */
c28749e97052f09388969427adf7df641cdcdc22kais {SSL_RSA_WITH_DES_CBC_SHA, cipher_des, mac_sha, 72},
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna /* 2 X 24 byte keys + 2 x 20 byte MAC secrets, 2 x 8 byte IVs */
c28749e97052f09388969427adf7df641cdcdc22kais {SSL_RSA_WITH_3DES_EDE_CBC_SHA, cipher_3des, mac_sha, 104},
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna /* 2 X 16 byte keys + 2 x 20 byte MAC secrets, 2 x 16 byte IVs */
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna {TLS_RSA_WITH_AES_128_CBC_SHA, cipher_aes128, mac_sha, 104},
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna /* 2 X 32 byte keys + 2 x 20 byte MAC secrets, 2 x 16 byte IVs */
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna {TLS_RSA_WITH_AES_256_CBC_SHA, cipher_aes256, mac_sha, 136},
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna
c28749e97052f09388969427adf7df641cdcdc22kais {SSL_RSA_WITH_NULL_SHA, cipher_null, mac_sha, 40}
c28749e97052f09388969427adf7df641cdcdc22kais};
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int cipher_suite_defs_nentries =
c28749e97052f09388969427adf7df641cdcdc22kais sizeof (cipher_suite_defs) / sizeof (cipher_suite_defs[0]);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic KSSLMACDef mac_defs[] = { /* indexed by SSL3MACAlgorithm */
c28749e97052f09388969427adf7df641cdcdc22kais /* macsz padsz HashInit HashUpdate HashFinal */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais {MD5_HASH_LEN, SSL3_MD5_PAD_LEN,
c28749e97052f09388969427adf7df641cdcdc22kais (hashinit_func_t)MD5Init, (hashupdate_func_t)MD5Update,
c28749e97052f09388969427adf7df641cdcdc22kais (hashfinal_func_t)MD5Final},
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais {SHA1_HASH_LEN, SSL3_SHA1_PAD_LEN,
c28749e97052f09388969427adf7df641cdcdc22kais (hashinit_func_t)SHA1Init, (hashupdate_func_t)SHA1Update,
c28749e97052f09388969427adf7df641cdcdc22kais (hashfinal_func_t)SHA1Final},
c28749e97052f09388969427adf7df641cdcdc22kais};
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic uchar_t kssl_pad_1[60] = {
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
c28749e97052f09388969427adf7df641cdcdc22kais 0x36, 0x36, 0x36, 0x36
c28749e97052f09388969427adf7df641cdcdc22kais};
c28749e97052f09388969427adf7df641cdcdc22kaisstatic uchar_t kssl_pad_2[60] = {
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
c28749e97052f09388969427adf7df641cdcdc22kais 0x5c, 0x5c, 0x5c, 0x5c
c28749e97052f09388969427adf7df641cdcdc22kais};
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic boolean_t kssl_synchronous = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_update_handshake_hashes(ssl_t *, uchar_t *, uint_t);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_compute_handshake_hashes(ssl_t *, SSL3Hashes *, uint32_t);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_handle_client_hello(ssl_t *, mblk_t *, int);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_handle_client_key_exchange(ssl_t *, mblk_t *, int,
c28749e97052f09388969427adf7df641cdcdc22kais kssl_callback_t, void *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_send_server_hello(ssl_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_send_certificate_and_server_hello_done(ssl_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_send_change_cipher_specs(ssl_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_send_finished(ssl_t *, int);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_handle_finished(ssl_t *, mblk_t *, int);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_get_hello_random(uchar_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic uchar_t *kssl_rsa_unwrap(uchar_t *, size_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_cache_sid(sslSessionID *, kssl_entry_t *);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduristatic void kssl_lookup_sid(sslSessionID *, uchar_t *, in6_addr_t *,
c28749e97052f09388969427adf7df641cdcdc22kais kssl_entry_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_generate_tls_ms(ssl_t *, uchar_t *, size_t);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_generate_ssl_ms(ssl_t *, uchar_t *, size_t);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_generate_tls_keyblock(ssl_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_generate_keyblock(ssl_t *);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_ssl3_key_material_derive_step(ssl_t *, uchar_t *, size_t,
c28749e97052f09388969427adf7df641cdcdc22kais int, uchar_t *, int);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_tls_PRF(ssl_t *, uchar_t *, size_t,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int kssl_tls_P_hash(crypto_mechanism_t *, crypto_key_t *,
c28749e97052f09388969427adf7df641cdcdc22kais size_t, uchar_t *, size_t, uchar_t *, size_t, uchar_t *, size_t);
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void kssl_cke_done(void *, int);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#define HMAC_INIT(m, k, c) \
c28749e97052f09388969427adf7df641cdcdc22kais rv = crypto_mac_init(m, k, NULL, c, NULL); if (CRYPTO_ERR(rv)) goto end;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#define HMAC_UPDATE(c, d, l) \
c28749e97052f09388969427adf7df641cdcdc22kais dd.cd_raw.iov_base = (char *)d; \
c28749e97052f09388969427adf7df641cdcdc22kais dd.cd_length = dd.cd_raw.iov_len = l; \
c28749e97052f09388969427adf7df641cdcdc22kais rv = crypto_mac_update(c, &dd, NULL); if (CRYPTO_ERR(rv)) goto end;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#define HMAC_FINAL(c, d, l) \
c28749e97052f09388969427adf7df641cdcdc22kais mac.cd_raw.iov_base = (char *)d; \
c28749e97052f09388969427adf7df641cdcdc22kais mac.cd_length = mac.cd_raw.iov_len = l; \
c28749e97052f09388969427adf7df641cdcdc22kais rv = crypto_mac_final(c, &mac, NULL); if (CRYPTO_ERR(rv)) goto end;
c28749e97052f09388969427adf7df641cdcdc22kais
efe05f9ecde56550699213909fd4152ef8ef6438krishna/*
efe05f9ecde56550699213909fd4152ef8ef6438krishna * This hack can go away once we have SSL3 MAC support by KCF
efe05f9ecde56550699213909fd4152ef8ef6438krishna * software providers (See 4873559).
efe05f9ecde56550699213909fd4152ef8ef6438krishna */
efe05f9ecde56550699213909fd4152ef8ef6438krishnaextern int kcf_md5_threshold;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
c28749e97052f09388969427adf7df641cdcdc22kaisint
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_compute_record_mac(
c28749e97052f09388969427adf7df641cdcdc22kais ssl_t *ssl,
c28749e97052f09388969427adf7df641cdcdc22kais int direction,
c28749e97052f09388969427adf7df641cdcdc22kais uint64_t seq_num,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3ContentType ct,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *versionp,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *buf,
c28749e97052f09388969427adf7df641cdcdc22kais int len,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *digest)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_HASHCTX mac_ctx;
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_HASHCTX *ctx = &mac_ctx;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t temp[16], *p;
c28749e97052f09388969427adf7df641cdcdc22kais KSSLCipherSpec *spec;
efe05f9ecde56550699213909fd4152ef8ef6438krishna boolean_t hash_use_ok = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais int rv = 0;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec = &ssl->spec[direction];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->mac_hashsz == 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais p = temp;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 56) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 48) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 40) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 32) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 24) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 16) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (seq_num) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (uchar_t)ct;
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = versionp[0];
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = versionp[1];
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (len >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais *p++ = (len) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais
efe05f9ecde56550699213909fd4152ef8ef6438krishna if (IS_TLS(ssl) || (spec->hmac_mech.cm_type != CRYPTO_MECH_INVALID &&
efe05f9ecde56550699213909fd4152ef8ef6438krishna len >= kcf_md5_threshold)) {
c28749e97052f09388969427adf7df641cdcdc22kais crypto_data_t dd, mac;
efe05f9ecde56550699213909fd4152ef8ef6438krishna struct uio uio_pt;
efe05f9ecde56550699213909fd4152ef8ef6438krishna struct iovec iovarray_pt[2];
efe05f9ecde56550699213909fd4152ef8ef6438krishna
efe05f9ecde56550699213909fd4152ef8ef6438krishna /* init the array of iovecs for use in the uio struct */
efe05f9ecde56550699213909fd4152ef8ef6438krishna iovarray_pt[0].iov_base = (char *)temp;
efe05f9ecde56550699213909fd4152ef8ef6438krishna iovarray_pt[0].iov_len = (p - temp);
efe05f9ecde56550699213909fd4152ef8ef6438krishna iovarray_pt[1].iov_base = (char *)buf;
efe05f9ecde56550699213909fd4152ef8ef6438krishna iovarray_pt[1].iov_len = len;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
efe05f9ecde56550699213909fd4152ef8ef6438krishna /* init the uio struct for use in the crypto_data_t struct */
efe05f9ecde56550699213909fd4152ef8ef6438krishna bzero(&uio_pt, sizeof (uio_pt));
efe05f9ecde56550699213909fd4152ef8ef6438krishna uio_pt.uio_iov = iovarray_pt;
efe05f9ecde56550699213909fd4152ef8ef6438krishna uio_pt.uio_iovcnt = 2;
efe05f9ecde56550699213909fd4152ef8ef6438krishna uio_pt.uio_segflg = UIO_SYSSPACE;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
efe05f9ecde56550699213909fd4152ef8ef6438krishna dd.cd_format = CRYPTO_DATA_UIO;
c28749e97052f09388969427adf7df641cdcdc22kais dd.cd_offset = 0;
efe05f9ecde56550699213909fd4152ef8ef6438krishna dd.cd_length = (p - temp) + len;
efe05f9ecde56550699213909fd4152ef8ef6438krishna dd.cd_miscdata = NULL;
efe05f9ecde56550699213909fd4152ef8ef6438krishna dd.cd_uio = &uio_pt;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
c28749e97052f09388969427adf7df641cdcdc22kais mac.cd_format = CRYPTO_DATA_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais mac.cd_offset = 0;
efe05f9ecde56550699213909fd4152ef8ef6438krishna mac.cd_raw.iov_base = (char *)digest;
efe05f9ecde56550699213909fd4152ef8ef6438krishna mac.cd_length = mac.cd_raw.iov_len = spec->mac_hashsz;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
efe05f9ecde56550699213909fd4152ef8ef6438krishna /*
efe05f9ecde56550699213909fd4152ef8ef6438krishna * The calling context can tolerate a blocking call here.
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * For outgoing traffic, we are in user context when called
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * from kssl_data_out_cb(). For incoming traffic past the
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * SSL handshake, we are in user context when called from
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * kssl_data_in_proc_cb(). During the SSL handshake, we are
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * called for client_finished message handling from a taskq
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * thread.
efe05f9ecde56550699213909fd4152ef8ef6438krishna */
efe05f9ecde56550699213909fd4152ef8ef6438krishna rv = crypto_mac(&spec->hmac_mech, &dd, &spec->hmac_key,
efe05f9ecde56550699213909fd4152ef8ef6438krishna NULL, &mac, NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(rv)) {
efe05f9ecde56550699213909fd4152ef8ef6438krishna hash_use_ok = (rv == CRYPTO_MECH_NOT_SUPPORTED &&
efe05f9ecde56550699213909fd4152ef8ef6438krishna !IS_TLS(ssl));
efe05f9ecde56550699213909fd4152ef8ef6438krishna if (!hash_use_ok) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__crypto_mac_error,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk int, rv);
efe05f9ecde56550699213909fd4152ef8ef6438krishna KSSL_COUNTER(compute_mac_failure, 1);
efe05f9ecde56550699213909fd4152ef8ef6438krishna }
c28749e97052f09388969427adf7df641cdcdc22kais }
efe05f9ecde56550699213909fd4152ef8ef6438krishna } else
efe05f9ecde56550699213909fd4152ef8ef6438krishna hash_use_ok = B_TRUE;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
efe05f9ecde56550699213909fd4152ef8ef6438krishna if (hash_use_ok) {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(&(ssl->mac_ctx[direction][0]), ctx,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk sizeof (KSSL_HASHCTX));
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, temp, p - temp);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, buf, len);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashFinal(digest, (void *)ctx);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(&(ssl->mac_ctx[direction][1]), ctx,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk sizeof (KSSL_HASHCTX));
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, digest, spec->mac_hashsz);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashFinal(digest, (void *)ctx);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (rv);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/*
c28749e97052f09388969427adf7df641cdcdc22kais * Handles handshake messages.
c28749e97052f09388969427adf7df641cdcdc22kais * Messages to be replied are returned in handshake_sendbuf.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kaisint
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_handle_handshake_message(ssl_t *ssl, mblk_t *mp, int *err,
c28749e97052f09388969427adf7df641cdcdc22kais kssl_callback_t cbfn, void *arg)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uint32_t msglen;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t msghdr[4];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->msg.state == MSG_BODY);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->msg.msglen_bytes == 3);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr >= mp->b_rptr + ssl->msg.msglen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->sslcnt++;
c28749e97052f09388969427adf7df641cdcdc22kais msglen = ssl->msg.msglen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->msg.type == client_hello) {
c28749e97052f09388969427adf7df641cdcdc22kais MD5Init(&ssl->hs_md5);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Init(&ssl->hs_sha1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->msg.type == finished && ssl->resumed == B_FALSE) {
c28749e97052f09388969427adf7df641cdcdc22kais if (kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
c28749e97052f09388969427adf7df641cdcdc22kais sender_client) != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais *err = SSL_MISS;
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->msg.type != finished || ssl->resumed == B_FALSE) {
c28749e97052f09388969427adf7df641cdcdc22kais msghdr[0] = (uchar_t)ssl->msg.type;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais msghdr[1] = (uchar_t)(msglen >> 16);
c28749e97052f09388969427adf7df641cdcdc22kais msghdr[2] = (uchar_t)(msglen >> 8);
c28749e97052f09388969427adf7df641cdcdc22kais msghdr[3] = (uchar_t)(msglen);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_update_handshake_hashes(ssl, msghdr, 4);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_update_handshake_hashes(ssl, mp->b_rptr, msglen);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->msg.state = MSG_INIT;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->msg.msglen = 0;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->msg.msglen_bytes = 0;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais switch (ssl->msg.type) {
c28749e97052f09388969427adf7df641cdcdc22kais case client_hello:
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->hs_waitstate != wait_client_hello) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal,
c28749e97052f09388969427adf7df641cdcdc22kais unexpected_message);
c28749e97052f09388969427adf7df641cdcdc22kais *err = EBADMSG;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais *err = kssl_handle_client_hello(ssl, mp, msglen);
c28749e97052f09388969427adf7df641cdcdc22kais if (*err == SSL_MISS) {
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais case client_key_exchange:
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->hs_waitstate != wait_client_key) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal,
c28749e97052f09388969427adf7df641cdcdc22kais unexpected_message);
c28749e97052f09388969427adf7df641cdcdc22kais *err = EBADMSG;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais *err = kssl_handle_client_key_exchange(ssl, mp,
c28749e97052f09388969427adf7df641cdcdc22kais msglen, cbfn, arg);
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais case finished:
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->hs_waitstate != wait_finished) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk unexpected_message);
c28749e97052f09388969427adf7df641cdcdc22kais *err = EBADMSG;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais *err = kssl_handle_finished(ssl, mp, msglen);
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais default:
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, unexpected_message);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais *err = EBADMSG;
c28749e97052f09388969427adf7df641cdcdc22kais return (1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_update_handshake_hashes(ssl_t *ssl, uchar_t *buf, uint_t len)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(&ssl->hs_md5, buf, len);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(&ssl->hs_sha1, buf, len);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_compute_handshake_hashes(
c28749e97052f09388969427adf7df641cdcdc22kais ssl_t *ssl,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3Hashes *hashes,
c28749e97052f09388969427adf7df641cdcdc22kais uint32_t sender)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais MD5_CTX md5 = ssl->hs_md5; /* clone md5 context */
c28749e97052f09388969427adf7df641cdcdc22kais SHA1_CTX sha1 = ssl->hs_sha1; /* clone sha1 context */
c28749e97052f09388969427adf7df641cdcdc22kais MD5_CTX *md5ctx = &md5;
c28749e97052f09388969427adf7df641cdcdc22kais SHA1_CTX *sha1ctx = &sha1;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t seed[MD5_HASH_LEN + SHA1_HASH_LEN];
c28749e97052f09388969427adf7df641cdcdc22kais char *label;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * Do not take another hash step here.
c28749e97052f09388969427adf7df641cdcdc22kais * Just complete the operation.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais MD5Final(hashes->md5, md5ctx);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Final(hashes->sha1, sha1ctx);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(hashes->md5, seed, MD5_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(hashes->sha1, seed + MD5_HASH_LEN, SHA1_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (sender == sender_client)
c28749e97052f09388969427adf7df641cdcdc22kais label = TLS_CLIENT_FINISHED_LABEL;
c28749e97052f09388969427adf7df641cdcdc22kais else
c28749e97052f09388969427adf7df641cdcdc22kais label = TLS_SERVER_FINISHED_LABEL;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (kssl_tls_PRF(ssl,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk ssl->sid.master_secret,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (size_t)SSL3_MASTER_SECRET_LEN,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (uchar_t *)label, strlen(label),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk seed, (size_t)(MD5_HASH_LEN + SHA1_HASH_LEN),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk hashes->tlshash, (size_t)TLS_FINISHED_SIZE));
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t s[4];
c28749e97052f09388969427adf7df641cdcdc22kais s[0] = (sender >> 24) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais s[1] = (sender >> 16) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais s[2] = (sender >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais s[3] = (sender) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, s, 4);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, ssl->sid.master_secret,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3_MASTER_SECRET_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, kssl_pad_1, SSL3_MD5_PAD_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Final(hashes->md5, md5ctx);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais MD5Init(md5ctx);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, ssl->sid.master_secret,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3_MASTER_SECRET_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, kssl_pad_2, SSL3_MD5_PAD_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, hashes->md5, MD5_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Final(hashes->md5, md5ctx);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, s, 4);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, ssl->sid.master_secret,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3_MASTER_SECRET_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, kssl_pad_1, SSL3_SHA1_PAD_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Final(hashes->sha1, sha1ctx);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Init(sha1ctx);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, ssl->sid.master_secret,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3_MASTER_SECRET_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, kssl_pad_2, SSL3_SHA1_PAD_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, hashes->sha1, SHA1_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Final(hashes->sha1, sha1ctx);
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri/*
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * Minimum message length for a client hello =
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * 2-byte client_version +
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * 32-byte random +
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * 1-byte session_id length +
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * 2-byte cipher_suites length +
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * 1-byte compression_methods length +
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * 1-byte CompressionMethod.null
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri */
c28749e97052f09388969427adf7df641cdcdc22kais#define KSSL_SSL3_CH_MIN_MSGLEN (39)
c28749e97052f09388969427adf7df641cdcdc22kais
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal/*
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * Process SSL/TLS Client Hello message. Return 0 on success, errno value
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * or SSL_MISS if no cipher suite of the server matches the list received
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * in the message.
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal */
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_handle_client_hello(ssl_t *ssl, mblk_t *mp, int msglen)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *msgend;
c28749e97052f09388969427adf7df641cdcdc22kais int err;
c28749e97052f09388969427adf7df641cdcdc22kais SSL3AlertDescription desc = illegal_parameter;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri uint_t sidlen, cslen, cmlen;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *suitesp;
c28749e97052f09388969427adf7df641cdcdc22kais uint_t i, j;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t suite, selected_suite;
c28749e97052f09388969427adf7df641cdcdc22kais int ch_msglen = KSSL_SSL3_CH_MIN_MSGLEN;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal boolean_t suite_found = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr >= mp->b_rptr + msglen);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->msg.type == client_hello);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->hs_waitstate == wait_client_hello);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->resumed == B_FALSE);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (msglen < ch_msglen) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE2(kssl_err__msglen_less_than_minimum,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal int, msglen, int, ch_msglen);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais msgend = mp->b_rptr + msglen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Support SSLv3 (version == 3.0) or TLS (version == 3.1) */
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->major_version != 3 || (ssl->major_version == 3 &&
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk ssl->minor_version != 0 && ssl->minor_version != 1)) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE2(kssl_err__SSL_version_not_supported,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk uchar_t, ssl->major_version,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk uchar_t, ssl->minor_version);
c28749e97052f09388969427adf7df641cdcdc22kais desc = handshake_failure;
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += 2; /* skip the version bytes */
c28749e97052f09388969427adf7df641cdcdc22kais
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal /* read client random field */
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(mp->b_rptr, ssl->client_random, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += SSL3_RANDOM_LENGTH;
c28749e97052f09388969427adf7df641cdcdc22kais
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal /* read session ID length */
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->sid.cached == B_FALSE);
c28749e97052f09388969427adf7df641cdcdc22kais sidlen = *mp->b_rptr++;
c28749e97052f09388969427adf7df641cdcdc22kais ch_msglen += sidlen;
c28749e97052f09388969427adf7df641cdcdc22kais if (msglen < ch_msglen) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE2(kssl_err__invalid_message_length_after_ver,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal int, msglen, int, ch_msglen);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais if (sidlen != SSL3_SESSIONID_BYTES) {
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += sidlen;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri kssl_lookup_sid(&ssl->sid, mp->b_rptr, &ssl->faddr,
c28749e97052f09388969427adf7df641cdcdc22kais ssl->kssl_entry);
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += SSL3_SESSIONID_BYTES;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal /* read cipher suite length */
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri cslen = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += 2;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri ch_msglen += cslen;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri /*
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * This check can't be a "!=" since there can be
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * compression methods other than CompressionMethod.null.
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * Also, there can be extra data (TLS extensions) after the
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * compression methods field.
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri */
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri if (msglen < ch_msglen) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE2(kssl_err__invalid_message_length_after_cslen,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal int, msglen, int, ch_msglen);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* The length has to be even since a cipher suite is 2-byte long. */
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri if (cslen & 0x1) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE1(kssl_err__uneven_cipher_suite_length,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal uint_t, cslen);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais suitesp = mp->b_rptr;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* session resumption checks */
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->sid.cached == B_TRUE) {
c28749e97052f09388969427adf7df641cdcdc22kais suite = ssl->sid.cipher_suite;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri for (j = 0; j < cslen; j += 2) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE2(kssl_cipher_suite_check_resumpt,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, suite,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (uint16_t)((suitesp[j] << 8) + suitesp[j+1]));
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check for regular (true) cipher suite. */
c28749e97052f09388969427adf7df641cdcdc22kais if (suitesp[j] == ((suite >> 8) & 0xff) &&
c28749e97052f09388969427adf7df641cdcdc22kais suitesp[j + 1] == (suite & 0xff)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE1(kssl_cipher_suite_found_resumpt,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, suite);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal suite_found = B_TRUE;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal selected_suite = suite;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check for SCSV. */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suitesp[j] == ((SSL_SCSV >> 8) & 0xff) &&
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal suitesp[j + 1] == (SSL_SCSV & 0xff)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE(kssl_scsv_found_resumpt);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->secure_renegotiation = B_TRUE;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * If we got cipher suite match and SCSV we can
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * terminate the cycle now.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suite_found && ssl->secure_renegotiation)
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal break;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suite_found)
c28749e97052f09388969427adf7df641cdcdc22kais goto suite_found;
c28749e97052f09388969427adf7df641cdcdc22kais kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check if this server is capable of the cipher suite. */
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
c28749e97052f09388969427adf7df641cdcdc22kais suite = ssl->kssl_entry->kssl_cipherSuites[i];
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri for (j = 0; j < cslen; j += 2) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE2(kssl_cipher_suite_check, uint16_t, suite,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (uint16_t)((suitesp[j] << 8) + suitesp[j+1]));
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check for regular (true) cipher suite. */
c28749e97052f09388969427adf7df641cdcdc22kais if (suitesp[j] == ((suite >> 8) & 0xff) &&
c28749e97052f09388969427adf7df641cdcdc22kais suitesp[j + 1] == (suite & 0xff)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE1(kssl_cipher_suite_found,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, suite);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal suite_found = B_TRUE;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal selected_suite = suite;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check for SCSV. */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suitesp[j] == ((SSL_SCSV >> 8) & 0xff) &&
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal suitesp[j + 1] == (SSL_SCSV & 0xff)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE(kssl_scsv_found);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->secure_renegotiation = B_TRUE;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * If we got cipher suite match and SCSV or went
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * through the whole list of client cipher suites
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * (hence we know if SCSV was present or not) we
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * can terminate the cycle now.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suite_found &&
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (ssl->secure_renegotiation || (i > 0)))
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal break;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suite_found)
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (!suite_found) {
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->sslcnt == 1) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE(kssl_no_cipher_suite_found);
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(no_suite_found, 1);
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal /*
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * If there is no fallback point terminate the
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * handshake with SSL alert otherwise return with
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * SSL_MISS.
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal */
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal if (ssl->kssl_entry->ke_fallback_head == NULL) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE(kssl_no_fallback);
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal desc = handshake_failure;
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal goto falert;
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal } else {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal return (SSL_MISS);
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais desc = handshake_failure;
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE(kssl_err__no_cipher_suites_found);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaissuite_found:
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri mp->b_rptr += cslen;
c28749e97052f09388969427adf7df641cdcdc22kais
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri /*
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * Check for the mandatory CompressionMethod.null. We do not
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * support any other compression methods.
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri */
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri cmlen = *mp->b_rptr++;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri ch_msglen += cmlen - 1; /* -1 accounts for the null method */
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri if (msglen < ch_msglen) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE2(kssl_err__invalid_message_length_after_complen,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal int, msglen, int, ch_msglen);
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri goto falert;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri }
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal /*
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * Search for null compression method (encoded as 0 byte) in the
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * compression methods field.
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal */
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri while (cmlen >= 1) {
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri if (*mp->b_rptr++ == 0)
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri break;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri cmlen--;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri }
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri if (cmlen == 0) {
c28749e97052f09388969427adf7df641cdcdc22kais desc = handshake_failure;
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE(kssl_err__no_null_compression_method);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Find the suite in the internal cipher suite table. */
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 0; i < cipher_suite_defs_nentries; i++) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (selected_suite == cipher_suite_defs[i].suite) {
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Get past the remaining compression methods (minus null method). */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_rptr += cmlen - 1;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(i < cipher_suite_defs_nentries);
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->pending_cipher_suite = selected_suite;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->pending_malg = cipher_suite_defs[i].malg;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->pending_calg = cipher_suite_defs[i].calg;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Parse TLS extensions (if any). */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ch_msglen + 2 < msglen) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Get the length of the extensions. */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t ext_total_len = ((uint_t)mp->b_rptr[0] << 8) +
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (uint_t)mp->b_rptr[1];
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE1(kssl_total_length_extensions, uint16_t,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ext_total_len);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Consider zero extensions length as invalid extension
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * encoding.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ext_total_len == 0) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE1(kssl_err__zero_extensions_length,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mblk_t *, mp);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal goto falert;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ch_msglen += 2;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ch_msglen + ext_total_len > msglen) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE2(kssl_err__invalid_extensions_length,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal int, msglen, int, ch_msglen);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal goto falert;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_rptr += 2;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Go through the TLS extensions. This is only done to check
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * for the presence of renegotiation_info extension. We do not
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * support any other TLS extensions and hence ignore them.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal while (mp->b_rptr < msgend) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t ext_len, ext_type;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Check that the extension has at least type and
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * length (2 + 2 bytes).
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ch_msglen + 4 > msglen) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE(kssl_err__invalid_ext_format);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal goto falert;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Get extension type and length */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ext_type = ((uint_t)mp->b_rptr[0] << 8) +
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (uint_t)mp->b_rptr[1];
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_rptr += 2;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ext_len = ((uint_t)mp->b_rptr[0] << 8) +
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (uint_t)mp->b_rptr[1];
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_rptr += 2;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ch_msglen += 4;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE3(kssl_ext_detected, uint16_t, ext_type,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, ext_len, mblk_t *, mp);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Make sure the contents of the extension are
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * accessible.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ch_msglen + ext_len > msglen) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE1(
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal kssl_err__invalid_ext_len,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, ext_len);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal goto falert;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal switch (ext_type) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal case TLSEXT_RENEGOTIATION_INFO:
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Search for empty "renegotiation_info"
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * extension (encoded as ff 01 00 01 00).
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE(kssl_reneg_info_found);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if ((ext_len != 1) ||
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (*mp->b_rptr != 0)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE2(
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal kssl_err__non_empty_reneg_info,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, ext_len,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mblk_t *, mp);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal goto falert;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->secure_renegotiation = B_TRUE;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal break;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal default:
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* FALLTHRU */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal break;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* jump to the next extension */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ch_msglen += ext_len;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_rptr += ext_len;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_rptr = msgend;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->sid.cached == B_TRUE) {
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_server_hello(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl))
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_generate_tls_keyblock(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais else
c28749e97052f09388969427adf7df641cdcdc22kais kssl_generate_keyblock(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_change_cipher_specs(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_finished(ssl, 1);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0)
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_compute_handshake_hashes(ssl, &ssl->hs_hashes,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk sender_client);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0)
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = wait_change_cipher;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->resumed = B_TRUE;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(resumed_sessions, 1);
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais (void) random_get_pseudo_bytes(ssl->sid.session_id,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3_SESSIONID_BYTES);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->sid.client_addr = ssl->faddr;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->sid.cipher_suite = selected_suite;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_server_hello(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_certificate_and_server_hello_done(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(full_handshakes, 1);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = wait_client_key;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisfalert:
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, desc);
c28749e97052f09388969427adf7df641cdcdc22kais return (EBADMSG);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri#define SET_HASH_INDEX(index, s, clnt_addr) { \
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri int addr; \
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri \
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri IN6_V4MAPPED_TO_IPADDR(clnt_addr, addr); \
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri index = addr ^ (((int)(s)[0] << 24) | ((int)(s)[1] << 16) | \
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri ((int)(s)[2] << 8) | (int)(s)[SSL3_SESSIONID_BYTES - 1]); \
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri}
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri/*
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri * Creates a cache entry. Sets the sid->cached flag
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri * and sid->time fields. So, the caller should not set them.
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri */
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_cache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uint_t index;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *s = sid->session_id;
c28749e97052f09388969427adf7df641cdcdc22kais kmutex_t *lock;
c28749e97052f09388969427adf7df641cdcdc22kais
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri ASSERT(sid->cached == B_FALSE);
c28749e97052f09388969427adf7df641cdcdc22kais
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri /* set the values before creating the cache entry */
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri sid->cached = B_TRUE;
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni sid->time = ddi_get_lbolt();
c28749e97052f09388969427adf7df641cdcdc22kais
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri SET_HASH_INDEX(index, s, &sid->client_addr);
c28749e97052f09388969427adf7df641cdcdc22kais index %= kssl_entry->sid_cache_nentries;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais lock = &(kssl_entry->sid_cache[index].se_lock);
c28749e97052f09388969427adf7df641cdcdc22kais mutex_enter(lock);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_entry->sid_cache[index].se_used++;
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(sid, &(kssl_entry->sid_cache[index].se_sid), sizeof (*sid));
c28749e97052f09388969427adf7df641cdcdc22kais mutex_exit(lock);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri KSSL_COUNTER(sid_cached, 1);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri}
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri/*
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri * Invalidates the cache entry, if any. Clears the sid->cached flag
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri * as a side effect.
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri */
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yendurivoid
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yendurikssl_uncache_sid(sslSessionID *sid, kssl_entry_t *kssl_entry)
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri{
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri uint_t index;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri uchar_t *s = sid->session_id;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri sslSessionID *csid;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri kmutex_t *lock;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri ASSERT(sid->cached == B_TRUE);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri sid->cached = B_FALSE;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri SET_HASH_INDEX(index, s, &sid->client_addr);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri index %= kssl_entry->sid_cache_nentries;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri lock = &(kssl_entry->sid_cache[index].se_lock);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri mutex_enter(lock);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri csid = &(kssl_entry->sid_cache[index].se_sid);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri if (!(IN6_ARE_ADDR_EQUAL(&csid->client_addr, &sid->client_addr)) ||
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri mutex_exit(lock);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri return;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri }
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri csid->cached = B_FALSE;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri mutex_exit(lock);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri KSSL_COUNTER(sid_uncached, 1);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yendurikssl_lookup_sid(sslSessionID *sid, uchar_t *s, in6_addr_t *faddr,
c28749e97052f09388969427adf7df641cdcdc22kais kssl_entry_t *kssl_entry)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uint_t index;
c28749e97052f09388969427adf7df641cdcdc22kais kmutex_t *lock;
c28749e97052f09388969427adf7df641cdcdc22kais sslSessionID *csid;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(sid_cache_lookups, 1);
c28749e97052f09388969427adf7df641cdcdc22kais
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri SET_HASH_INDEX(index, s, faddr);
c28749e97052f09388969427adf7df641cdcdc22kais index %= kssl_entry->sid_cache_nentries;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais lock = &(kssl_entry->sid_cache[index].se_lock);
c28749e97052f09388969427adf7df641cdcdc22kais mutex_enter(lock);
c28749e97052f09388969427adf7df641cdcdc22kais csid = &(kssl_entry->sid_cache[index].se_sid);
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri if (csid->cached == B_FALSE ||
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri !IN6_ARE_ADDR_EQUAL(&csid->client_addr, faddr) ||
c28749e97052f09388969427adf7df641cdcdc22kais bcmp(csid->session_id, s, SSL3_SESSIONID_BYTES)) {
c28749e97052f09388969427adf7df641cdcdc22kais mutex_exit(lock);
c28749e97052f09388969427adf7df641cdcdc22kais return;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni if (TICK_TO_SEC(ddi_get_lbolt() - csid->time) >
d3d50737e566cade9a08d73d2af95105ac7cd960Rafael Vanoni kssl_entry->sid_cache_timeout) {
c28749e97052f09388969427adf7df641cdcdc22kais csid->cached = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais mutex_exit(lock);
c28749e97052f09388969427adf7df641cdcdc22kais return;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(csid, sid, sizeof (*sid));
c28749e97052f09388969427adf7df641cdcdc22kais mutex_exit(lock);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(sid->cached == B_TRUE);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(sid_cache_hits, 1);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic uchar_t *
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_rsa_unwrap(uchar_t *buf, size_t *lenp)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais size_t len = *lenp;
c28749e97052f09388969427adf7df641cdcdc22kais int i = 2;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (buf[0] != 0 || buf[1] != 2) {
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais while (i < len) {
c28749e97052f09388969427adf7df641cdcdc22kais if (buf[i++] == 0) {
c28749e97052f09388969427adf7df641cdcdc22kais *lenp = len - i;
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (i == len) {
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (buf + i);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#define KSSL_SSL3_SH_RECLEN (74)
c28749e97052f09388969427adf7df641cdcdc22kais#define KSSL_SSL3_FIN_MSGLEN (36)
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal#define KSSL_EMPTY_RENEG_INFO_LEN (7)
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#define KSSL_SSL3_MAX_CCP_FIN_MSGLEN (128) /* comfortable upper bound */
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal/*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Send ServerHello record to the client.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_send_server_hello(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *buf;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *msgstart;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t reclen = KSSL_SSL3_SH_RECLEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp = allocb(ssl->tcp_mss, BPRI_HI);
c28749e97052f09388969427adf7df641cdcdc22kais if (mp == NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(alloc_fails, 1);
c28749e97052f09388969427adf7df641cdcdc22kais return (ENOMEM);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais ssl->handshake_sendbuf = mp;
c28749e97052f09388969427adf7df641cdcdc22kais buf = mp->b_wptr;
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ssl->secure_renegotiation)
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal reclen += KSSL_EMPTY_RENEG_INFO_LEN;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
c28749e97052f09388969427adf7df641cdcdc22kais /* 5 byte record header */
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = content_handshake;
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = ssl->major_version;
c28749e97052f09388969427adf7df641cdcdc22kais buf[2] = ssl->minor_version;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[3] = reclen >> 8;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[4] = reclen & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais buf += SSL3_HDR_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais msgstart = buf;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* 6 byte message header */
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = (uchar_t)server_hello; /* message type */
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = 0; /* message len byte 0 */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[2] = ((reclen - 4) >> 8) &
c28749e97052f09388969427adf7df641cdcdc22kais 0xff; /* message len byte 1 */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[3] = (reclen - 4) & 0xff; /* message len byte 2 */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf[4] = ssl->major_version; /* version byte 0 */
c28749e97052f09388969427adf7df641cdcdc22kais buf[5] = ssl->minor_version; /* version byte 1 */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf += 6;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kssl_get_hello_random(ssl->server_random);
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->server_random, buf, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais buf += SSL3_RANDOM_LENGTH;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = SSL3_SESSIONID_BYTES;
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->sid.session_id, buf + 1, SSL3_SESSIONID_BYTES);
c28749e97052f09388969427adf7df641cdcdc22kais buf += SSL3_SESSIONID_BYTES + 1;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = (ssl->pending_cipher_suite >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = ssl->pending_cipher_suite & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf[2] = 0; /* No compression */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf += 3;
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * Add "renegotiation_info" extension if the ClientHello message
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * contained either SCSV value in cipher suite list or
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * "renegotiation_info" extension. This is per RFC 5746, section 3.6.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ssl->secure_renegotiation) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Extensions length */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[0] = 0x00;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[1] = 0x05;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* empty renegotiation_info extension encoding (section 3.2) */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[2] = 0xff;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[3] = 0x01;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[4] = 0x00;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[5] = 0x01;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf[6] = 0x00;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf += KSSL_EMPTY_RENEG_INFO_LEN;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal mp->b_wptr = buf;
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr < mp->b_datap->db_lim);
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal kssl_update_handshake_hashes(ssl, msgstart, reclen);
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_get_hello_random(uchar_t *buf)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais timestruc_t ts;
c28749e97052f09388969427adf7df641cdcdc22kais time_t sec;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais gethrestime(&ts);
c28749e97052f09388969427adf7df641cdcdc22kais sec = ts.tv_sec;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = (sec >> 24) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = (sec >> 16) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais buf[2] = (sec >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais buf[3] = (sec) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais (void) random_get_pseudo_bytes(&buf[4], SSL3_RANDOM_LENGTH - 4);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Should this be caching? */
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_tls_P_hash(crypto_mechanism_t *mech, crypto_key_t *key,
c28749e97052f09388969427adf7df641cdcdc22kais size_t hashlen,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *label, size_t label_len,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *seed, size_t seedlen,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *data, size_t datalen)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais int rv = 0;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t A1[MAX_HASH_LEN], result[MAX_HASH_LEN];
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson int bytes_left = (int)datalen;
c28749e97052f09388969427adf7df641cdcdc22kais crypto_data_t dd, mac;
c28749e97052f09388969427adf7df641cdcdc22kais crypto_context_t ctx;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais dd.cd_format = CRYPTO_DATA_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais dd.cd_offset = 0;
c28749e97052f09388969427adf7df641cdcdc22kais mac.cd_format = CRYPTO_DATA_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais mac.cd_offset = 0;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri * A(i) = HMAC_hash(secret, seed + A(i-1));
c28749e97052f09388969427adf7df641cdcdc22kais * A(0) = seed;
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * Compute A(1):
c28749e97052f09388969427adf7df641cdcdc22kais * A(1) = HMAC_hash(secret, label + seed)
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_INIT(mech, key, &ctx);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_UPDATE(ctx, label, label_len);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_UPDATE(ctx, seed, seedlen);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_FINAL(ctx, A1, hashlen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Compute A(2) ... A(n) */
c28749e97052f09388969427adf7df641cdcdc22kais while (bytes_left > 0) {
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_INIT(mech, key, &ctx);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_UPDATE(ctx, A1, hashlen);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_UPDATE(ctx, label, label_len);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_UPDATE(ctx, seed, seedlen);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_FINAL(ctx, result, hashlen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * The A(i) value is stored in "result".
c28749e97052f09388969427adf7df641cdcdc22kais * Save the results of the MAC so it can be input to next
c28749e97052f09388969427adf7df641cdcdc22kais * iteration.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais if (bytes_left > hashlen) {
c28749e97052f09388969427adf7df641cdcdc22kais /* Store the chunk result */
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(result, data, hashlen);
c28749e97052f09388969427adf7df641cdcdc22kais data += hashlen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais bytes_left -= hashlen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Update A1 for next iteration */
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_INIT(mech, key, &ctx);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_UPDATE(ctx, A1, hashlen);
c28749e97052f09388969427adf7df641cdcdc22kais HMAC_FINAL(ctx, A1, hashlen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(result, data, bytes_left);
c28749e97052f09388969427adf7df641cdcdc22kais data += bytes_left;
c28749e97052f09388969427adf7df641cdcdc22kais bytes_left = 0;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kaisend:
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(rv)) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__crypto_mac_error, int, rv);
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(compute_mac_failure, 1);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais return (rv);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/* ARGSUSED */
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_tls_PRF(ssl_t *ssl,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *secret, size_t secret_len,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *label, size_t label_len,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *seed, size_t seed_len,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *prfresult, size_t prfresult_len)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * RFC 2246:
c28749e97052f09388969427adf7df641cdcdc22kais * PRF(secret, label, seed) = P_MD5(S1, label + seed) XOR
c28749e97052f09388969427adf7df641cdcdc22kais * P_SHA1(S2, label + seed);
c28749e97052f09388969427adf7df641cdcdc22kais * S1 = 1st half of secret.
c28749e97052f09388969427adf7df641cdcdc22kais * S1 = 2nd half of secret.
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri int rv, i;
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna uchar_t psha1[MAX_KEYBLOCK_LENGTH];
c28749e97052f09388969427adf7df641cdcdc22kais crypto_key_t S1, S2;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* length of secret keys is ceil(length/2) */
c28749e97052f09388969427adf7df641cdcdc22kais size_t slen = roundup(secret_len, 2) / 2;
c28749e97052f09388969427adf7df641cdcdc22kais
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna if (prfresult_len > MAX_KEYBLOCK_LENGTH) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__unexpected_keyblock_size,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk size_t, prfresult_len);
c28749e97052f09388969427adf7df641cdcdc22kais return (CRYPTO_ARGUMENTS_BAD);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(prfresult != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(label != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(seed != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais S1.ck_data = secret;
c28749e97052f09388969427adf7df641cdcdc22kais S1.ck_length = slen * 8; /* bits */
c28749e97052f09388969427adf7df641cdcdc22kais S1.ck_format = CRYPTO_KEY_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais S2.ck_data = secret + slen;
c28749e97052f09388969427adf7df641cdcdc22kais S2.ck_length = slen * 8; /* bits */
c28749e97052f09388969427adf7df641cdcdc22kais S2.ck_format = CRYPTO_KEY_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais rv = kssl_tls_P_hash(&hmac_md5_mech, &S1, MD5_HASH_LEN,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk label, label_len,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk seed, seed_len,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk prfresult, prfresult_len);
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(rv))
c28749e97052f09388969427adf7df641cdcdc22kais goto end;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais rv = kssl_tls_P_hash(&hmac_sha1_mech, &S2, SHA1_HASH_LEN,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk label, label_len,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk seed, seed_len,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk psha1, prfresult_len);
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(rv))
c28749e97052f09388969427adf7df641cdcdc22kais goto end;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 0; i < prfresult_len; i++)
c28749e97052f09388969427adf7df641cdcdc22kais prfresult[i] ^= psha1[i];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisend:
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(rv))
c28749e97052f09388969427adf7df641cdcdc22kais bzero(prfresult, prfresult_len);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (rv);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
968d6dde54d2efa62910a3cf36438325d0b69031krishna#define IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl) \
968d6dde54d2efa62910a3cf36438325d0b69031krishna (pms == NULL || pmslen != SSL3_PRE_MASTER_SECRET_LEN || \
968d6dde54d2efa62910a3cf36438325d0b69031krishna pms[0] != ssl->major_version || pms[1] != ssl->minor_version)
968d6dde54d2efa62910a3cf36438325d0b69031krishna
968d6dde54d2efa62910a3cf36438325d0b69031krishna#define FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf) { \
968d6dde54d2efa62910a3cf36438325d0b69031krishna KSSL_COUNTER(bad_pre_master_secret, 1); \
968d6dde54d2efa62910a3cf36438325d0b69031krishna pms = buf; \
968d6dde54d2efa62910a3cf36438325d0b69031krishna pmslen = SSL3_PRE_MASTER_SECRET_LEN; \
968d6dde54d2efa62910a3cf36438325d0b69031krishna pms[0] = ssl->major_version; \
968d6dde54d2efa62910a3cf36438325d0b69031krishna pms[1] = ssl->minor_version; \
968d6dde54d2efa62910a3cf36438325d0b69031krishna (void) random_get_pseudo_bytes(&buf[2], pmslen - 2); \
968d6dde54d2efa62910a3cf36438325d0b69031krishna}
968d6dde54d2efa62910a3cf36438325d0b69031krishna
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_generate_tls_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
c28749e97052f09388969427adf7df641cdcdc22kais{
968d6dde54d2efa62910a3cf36438325d0b69031krishna uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t seed[SSL3_RANDOM_LENGTH * 2];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * Computing the master secret:
c28749e97052f09388969427adf7df641cdcdc22kais * ----------------------------
c28749e97052f09388969427adf7df641cdcdc22kais * master_secret = PRF (pms, "master secret",
c28749e97052f09388969427adf7df641cdcdc22kais * ClientHello.random + ServerHello.random);
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->client_random, seed, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->server_random, seed + SSL3_RANDOM_LENGTH,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais
968d6dde54d2efa62910a3cf36438325d0b69031krishna /* if pms is bad fake it to thwart Bleichenbacher attack */
968d6dde54d2efa62910a3cf36438325d0b69031krishna if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE(kssl_err__under_Bleichenbacher_attack);
968d6dde54d2efa62910a3cf36438325d0b69031krishna FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
968d6dde54d2efa62910a3cf36438325d0b69031krishna }
968d6dde54d2efa62910a3cf36438325d0b69031krishna
c28749e97052f09388969427adf7df641cdcdc22kais return (kssl_tls_PRF(ssl,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk pms, pmslen,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (uchar_t *)TLS_MASTER_SECRET_LABEL,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (size_t)strlen(TLS_MASTER_SECRET_LABEL),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk seed, sizeof (seed),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk ssl->sid.master_secret,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (size_t)sizeof (ssl->sid.master_secret)));
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
968d6dde54d2efa62910a3cf36438325d0b69031krishna
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_generate_ssl_ms(ssl_t *ssl, uchar_t *pms, size_t pmslen)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t buf[SSL3_PRE_MASTER_SECRET_LEN];
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *ms;
c28749e97052f09388969427adf7df641cdcdc22kais int hlen = MD5_HASH_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ms = ssl->sid.master_secret;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* if pms is bad fake it to thwart Bleichenbacher attack */
968d6dde54d2efa62910a3cf36438325d0b69031krishna if (IS_BAD_PRE_MASTER_SECRET(pms, pmslen, ssl)) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE(kssl_err__under_Bleichenbacher_attack);
968d6dde54d2efa62910a3cf36438325d0b69031krishna FAKE_PRE_MASTER_SECRET(pms, pmslen, ssl, buf);
c28749e97052f09388969427adf7df641cdcdc22kais }
968d6dde54d2efa62910a3cf36438325d0b69031krishna
c28749e97052f09388969427adf7df641cdcdc22kais kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 1, ms, 0);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 2, ms + hlen, 0);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_ssl3_key_material_derive_step(ssl, pms, pmslen, 3, ms + 2 * hlen,
c28749e97052f09388969427adf7df641cdcdc22kais 0);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_generate_tls_keyblock(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t seed[2 * SSL3_RANDOM_LENGTH];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->server_random, seed, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->client_random, seed + SSL3_RANDOM_LENGTH,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (kssl_tls_PRF(ssl, ssl->sid.master_secret,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (size_t)SSL3_MASTER_SECRET_LEN,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (uchar_t *)TLS_KEY_EXPANSION_LABEL,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (size_t)strlen(TLS_KEY_EXPANSION_LABEL),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk seed, (size_t)sizeof (seed),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk ssl->pending_keyblock,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk (size_t)ssl->pending_keyblksz));
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_generate_keyblock(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *ms;
c28749e97052f09388969427adf7df641cdcdc22kais size_t mslen = SSL3_MASTER_SECRET_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais int hlen = MD5_HASH_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *keys = ssl->pending_keyblock;
c28749e97052f09388969427adf7df641cdcdc22kais int steps = howmany(ssl->pending_keyblksz, hlen);
c28749e97052f09388969427adf7df641cdcdc22kais int i;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ms = ssl->sid.master_secret;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(hlen * steps <= MAX_KEYBLOCK_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 1; i <= steps; i++) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_ssl3_key_material_derive_step(ssl, ms, mslen, i, keys, 1);
c28749e97052f09388969427adf7df641cdcdc22kais keys += hlen;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishnastatic char *ssl3_key_derive_seeds[9] = {"A", "BB", "CCC", "DDDD", "EEEEE",
2bd70d4be73561631df9cb3d9eb4c65fa94fa665krishna "FFFFFF", "GGGGGGG", "HHHHHHHH", "IIIIIIIII"};
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_ssl3_key_material_derive_step(
c28749e97052f09388969427adf7df641cdcdc22kais ssl_t *ssl,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *secret,
c28749e97052f09388969427adf7df641cdcdc22kais size_t secretlen,
c28749e97052f09388969427adf7df641cdcdc22kais int step,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *dst,
c28749e97052f09388969427adf7df641cdcdc22kais int sr_first)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais SHA1_CTX sha1, *sha1ctx;
c28749e97052f09388969427adf7df641cdcdc22kais MD5_CTX md5, *md5ctx;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t sha1_hash[SHA1_HASH_LEN];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais sha1ctx = &sha1;
c28749e97052f09388969427adf7df641cdcdc22kais md5ctx = &md5;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(step <=
c28749e97052f09388969427adf7df641cdcdc22kais sizeof (ssl3_key_derive_seeds) /
c28749e97052f09388969427adf7df641cdcdc22kais sizeof (ssl3_key_derive_seeds[0]));
c28749e97052f09388969427adf7df641cdcdc22kais step--;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Init(sha1ctx);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, (uchar_t *)ssl3_key_derive_seeds[step],
c28749e97052f09388969427adf7df641cdcdc22kais step + 1);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, secret, secretlen);
c28749e97052f09388969427adf7df641cdcdc22kais if (sr_first) {
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, ssl->client_random, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Update(sha1ctx, ssl->server_random, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Final(sha1_hash, sha1ctx);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais MD5Init(md5ctx);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, secret, secretlen);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Update(md5ctx, sha1_hash, SHA1_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais MD5Final(dst, md5ctx);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_send_certificate_and_server_hello_done(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais int cur_reclen;
c28749e97052f09388969427adf7df641cdcdc22kais int mss;
c28749e97052f09388969427adf7df641cdcdc22kais int len, copylen;
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *cert_buf;
c28749e97052f09388969427adf7df641cdcdc22kais int cert_len;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *msgbuf;
c28749e97052f09388969427adf7df641cdcdc22kais Certificate_t *cert;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t reclen = KSSL_SSL3_SH_RECLEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais cert = ssl->kssl_entry->ke_server_certificate;
c28749e97052f09388969427adf7df641cdcdc22kais if (cert == NULL) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk return (ENOENT);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais cert_buf = cert->msg;
c28749e97052f09388969427adf7df641cdcdc22kais cert_len = cert->len;
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ssl->secure_renegotiation)
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal reclen += KSSL_EMPTY_RENEG_INFO_LEN;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
c28749e97052f09388969427adf7df641cdcdc22kais mp = ssl->handshake_sendbuf;
c28749e97052f09388969427adf7df641cdcdc22kais mss = ssl->tcp_mss;
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais cur_reclen = mp->b_wptr - mp->b_rptr - SSL3_HDR_LEN;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ASSERT(cur_reclen == reclen);
c28749e97052f09388969427adf7df641cdcdc22kais /* Assume MSS is at least 80 bytes */
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mss > cur_reclen + SSL3_HDR_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(cur_reclen < SSL3_MAX_RECORD_LENGTH); /* XXX */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais copylen = mss - (cur_reclen + SSL3_HDR_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais len = cert_len;
c28749e97052f09388969427adf7df641cdcdc22kais copylen = MIN(copylen, len);
c28749e97052f09388969427adf7df641cdcdc22kais copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* new record always starts in a new mblk for simplicity */
c28749e97052f09388969427adf7df641cdcdc22kais msgbuf = cert_buf;
c28749e97052f09388969427adf7df641cdcdc22kais for (;;) {
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr + copylen <= mp->b_datap->db_lim);
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(msgbuf, mp->b_wptr, copylen);
c28749e97052f09388969427adf7df641cdcdc22kais msgbuf += copylen;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr += copylen;
c28749e97052f09388969427adf7df641cdcdc22kais cur_reclen += copylen;
c28749e97052f09388969427adf7df641cdcdc22kais len -= copylen;
c28749e97052f09388969427adf7df641cdcdc22kais if (len == 0) {
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais if (cur_reclen == SSL3_MAX_RECORD_LENGTH) {
c28749e97052f09388969427adf7df641cdcdc22kais cur_reclen = 0;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais copylen = MIN(len, mss);
c28749e97052f09388969427adf7df641cdcdc22kais copylen = MIN(copylen, SSL3_MAX_RECORD_LENGTH - cur_reclen);
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_cont = allocb(copylen, BPRI_HI);
c28749e97052f09388969427adf7df641cdcdc22kais if (mp->b_cont == NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(alloc_fails, 1);
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(ssl->handshake_sendbuf);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->handshake_sendbuf = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais return (ENOMEM);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mp = mp->b_cont;
c28749e97052f09388969427adf7df641cdcdc22kais if (cur_reclen == 0) {
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr[0] = content_handshake;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr[1] = ssl->major_version;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr[2] = ssl->minor_version;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal cur_reclen = MIN(len, reclen);
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr[3] = (cur_reclen >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr[4] = (cur_reclen) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr += SSL3_HDR_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais cur_reclen = 0;
c28749e97052f09388969427adf7df641cdcdc22kais copylen = MIN(copylen, mss - SSL3_HDR_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* adjust the record length field for the first record */
c28749e97052f09388969427adf7df641cdcdc22kais mp = ssl->handshake_sendbuf;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal cur_reclen = MIN(reclen + cert_len, SSL3_MAX_RECORD_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr[3] = (cur_reclen >> 8) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr[4] = (cur_reclen) & 0xff;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kssl_update_handshake_hashes(ssl, cert_buf, cert_len);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_send_change_cipher_specs(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp, *newmp;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *buf;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp = ssl->handshake_sendbuf;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* We're most likely to hit the fast path for resumed sessions */
c28749e97052f09388969427adf7df641cdcdc22kais if ((mp != NULL) &&
c28749e97052f09388969427adf7df641cdcdc22kais (mp->b_datap->db_lim - mp->b_wptr > KSSL_SSL3_MAX_CCP_FIN_MSGLEN)) {
c28749e97052f09388969427adf7df641cdcdc22kais buf = mp->b_wptr;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais newmp = allocb(KSSL_SSL3_MAX_CCP_FIN_MSGLEN, BPRI_HI);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (newmp == NULL)
c28749e97052f09388969427adf7df641cdcdc22kais return (ENOMEM); /* need to do better job! */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (mp == NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais ssl->handshake_sendbuf = newmp;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais linkb(ssl->handshake_sendbuf, newmp);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mp = newmp;
c28749e97052f09388969427adf7df641cdcdc22kais buf = mp->b_rptr;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* 5 byte record header */
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = content_change_cipher_spec;
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = ssl->major_version;
c28749e97052f09388969427adf7df641cdcdc22kais buf[2] = ssl->minor_version;
c28749e97052f09388969427adf7df641cdcdc22kais buf[3] = 0;
c28749e97052f09388969427adf7df641cdcdc22kais buf[4] = 1;
c28749e97052f09388969427adf7df641cdcdc22kais buf += SSL3_HDR_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = 1;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr = buf + 1;
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr < mp->b_datap->db_lim);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->seq_num[KSSL_WRITE] = 0;
c28749e97052f09388969427adf7df641cdcdc22kais return (kssl_spec_init(ssl, KSSL_WRITE));
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisint
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_spec_init(ssl_t *ssl, int dir)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_HASHCTX *ctx;
c28749e97052f09388969427adf7df641cdcdc22kais KSSLCipherSpec *spec = &ssl->spec[dir];
c28749e97052f09388969427adf7df641cdcdc22kais int ret = 0;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec->mac_hashsz = mac_defs[ssl->pending_malg].hashsz;
c28749e97052f09388969427adf7df641cdcdc22kais spec->mac_padsz = mac_defs[ssl->pending_malg].padsz;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashInit = mac_defs[ssl->pending_malg].HashInit;
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate = mac_defs[ssl->pending_malg].HashUpdate;
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashFinal = mac_defs[ssl->pending_malg].HashFinal;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (dir == KSSL_READ) {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->pending_keyblock, ssl->mac_secret[dir],
c28749e97052f09388969427adf7df641cdcdc22kais spec->mac_hashsz);
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(&(ssl->pending_keyblock[spec->mac_hashsz]),
c28749e97052f09388969427adf7df641cdcdc22kais ssl->mac_secret[dir], spec->mac_hashsz);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Pre-compute these here. will save cycles on each record later */
c28749e97052f09388969427adf7df641cdcdc22kais if (!IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais ctx = &ssl->mac_ctx[dir][0];
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashInit((void *)ctx);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
c28749e97052f09388969427adf7df641cdcdc22kais spec->mac_hashsz);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, kssl_pad_1,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk spec->mac_padsz);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ctx = &ssl->mac_ctx[dir][1];
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashInit((void *)ctx);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, ssl->mac_secret[dir],
c28749e97052f09388969427adf7df641cdcdc22kais spec->mac_hashsz);
c28749e97052f09388969427adf7df641cdcdc22kais spec->MAC_HashUpdate((void *)ctx, kssl_pad_2,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk spec->mac_padsz);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_type = cipher_defs[ssl->pending_calg].type;
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_mech.cm_type = cipher_defs[ssl->pending_calg].mech_type;
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_bsize = cipher_defs[ssl->pending_calg].bsize;
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_keysz = cipher_defs[ssl->pending_calg].keysz;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->cipher_ctx != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais crypto_cancel_ctx(spec->cipher_ctx);
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_ctx = 0;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
efe05f9ecde56550699213909fd4152ef8ef6438krishna * Initialize HMAC keys for TLS and SSL3 HMAC keys
efe05f9ecde56550699213909fd4152ef8ef6438krishna * for SSL 3.0.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->pending_malg == mac_md5) {
c28749e97052f09388969427adf7df641cdcdc22kais spec->hmac_mech = hmac_md5_mech;
c28749e97052f09388969427adf7df641cdcdc22kais } else if (ssl->pending_malg == mac_sha) {
c28749e97052f09388969427adf7df641cdcdc22kais spec->hmac_mech = hmac_sha1_mech;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_key.ck_data = ssl->mac_secret[dir];
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_key.ck_length = spec->mac_hashsz * 8;
efe05f9ecde56550699213909fd4152ef8ef6438krishna } else {
efe05f9ecde56550699213909fd4152ef8ef6438krishna static uint32_t param;
efe05f9ecde56550699213909fd4152ef8ef6438krishna
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_mech.cm_type = CRYPTO_MECH_INVALID;
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_mech.cm_param = (caddr_t)&param;
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_mech.cm_param_len = sizeof (param);
efe05f9ecde56550699213909fd4152ef8ef6438krishna if (ssl->pending_malg == mac_md5) {
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_mech.cm_type =
efe05f9ecde56550699213909fd4152ef8ef6438krishna crypto_mech2id("CKM_SSL3_MD5_MAC");
efe05f9ecde56550699213909fd4152ef8ef6438krishna param = MD5_HASH_LEN;
efe05f9ecde56550699213909fd4152ef8ef6438krishna } else if (ssl->pending_malg == mac_sha) {
efe05f9ecde56550699213909fd4152ef8ef6438krishna spec->hmac_mech.cm_type =
efe05f9ecde56550699213909fd4152ef8ef6438krishna crypto_mech2id("CKM_SSL3_SHA1_MAC");
efe05f9ecde56550699213909fd4152ef8ef6438krishna param = SHA1_HASH_LEN;
efe05f9ecde56550699213909fd4152ef8ef6438krishna }
efe05f9ecde56550699213909fd4152ef8ef6438krishna
c28749e97052f09388969427adf7df641cdcdc22kais spec->hmac_key.ck_format = CRYPTO_KEY_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais spec->hmac_key.ck_data = ssl->mac_secret[dir];
c28749e97052f09388969427adf7df641cdcdc22kais spec->hmac_key.ck_length = spec->mac_hashsz * 8;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* We're done if this is the nil cipher */
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->cipher_keysz == 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Initialize the key and the active context */
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_key.ck_format = CRYPTO_KEY_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_key.ck_length = 8 * spec->cipher_keysz; /* in bits */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (cipher_defs[ssl->pending_calg].bsize > 0) {
c28749e97052f09388969427adf7df641cdcdc22kais /* client_write_IV */
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_mech.cm_param =
c28749e97052f09388969427adf7df641cdcdc22kais (caddr_t)&(ssl->pending_keyblock[2 * spec->mac_hashsz +
c28749e97052f09388969427adf7df641cdcdc22kais 2 * spec->cipher_keysz]);
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_mech.cm_param_len = spec->cipher_bsize;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_data.cd_format = CRYPTO_DATA_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais if (dir == KSSL_READ) {
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_mech.cm_param_len =
c28749e97052f09388969427adf7df641cdcdc22kais cipher_defs[ssl->pending_calg].bsize;
c28749e97052f09388969427adf7df641cdcdc22kais
c892ebf1bef94f4f922f282c11516677c134dbe0krishna /* client_write_key */
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_key.ck_data =
c28749e97052f09388969427adf7df641cdcdc22kais &(ssl->pending_keyblock[2 * spec->mac_hashsz]);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ret = crypto_decrypt_init(&(spec->cipher_mech),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(ret)) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__crypto_decrypt_init_read,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk int, ret);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais if (cipher_defs[ssl->pending_calg].bsize > 0) {
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri /* server_write_IV */
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_mech.cm_param += spec->cipher_bsize;
c28749e97052f09388969427adf7df641cdcdc22kais }
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri
c28749e97052f09388969427adf7df641cdcdc22kais /* server_write_key */
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_key.ck_data =
c28749e97052f09388969427adf7df641cdcdc22kais &(ssl->pending_keyblock[2 * spec->mac_hashsz +
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_keysz]);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ret = crypto_encrypt_init(&(spec->cipher_mech),
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk &(spec->cipher_key), NULL, &spec->cipher_ctx, NULL);
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(ret))
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__crypto_encrypt_init_non_read,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk int, ret);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais return (ret);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_send_finished(ssl_t *ssl, int update_hsh)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *buf;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *rstart;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *versionp;
c28749e97052f09388969427adf7df641cdcdc22kais SSL3Hashes ssl3hashes;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson uchar_t finish_len;
2ec7cc7fc084163eaed884efee9bbd322cc8951bKrishna Yenduri int ret;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t adj_len = 0;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp = ssl->handshake_sendbuf;
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais buf = mp->b_wptr;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (ssl->secure_renegotiation)
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal adj_len = KSSL_EMPTY_RENEG_INFO_LEN;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * It should be either a message with Server Hello record or just plain
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * SSL header (data packet).
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ASSERT(buf - mp->b_rptr ==
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal SSL3_HDR_LEN + KSSL_SSL3_SH_RECLEN + SSL3_HDR_LEN + 1 + adj_len ||
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal buf - mp->b_rptr == SSL3_HDR_LEN + 1);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais rstart = buf;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl))
c28749e97052f09388969427adf7df641cdcdc22kais finish_len = TLS_FINISHED_SIZE;
c28749e97052f09388969427adf7df641cdcdc22kais else
c28749e97052f09388969427adf7df641cdcdc22kais finish_len = KSSL_SSL3_FIN_MSGLEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* 5 byte record header */
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = content_handshake;
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = ssl->major_version;
c28749e97052f09388969427adf7df641cdcdc22kais buf[2] = ssl->minor_version;
c28749e97052f09388969427adf7df641cdcdc22kais buf[3] = 0;
c28749e97052f09388969427adf7df641cdcdc22kais buf[4] = 4 + finish_len;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais versionp = &buf[1];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais buf += SSL3_HDR_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* 4 byte message header */
c28749e97052f09388969427adf7df641cdcdc22kais buf[0] = (uchar_t)finished; /* message type */
c28749e97052f09388969427adf7df641cdcdc22kais buf[1] = 0; /* message len byte 0 */
c28749e97052f09388969427adf7df641cdcdc22kais buf[2] = 0; /* message len byte 1 */
c28749e97052f09388969427adf7df641cdcdc22kais buf[3] = finish_len; /* message len byte 2 */
c28749e97052f09388969427adf7df641cdcdc22kais buf += 4;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->hs_hashes.md5, ssl3hashes.md5,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk sizeof (ssl3hashes.md5));
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl->hs_hashes.sha1, ssl3hashes.sha1,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk sizeof (ssl3hashes.sha1));
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Compute hashes for the SENDER side */
c28749e97052f09388969427adf7df641cdcdc22kais ret = kssl_compute_handshake_hashes(ssl, &ssl3hashes, sender_server);
c28749e97052f09388969427adf7df641cdcdc22kais if (ret != 0)
c28749e97052f09388969427adf7df641cdcdc22kais return (ret);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl3hashes.tlshash, buf, sizeof (ssl3hashes.tlshash));
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl3hashes.md5, buf, MD5_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(ssl3hashes.sha1, buf + MD5_HASH_LEN, SHA1_HASH_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (update_hsh) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_update_handshake_hashes(ssl, buf - 4, finish_len + 4);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr = buf + finish_len;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ret = kssl_mac_encrypt_record(ssl, content_handshake, versionp,
c28749e97052f09388969427adf7df641cdcdc22kais rstart, mp);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr <= mp->b_datap->db_lim);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (ret);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisint
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_mac_encrypt_record(ssl_t *ssl,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3ContentType ct,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *versionp,
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *rstart,
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais KSSLCipherSpec *spec;
c28749e97052f09388969427adf7df641cdcdc22kais int mac_sz;
c28749e97052f09388969427adf7df641cdcdc22kais int ret = 0;
c28749e97052f09388969427adf7df641cdcdc22kais uint16_t rec_sz;
c28749e97052f09388969427adf7df641cdcdc22kais int pad_sz;
c28749e97052f09388969427adf7df641cdcdc22kais int i;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(rstart >= mp->b_rptr);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(rstart < mp->b_wptr);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec = &ssl->spec[KSSL_WRITE];
c28749e97052f09388969427adf7df641cdcdc22kais mac_sz = spec->mac_hashsz;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais rec_sz = (mp->b_wptr - rstart) - SSL3_HDR_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(rec_sz > 0);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (mac_sz != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr + mac_sz <= mp->b_datap->db_lim);
c28749e97052f09388969427adf7df641cdcdc22kais ret = kssl_compute_record_mac(ssl, KSSL_WRITE,
c28749e97052f09388969427adf7df641cdcdc22kais ssl->seq_num[KSSL_WRITE], ct, versionp,
c28749e97052f09388969427adf7df641cdcdc22kais rstart + SSL3_HDR_LEN, rec_sz, mp->b_wptr);
c28749e97052f09388969427adf7df641cdcdc22kais if (ret == CRYPTO_SUCCESS) {
c28749e97052f09388969427adf7df641cdcdc22kais ssl->seq_num[KSSL_WRITE]++;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr += mac_sz;
c28749e97052f09388969427adf7df641cdcdc22kais rec_sz += mac_sz;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais return (ret);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->cipher_type == type_block) {
c28749e97052f09388969427adf7df641cdcdc22kais pad_sz = spec->cipher_bsize -
c28749e97052f09388969427adf7df641cdcdc22kais (rec_sz & (spec->cipher_bsize - 1));
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr + pad_sz <= mp->b_datap->db_lim);
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 0; i < pad_sz; i++) {
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr[i] = pad_sz - 1;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_wptr += pad_sz;
c28749e97052f09388969427adf7df641cdcdc22kais rec_sz += pad_sz;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(rec_sz <= SSL3_MAX_RECORD_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais U16_TO_BE16(rec_sz, rstart + 3);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->cipher_ctx == 0)
c28749e97052f09388969427adf7df641cdcdc22kais return (ret);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_data.cd_length = rec_sz;
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_data.cd_raw.iov_base = (char *)(rstart + SSL3_HDR_LEN);
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_data.cd_raw.iov_len = rec_sz;
c28749e97052f09388969427adf7df641cdcdc22kais /* One record at a time. Otherwise, gotta allocate the crypt_data_t */
c28749e97052f09388969427adf7df641cdcdc22kais ret = crypto_encrypt_update(spec->cipher_ctx, &spec->cipher_data,
c28749e97052f09388969427adf7df641cdcdc22kais NULL, NULL);
c28749e97052f09388969427adf7df641cdcdc22kais if (CRYPTO_ERR(ret)) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__crypto_encrypt_update,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk int, ret);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais return (ret);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal/*
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal * Produce SSL alert message (SSLv3/TLS) or error message (SSLv2). For SSLv2
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal * it is only done to tear down the SSL connection so it has fixed encoding.
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal */
c28749e97052f09388969427adf7df641cdcdc22kaisvoid
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_send_alert(ssl_t *ssl, SSL3AlertLevel level, SSL3AlertDescription desc)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *buf;
c28749e97052f09388969427adf7df641cdcdc22kais KSSLCipherSpec *spec;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal size_t len;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->sendalert_level = level;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->sendalert_desc = desc;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (level == alert_fatal) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE2(kssl_sending_alert,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk SSL3AlertLevel, level, SSL3AlertDescription, desc);
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->sid.cached == B_TRUE) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_uncache_sid(&ssl->sid, ssl->kssl_entry);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais ssl->fatal_alert = B_TRUE;
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(fatal_alerts, 1);
c28749e97052f09388969427adf7df641cdcdc22kais } else
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(warning_alerts, 1);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec = &ssl->spec[KSSL_WRITE];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->alert_sendbuf == NULL);
9b1bd49f83497d7b339a684a1a76de3aaccf5269Vladimir Kotal if (ssl->major_version == 0x03) {
9b1bd49f83497d7b339a684a1a76de3aaccf5269Vladimir Kotal len = SSL3_HDR_LEN + SSL3_ALERT_LEN;
9b1bd49f83497d7b339a684a1a76de3aaccf5269Vladimir Kotal } else {
9b1bd49f83497d7b339a684a1a76de3aaccf5269Vladimir Kotal /* KSSL generates 5 byte SSLv2 alert messages only. */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal len = 5;
9b1bd49f83497d7b339a684a1a76de3aaccf5269Vladimir Kotal }
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal ssl->alert_sendbuf = mp = allocb(len + spec->mac_hashsz +
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_bsize, BPRI_HI);
c28749e97052f09388969427adf7df641cdcdc22kais if (mp == NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(alloc_fails, 1);
c28749e97052f09388969427adf7df641cdcdc22kais return;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais buf = mp->b_wptr;
c28749e97052f09388969427adf7df641cdcdc22kais
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* SSLv3/TLS */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal if (ssl->major_version == 0x03) {
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* 5 byte record header */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[0] = content_alert;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[1] = ssl->major_version;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[2] = ssl->minor_version;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[3] = 0;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[4] = 2;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf += SSL3_HDR_LEN;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* alert contents */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[0] = (uchar_t)level;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[1] = (uchar_t)desc;
9b1bd49f83497d7b339a684a1a76de3aaccf5269Vladimir Kotal buf += SSL3_ALERT_LEN;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal } else {
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* SSLv2 has different encoding. */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* 2-byte encoding of the length */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[0] = 0x80;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[1] = 0x03;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf += 2;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* Protocol Message Code = Error */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[0] = 0;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal /* Error Message Code = Undefined Error */
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[1] = 0;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf[2] = 0;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal buf += 3;
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal }
c28749e97052f09388969427adf7df641cdcdc22kais
7dd0d8ffa6288391fcbac80fa5deeb770d202cb8Vladimir Kotal mp->b_wptr = buf;
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/* Assumes RSA encryption */
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_handle_client_key_exchange(ssl_t *ssl, mblk_t *mp, int msglen,
c28749e97052f09388969427adf7df641cdcdc22kais kssl_callback_t cbfn, void *arg)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais char *buf;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *pms;
c28749e97052f09388969427adf7df641cdcdc22kais size_t pmslen;
c28749e97052f09388969427adf7df641cdcdc22kais int allocated;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna int err, rverr = ENOMEM;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna kssl_entry_t *ep;
c28749e97052f09388969427adf7df641cdcdc22kais crypto_key_t *privkey;
c28749e97052f09388969427adf7df641cdcdc22kais crypto_data_t *wrapped_pms_data, *pms_data;
c28749e97052f09388969427adf7df641cdcdc22kais crypto_call_req_t creq, *creqp;
c28749e97052f09388969427adf7df641cdcdc22kais
c892ebf1bef94f4f922f282c11516677c134dbe0krishna ep = ssl->kssl_entry;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna privkey = ep->ke_private_key;
c28749e97052f09388969427adf7df641cdcdc22kais if (privkey == NULL) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna return (ENOENT);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->msg.type == client_key_exchange);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->hs_waitstate == wait_client_key);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * TLS adds an extra 2 byte length field before the data.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais msglen = (mp->b_rptr[0] << 8) | mp->b_rptr[1];
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += 2;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * Allocate all we need in one shot. about 300 bytes total, for
c28749e97052f09388969427adf7df641cdcdc22kais * 1024 bit RSA modulus.
c28749e97052f09388969427adf7df641cdcdc22kais * The buffer layout will be: pms_data, wrapped_pms_data, the
c28749e97052f09388969427adf7df641cdcdc22kais * value of the wrapped pms from the client, then room for the
c28749e97052f09388969427adf7df641cdcdc22kais * resulting decrypted premaster secret.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais allocated = 2 * (sizeof (crypto_data_t) + msglen);
c28749e97052f09388969427adf7df641cdcdc22kais buf = kmem_alloc(allocated, KM_NOSLEEP);
c28749e97052f09388969427adf7df641cdcdc22kais if (buf == NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais return (ENOMEM);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais pms_data = (crypto_data_t *)buf;
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data = &(((crypto_data_t *)buf)[1]);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data->cd_format = pms_data->cd_format = CRYPTO_DATA_RAW;
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data->cd_offset = pms_data->cd_offset = 0;
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data->cd_length = pms_data->cd_length = msglen;
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data->cd_miscdata = pms_data->cd_miscdata = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data->cd_raw.iov_len = pms_data->cd_raw.iov_len = msglen;
c28749e97052f09388969427adf7df641cdcdc22kais wrapped_pms_data->cd_raw.iov_base = buf + 2 * sizeof (crypto_data_t);
c28749e97052f09388969427adf7df641cdcdc22kais pms_data->cd_raw.iov_base = wrapped_pms_data->cd_raw.iov_base + msglen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(mp->b_rptr, wrapped_pms_data->cd_raw.iov_base, msglen);
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += msglen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Proceed synchronously if out of interrupt and configured to do so */
c28749e97052f09388969427adf7df641cdcdc22kais if ((kssl_synchronous) && (!servicing_interrupt())) {
c28749e97052f09388969427adf7df641cdcdc22kais creqp = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais ssl->cke_callback_func = cbfn;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->cke_callback_arg = arg;
c28749e97052f09388969427adf7df641cdcdc22kais creq.cr_flag = kssl_call_flag;
c28749e97052f09388969427adf7df641cdcdc22kais creq.cr_callback_func = kssl_cke_done;
c28749e97052f09388969427adf7df641cdcdc22kais creq.cr_callback_arg = ssl;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais creqp = &creq;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c892ebf1bef94f4f922f282c11516677c134dbe0krishna if (ep->ke_is_nxkey) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna kssl_session_info_t *s;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna
c892ebf1bef94f4f922f282c11516677c134dbe0krishna s = ep->ke_sessinfo;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna err = CRYPTO_SUCCESS;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna if (!s->is_valid_handle) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna /* Reauthenticate to the provider */
c892ebf1bef94f4f922f282c11516677c134dbe0krishna if (s->do_reauth) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna err = kssl_get_obj_handle(ep);
c892ebf1bef94f4f922f282c11516677c134dbe0krishna if (err == CRYPTO_SUCCESS) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna s->is_valid_handle = B_TRUE;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna s->do_reauth = B_FALSE;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna }
c892ebf1bef94f4f922f282c11516677c134dbe0krishna } else
c892ebf1bef94f4f922f282c11516677c134dbe0krishna err = CRYPTO_FAILED;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna }
c892ebf1bef94f4f922f282c11516677c134dbe0krishna
c892ebf1bef94f4f922f282c11516677c134dbe0krishna if (err == CRYPTO_SUCCESS) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna ASSERT(s->is_valid_handle);
c892ebf1bef94f4f922f282c11516677c134dbe0krishna err = crypto_decrypt_prov(s->prov, s->sid,
c892ebf1bef94f4f922f282c11516677c134dbe0krishna &rsa_x509_mech, wrapped_pms_data, &s->key,
c892ebf1bef94f4f922f282c11516677c134dbe0krishna NULL, pms_data, creqp);
c892ebf1bef94f4f922f282c11516677c134dbe0krishna }
c892ebf1bef94f4f922f282c11516677c134dbe0krishna
c892ebf1bef94f4f922f282c11516677c134dbe0krishna /*
c892ebf1bef94f4f922f282c11516677c134dbe0krishna * Deal with session specific errors. We translate to
c892ebf1bef94f4f922f282c11516677c134dbe0krishna * the closest errno.
c892ebf1bef94f4f922f282c11516677c134dbe0krishna */
c892ebf1bef94f4f922f282c11516677c134dbe0krishna switch (err) {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna case CRYPTO_KEY_HANDLE_INVALID:
c892ebf1bef94f4f922f282c11516677c134dbe0krishna case CRYPTO_SESSION_HANDLE_INVALID:
c892ebf1bef94f4f922f282c11516677c134dbe0krishna s->is_valid_handle = B_FALSE;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna s->do_reauth = B_TRUE;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna rverr = EINVAL;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna break;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna case CRYPTO_PIN_EXPIRED:
c892ebf1bef94f4f922f282c11516677c134dbe0krishna case CRYPTO_PIN_LOCKED:
c892ebf1bef94f4f922f282c11516677c134dbe0krishna rverr = EACCES;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna break;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna case CRYPTO_UNKNOWN_PROVIDER:
c892ebf1bef94f4f922f282c11516677c134dbe0krishna rverr = ENXIO;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna break;
c892ebf1bef94f4f922f282c11516677c134dbe0krishna }
c892ebf1bef94f4f922f282c11516677c134dbe0krishna } else {
c892ebf1bef94f4f922f282c11516677c134dbe0krishna err = crypto_decrypt(&rsa_x509_mech, wrapped_pms_data,
c892ebf1bef94f4f922f282c11516677c134dbe0krishna privkey, NULL, pms_data, creqp);
c892ebf1bef94f4f922f282c11516677c134dbe0krishna }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais switch (err) {
c28749e97052f09388969427adf7df641cdcdc22kais case CRYPTO_SUCCESS:
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais case CRYPTO_QUEUED:
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * Finish the master secret then the rest of key material
c28749e97052f09388969427adf7df641cdcdc22kais * derivation later.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais ssl->job.kjob = creq.cr_reqid;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->job.buf = buf;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->job.buflen = allocated;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = wait_client_key_done;
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais default:
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__crypto_decrypt, int, err);
c28749e97052f09388969427adf7df641cdcdc22kais kmem_free(buf, allocated);
c892ebf1bef94f4f922f282c11516677c134dbe0krishna return (rverr);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais pmslen = pms_data->cd_length;
c28749e97052f09388969427adf7df641cdcdc22kais pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* generate master key and save it in the ssl sid structure */
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_generate_tls_ms(ssl, pms, pmslen);
c28749e97052f09388969427adf7df641cdcdc22kais if (!CRYPTO_ERR(err))
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_generate_tls_keyblock(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_generate_ssl_ms(ssl, pms, pmslen);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_generate_keyblock(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (err == CRYPTO_SUCCESS)
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = wait_change_cipher;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kmem_free(buf, allocated);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic int
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_handle_finished(ssl_t *ssl, mblk_t *mp, int msglen)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais int err;
c28749e97052f09388969427adf7df641cdcdc22kais size_t finish_len;
c28749e97052f09388969427adf7df641cdcdc22kais int hashcompare;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->msg.type == finished);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->hs_waitstate == wait_finished);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl))
c28749e97052f09388969427adf7df641cdcdc22kais finish_len = TLS_FINISHED_SIZE;
c28749e97052f09388969427adf7df641cdcdc22kais else
c28749e97052f09388969427adf7df641cdcdc22kais finish_len = KSSL_SSL3_FIN_MSGLEN;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (msglen != finish_len) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, illegal_parameter);
c28749e97052f09388969427adf7df641cdcdc22kais return (EBADMSG);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais hashcompare = bcmp(mp->b_rptr, ssl->hs_hashes.tlshash,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk finish_len);
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais hashcompare = bcmp(mp->b_rptr, &ssl->hs_hashes, finish_len);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* The handshake hashes should be computed by now */
c28749e97052f09388969427adf7df641cdcdc22kais if (hashcompare != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, handshake_failure);
c28749e97052f09388969427adf7df641cdcdc22kais return (EBADMSG);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += msglen;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = idle_handshake;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->resumed == B_TRUE) {
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_change_cipher_specs(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_finished(ssl, 0);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kssl_cache_sid(&ssl->sid, ssl->kssl_entry);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais#define KSSL2_CH_MIN_RECSZ (9)
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/*
c28749e97052f09388969427adf7df641cdcdc22kais * This method is needed to handle clients which send the
c28749e97052f09388969427adf7df641cdcdc22kais * SSLv2/SSLv3 handshake for backwards compat with SSLv2 servers.
c28749e97052f09388969427adf7df641cdcdc22kais * We are not really doing SSLv2 here, just handling the header
c28749e97052f09388969427adf7df641cdcdc22kais * and then switching to SSLv3.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kaisint
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_handle_v2client_hello(ssl_t *ssl, mblk_t *mp, int recsz)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *recend;
c28749e97052f09388969427adf7df641cdcdc22kais int err;
c28749e97052f09388969427adf7df641cdcdc22kais SSL3AlertDescription desc = illegal_parameter;
c28749e97052f09388969427adf7df641cdcdc22kais uint_t randlen;
c28749e97052f09388969427adf7df641cdcdc22kais uint_t sidlen;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri uint_t cslen;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *suitesp;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *rand;
c28749e97052f09388969427adf7df641cdcdc22kais uint_t i, j;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t suite, selected_suite;
c28749e97052f09388969427adf7df641cdcdc22kais int ch_recsz = KSSL2_CH_MIN_RECSZ;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal boolean_t suite_found = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mp->b_wptr >= mp->b_rptr + recsz);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->hs_waitstate == wait_client_hello);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->resumed == B_FALSE);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (recsz < ch_recsz) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE2(kssl_err__reclen_less_than_minimum,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal int, recsz, int, ch_recsz);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais MD5Init(&ssl->hs_md5);
c28749e97052f09388969427adf7df641cdcdc22kais SHA1Init(&ssl->hs_sha1);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kssl_update_handshake_hashes(ssl, mp->b_rptr, recsz);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais recend = mp->b_rptr + recsz;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (*mp->b_rptr != 1) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE1(kssl_err__invalid_version, uint_t, *mp->b_rptr);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += 3;
c28749e97052f09388969427adf7df641cdcdc22kais
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri cslen = ((uint_t)mp->b_rptr[0] << 8) + (uint_t)mp->b_rptr[1];
c28749e97052f09388969427adf7df641cdcdc22kais sidlen = ((uint_t)mp->b_rptr[2] << 8) + (uint_t)mp->b_rptr[3];
c28749e97052f09388969427adf7df641cdcdc22kais randlen = ((uint_t)mp->b_rptr[4] << 8) + (uint_t)mp->b_rptr[5];
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri if (cslen % 3 != 0) {
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri DTRACE_PROBE1(kssl_err__cipher_suites_len_error, uint_t, cslen);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais if (randlen < SSL_MIN_CHALLENGE_BYTES ||
c28749e97052f09388969427adf7df641cdcdc22kais randlen > SSL_MAX_CHALLENGE_BYTES) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_err__randlen_out_of_range,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk uint_t, randlen);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += 6;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri ch_recsz += cslen + sidlen + randlen;
c28749e97052f09388969427adf7df641cdcdc22kais if (recsz != ch_recsz) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE2(kssl_err__invalid_message_len_sum,
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal int, recsz, int, ch_recsz);
c28749e97052f09388969427adf7df641cdcdc22kais goto falert;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais suitesp = mp->b_rptr;
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri rand = suitesp + cslen + sidlen;
c28749e97052f09388969427adf7df641cdcdc22kais if (randlen < SSL3_RANDOM_LENGTH) {
c28749e97052f09388969427adf7df641cdcdc22kais bzero(ssl->client_random, SSL3_RANDOM_LENGTH);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais bcopy(rand, &ssl->client_random[SSL3_RANDOM_LENGTH - randlen],
c28749e97052f09388969427adf7df641cdcdc22kais randlen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 0; i < ssl->kssl_entry->kssl_cipherSuites_nentries; i++) {
c28749e97052f09388969427adf7df641cdcdc22kais suite = ssl->kssl_entry->kssl_cipherSuites[i];
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri for (j = 0; j < cslen; j += 3) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE2(kssl_cipher_suite_check_v2,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, suite,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (uint16_t)((suitesp[j+1] << 8) + suitesp[j+2]));
c28749e97052f09388969427adf7df641cdcdc22kais if (suitesp[j] != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais continue;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check for regular (true) cipher suite. */
c28749e97052f09388969427adf7df641cdcdc22kais if (suitesp[j + 1] == ((suite >> 8) & 0xff) &&
c28749e97052f09388969427adf7df641cdcdc22kais suitesp[j + 2] == (suite & 0xff)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE1(kssl_cipher_suite_found,
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal uint16_t, suite);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal suite_found = B_TRUE;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal selected_suite = suite;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /* Check for SCSV. */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suitesp[j + 1] == ((SSL_SCSV >> 8) & 0xff) &&
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal suitesp[j + 2] == (SSL_SCSV & 0xff)) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal DTRACE_PROBE(kssl_scsv_found);
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->secure_renegotiation = B_TRUE;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal /*
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * If we got cipher suite match and SCSV or went
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * through the whole list of client cipher suites
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * (hence we know if SCSV was present or not) we
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal * can terminate the cycle now.
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal */
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suite_found &&
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal (ssl->secure_renegotiation || (i > 0)))
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal break;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (suite_found)
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais }
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (!suite_found) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE(kssl_err__no_SSLv2_cipher_suite);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal /*
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * If there is no fallback point terminate the handshake with
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal * SSL alert otherwise return with SSL_MISS.
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal */
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal if (ssl->kssl_entry->ke_fallback_head == NULL) {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal DTRACE_PROBE(kssl_no_fallback);
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal desc = handshake_failure;
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal goto falert;
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal } else {
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal return (SSL_MISS);
65d184575ba5adcc532b970fc99d2f67e2df7af6Vladimir Kotal }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr = recend;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais for (i = 0; i < cipher_suite_defs_nentries; i++) {
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal if (selected_suite == cipher_suite_defs[i].suite) {
c28749e97052f09388969427adf7df641cdcdc22kais break;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(i < cipher_suite_defs_nentries);
c28749e97052f09388969427adf7df641cdcdc22kais
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->pending_cipher_suite = selected_suite;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->pending_malg = cipher_suite_defs[i].malg;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->pending_calg = cipher_suite_defs[i].calg;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->pending_keyblksz = cipher_suite_defs[i].keyblksz;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->sid.cached == B_FALSE);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais (void) random_get_pseudo_bytes(ssl->sid.session_id,
c28749e97052f09388969427adf7df641cdcdc22kais SSL3_SESSIONID_BYTES);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->sid.client_addr = ssl->faddr;
11d0a659fdd288190c17d8600ecd218e9a9b546dVladimir Kotal ssl->sid.cipher_suite = selected_suite;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_server_hello(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais err = kssl_send_certificate_and_server_hello_done(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais if (err != 0) {
c28749e97052f09388969427adf7df641cdcdc22kais return (err);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_COUNTER(full_handshakes, 1);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = wait_client_key;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (0);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisfalert:
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, desc);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais return (EBADMSG);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/*
c28749e97052f09388969427adf7df641cdcdc22kais * Call back routine for asynchronously submitted RSA decryption jobs.
51144063f3afc862c6cb3f54fd4341724f765075Krishna Yenduri * This routine retrieves the pre-master secret, and proceeds to generate
c28749e97052f09388969427adf7df641cdcdc22kais * the remaining key materials.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_cke_done(void *arg, int status)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais int ret = 0;
c28749e97052f09388969427adf7df641cdcdc22kais uchar_t *pms;
c28749e97052f09388969427adf7df641cdcdc22kais size_t pmslen;
c28749e97052f09388969427adf7df641cdcdc22kais crypto_data_t *pms_data;
c28749e97052f09388969427adf7df641cdcdc22kais kssl_cmd_t kssl_cmd = KSSL_CMD_NONE;
c28749e97052f09388969427adf7df641cdcdc22kais ssl_t *ssl = (ssl_t *)arg;
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *alertmp;
c28749e97052f09388969427adf7df641cdcdc22kais kssl_callback_t cbfn;
c28749e97052f09388969427adf7df641cdcdc22kais void *cbarg;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mutex_enter(&ssl->kssl_lock);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->msg.type == client_key_exchange);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl->hs_waitstate == wait_client_key_done);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (status != CRYPTO_SUCCESS) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, decrypt_error);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_cmd = KSSL_CMD_SEND;
c28749e97052f09388969427adf7df641cdcdc22kais goto out;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais pms_data = (crypto_data_t *)(ssl->job.buf);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(pms_data != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais pmslen = pms_data->cd_length;
c28749e97052f09388969427adf7df641cdcdc22kais pms = kssl_rsa_unwrap((uchar_t *)pms_data->cd_raw.iov_base, &pmslen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* generate master key and save it in the ssl sid structure */
c28749e97052f09388969427adf7df641cdcdc22kais if (IS_TLS(ssl)) {
c28749e97052f09388969427adf7df641cdcdc22kais ret = kssl_generate_tls_ms(ssl, pms, pmslen);
c28749e97052f09388969427adf7df641cdcdc22kais if (!CRYPTO_ERR(ret))
c28749e97052f09388969427adf7df641cdcdc22kais ret = kssl_generate_tls_keyblock(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais } else {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_generate_ssl_ms(ssl, pms, pmslen);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_generate_keyblock(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ret == CRYPTO_SUCCESS)
c28749e97052f09388969427adf7df641cdcdc22kais ssl->hs_waitstate = wait_change_cipher;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisout:
c28749e97052f09388969427adf7df641cdcdc22kais kmem_free(ssl->job.buf, ssl->job.buflen);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->job.kjob = 0;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->job.buf = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->job.buflen = 0;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ssl->activeinput = B_FALSE;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais cbfn = ssl->cke_callback_func;
c28749e97052f09388969427adf7df641cdcdc22kais cbarg = ssl->cke_callback_arg;
c28749e97052f09388969427adf7df641cdcdc22kais alertmp = ssl->alert_sendbuf;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->alert_sendbuf = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson /* dropped by callback when it has completed */
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson ssl->async_ops_pending++;
c28749e97052f09388969427adf7df641cdcdc22kais mutex_exit(&ssl->kssl_lock);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Now call the callback routine */
c28749e97052f09388969427adf7df641cdcdc22kais (*(cbfn))(cbarg, alertmp, kssl_cmd);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/*
c28749e97052f09388969427adf7df641cdcdc22kais * Returns the first complete contiguous record out of rec_ass_head
c28749e97052f09388969427adf7df641cdcdc22kais * The record is returned in a separate contiguous mblk, rec_ass_head is
c28749e97052f09388969427adf7df641cdcdc22kais * left pointing to the next record in the queue.
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * The output looks as follows:
c28749e97052f09388969427adf7df641cdcdc22kais *
c28749e97052f09388969427adf7df641cdcdc22kais * |--------|---------- .... -----|<---------->|<----------->|--- ... ---|
c28749e97052f09388969427adf7df641cdcdc22kais * ^ ^ ^ mac_size pad_size ^
c28749e97052f09388969427adf7df641cdcdc22kais * | |___ b_rptr b_wptr __| |
c28749e97052f09388969427adf7df641cdcdc22kais * | |
c28749e97052f09388969427adf7df641cdcdc22kais * |___ db_base db_lim ___|
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kaismblk_t *
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_get_next_record(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais mblk_t *mp, *retmp;
c28749e97052f09388969427adf7df641cdcdc22kais int rhsz = SSL3_HDR_LEN;
c28749e97052f09388969427adf7df641cdcdc22kais uint16_t rec_sz;
c28749e97052f09388969427adf7df641cdcdc22kais int mpsz, total_size;
c28749e97052f09388969427adf7df641cdcdc22kais SSL3ContentType content_type;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(MUTEX_HELD(&ssl->kssl_lock));
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mp = ssl->rec_ass_head;
c28749e97052f09388969427adf7df641cdcdc22kais if (mp == NULL)
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /* Fast path: when mp has at least a complete record */
c28749e97052f09388969427adf7df641cdcdc22kais if (MBLKL(mp) < rhsz) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_mblk__incomplete_header,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk mblk_t *, mp);
c28749e97052f09388969427adf7df641cdcdc22kais /* Not even a complete header in there yet */
c28749e97052f09388969427adf7df641cdcdc22kais if (msgdsize(mp) < rhsz) {
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (!pullupmsg(mp, rhsz)) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, internal_error);
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(mp);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais content_type = (SSL3ContentType)mp->b_rptr[0];
c28749e97052f09388969427adf7df641cdcdc22kais if (content_type == content_handshake_v2) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_mblk__ssl_v2, mblk_t *, mp);
c28749e97052f09388969427adf7df641cdcdc22kais rec_sz = (uint16_t)mp->b_rptr[1];
c28749e97052f09388969427adf7df641cdcdc22kais rhsz = 2;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE1(kssl_mblk__ssl_v3, mblk_t *, mp);
c28749e97052f09388969427adf7df641cdcdc22kais uint8_t *rec_sz_p = (uint8_t *)mp->b_rptr + 3;
c28749e97052f09388969427adf7df641cdcdc22kais rec_sz = BE16_TO_U16(rec_sz_p);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * same tests as above. Only rare very fragmented cases will
c28749e97052f09388969427adf7df641cdcdc22kais * incur the cost of msgdsize() and msgpullup(). Well formed
c28749e97052f09388969427adf7df641cdcdc22kais * packets will fall in the most frequent fast path.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais total_size = rhsz + rec_sz;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais /*
c28749e97052f09388969427adf7df641cdcdc22kais * Missing: defensive against record fabricated with longer than
c28749e97052f09388969427adf7df641cdcdc22kais * MAX record length.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kais if (MBLKL(mp) < total_size) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE2(kssl_mblk__smaller_than_total_size,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk mblk_t *, mp, int, total_size);
c28749e97052f09388969427adf7df641cdcdc22kais /* Not a complete record yet. Keep accumulating */
c28749e97052f09388969427adf7df641cdcdc22kais if (msgdsize(mp) < total_size) {
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (!pullupmsg(mp, total_size)) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, internal_error);
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(mp);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais mpsz = MBLKL(mp); /* could've changed after the pullup */
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (mpsz > total_size) {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE2(kssl_mblk__bigger_than_total_size,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk mblk_t *, mp, int, total_size);
c28749e97052f09388969427adf7df641cdcdc22kais /* gotta allocate a new block */
c28749e97052f09388969427adf7df641cdcdc22kais if ((retmp = dupb(mp)) == NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais kssl_send_alert(ssl, alert_fatal, internal_error);
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(mp);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_head = ssl->rec_ass_tail = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais return (NULL);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais retmp->b_wptr = retmp->b_rptr + total_size;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_rptr += total_size;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_head = mp;
c28749e97052f09388969427adf7df641cdcdc22kais } else {
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk DTRACE_PROBE2(kssl_mblk__equal_to_total_size,
51dd2c77f06e5663c28bd4f7a760cae4cf159e79vk mblk_t *, mp, int, total_size);
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(mpsz == total_size);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_head = mp->b_cont;
c28749e97052f09388969427adf7df641cdcdc22kais mp->b_cont = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais retmp = mp;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais /* Adjust the tail */
c28749e97052f09388969427adf7df641cdcdc22kais if ((mp = ssl->rec_ass_tail = ssl->rec_ass_head) != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais for (; mp->b_cont != NULL; mp = mp->b_cont) {
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_tail = mp->b_cont;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais return (retmp);
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_mblksfree(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->rec_ass_head != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(ssl->rec_ass_head);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_head = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->rec_ass_tail = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->msg.head != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(ssl->msg.head);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais ssl->msg.head = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais ssl->msg.tail = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->handshake_sendbuf != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(ssl->handshake_sendbuf);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->handshake_sendbuf = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais if (ssl->alert_sendbuf != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais freemsg(ssl->alert_sendbuf);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->alert_sendbuf = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kaisstatic void
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_specsfree(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
c28749e97052f09388969427adf7df641cdcdc22kais KSSLCipherSpec *spec = &ssl->spec[KSSL_READ];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->cipher_ctx != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais crypto_cancel_ctx(spec->cipher_ctx);
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_ctx = 0;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais spec = &ssl->spec[KSSL_WRITE];
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais if (spec->cipher_ctx != NULL) {
c28749e97052f09388969427adf7df641cdcdc22kais crypto_cancel_ctx(spec->cipher_ctx);
c28749e97052f09388969427adf7df641cdcdc22kais spec->cipher_ctx = 0;
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais}
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais/*
c28749e97052f09388969427adf7df641cdcdc22kais * Frees the ssl structure (aka the context of an SSL session).
c28749e97052f09388969427adf7df641cdcdc22kais * Any pending crypto jobs are cancelled.
c28749e97052f09388969427adf7df641cdcdc22kais * Any initiated crypto contexts are freed as well.
c28749e97052f09388969427adf7df641cdcdc22kais */
c28749e97052f09388969427adf7df641cdcdc22kaisvoid
c28749e97052f09388969427adf7df641cdcdc22kaiskssl_free_context(ssl_t *ssl)
c28749e97052f09388969427adf7df641cdcdc22kais{
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson crypto_req_id_t reqid;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
c28749e97052f09388969427adf7df641cdcdc22kais ASSERT(ssl != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais if (!(MUTEX_HELD(&ssl->kssl_lock))) {
c28749e97052f09388969427adf7df641cdcdc22kais /* we're coming from an external API entry point */
c28749e97052f09388969427adf7df641cdcdc22kais mutex_enter(&ssl->kssl_lock);
c28749e97052f09388969427adf7df641cdcdc22kais }
c28749e97052f09388969427adf7df641cdcdc22kais
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson /*
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * Cancel any active crypto request and wait for pending async
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * operations to complete. We loop here because the async thread
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * might submit a new cryto request.
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson */
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson do {
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson if (ssl->job.kjob != NULL) {
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson /*
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * Drop the lock before canceling the request;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * otherwise we might deadlock if the completion
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson * callback is running.
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson */
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson reqid = ssl->job.kjob;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson mutex_exit(&ssl->kssl_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson crypto_cancel_req(reqid);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson mutex_enter(&ssl->kssl_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson /* completion callback might have done the cleanup */
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson if (ssl->job.kjob != NULL) {
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson kmem_free(ssl->job.buf, ssl->job.buflen);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson ssl->job.kjob = 0;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson ssl->job.buf = NULL;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson ssl->job.buflen = 0;
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson }
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson }
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson while (ssl->async_ops_pending > 0)
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson cv_wait(&ssl->async_cv, &ssl->kssl_lock);
dd49f125507979bb2ab505a8daf2a46d1be27051Anders Persson } while (ssl->job.kjob != NULL);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kssl_mblksfree(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais kssl_specsfree(ssl);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais KSSL_ENTRY_REFRELE(ssl->kssl_entry);
c28749e97052f09388969427adf7df641cdcdc22kais ssl->kssl_entry = NULL;
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais mutex_exit(&ssl->kssl_lock);
c28749e97052f09388969427adf7df641cdcdc22kais
c28749e97052f09388969427adf7df641cdcdc22kais kmem_cache_free(kssl_cache, ssl);
c28749e97052f09388969427adf7df641cdcdc22kais}